Open Source im professionellen Einsatz

Newsletter abonnieren
Seite durchsuchen

HEFTARCHIV | NEWS | E-BIBLIOTHEK | VIDEO | BLOGS | WHITEPAPER | EVENTS | ACADEMY | ABO | SHOP

user friendly

  Home  »  Heft & Abo  »  Heftarchiv  »  2008  »  12  »  Vom Thron gestürzt  

RSS-Feed der aktuellen News von Linux-Magazin Online Folgen Sie Linux-Magazin Online auf Twitter
Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark

Kurz: Günther, Winfried, Dirk

Perl wird seiner Rolle als knappe Programmiersprache einmal mehr gerecht: Gleich drei Lösungen teilen sich den ersten Platz bei der Programmlänge. Die Programme "Günther" (Nr. 35), "Winfried" (Nr. 33) und "Dirk" (Nr. 41) benötigen nur 17 Zeilen Code für die Aufgabe (siehe Listings 1, 2 und 3, teilweise gekürzt).

Zudem bügelten die Perl-Freunde die Schmach, die einige in der langen Laufzeit der Expertenlösung sahen, wieder aus. Deren Autor Randal L. Schwartz hatte allerdings auch explizit den Auftrag erhalten, seine Lieblingssprache stilistisch vorzustellen, und nicht sein Programm auf Leistung zu trimmen. Das erledigten die drei Perl-Skripte im Testfeld, von denen das schnellste kaum ein Zehntel der Laufzeit der ersten Perl-Lösung benötigte. Alle drei verfolgen einen ähnlichen Ansatz und kommen mit einfachen Datenstrukturen aus. Der Ruf der Skriptsprache ist wieder hergestellt.

Schnell: Rörd, Helmut, Christoph

Die schnellsten Lösungen benutzen Compilersprachen - was niemanden überrascht. Verwundert hat aber doch, dass die Ocaml-Variante "Rörd" allen anderen den Rang ablief (Nr. 50, Listing 4). Die Sprache, die objektorientierte und funktionale Elemente vereint, hatte ihre Qualitäten schon bei mehreren Programmierwettbewerben bewiesen.

Auch auf C++ hatten einige in der Redaktion gewettet. Tatsächlich ist "Christoph" (Nr. 19, Listing 5) nur eine gute Sekunde langsamer als die Ocaml-Lösung. Das Programm nutzt neben der Bibliothek "Perl Compatible Regular Expression" nur reines C++ und schafft es damit auf Platz drei.

Für eine weitere Überraschung sorgte das Java-Programm "Helmut" (Nr. 18): Es war eine Spur schneller als die C++-Variante, benötigt dafür jedoch 365 Programmzeilen. Um das Ergebnis zu erreichen, wählte der Autor einen Mittelweg zwischen objektorientiertem Programmierstil und konkreter, datennaher Implementierung. So besteht sein Code aus fünf Klassen, darunter ein abstraktes Interface und zwei alternative Umsetzungen für die Sortierstrategie. Im Gegensatz zu vielen anderen Lösungen benutzt er jedoch keine Regular Expressions, um über den Text zu iterieren. Vielmehr lädt er Textstücke in Eingabebuffer und bearbeitet diese zeichenweise. Dabei hält er die Verwaltungsstrukturen einfach in einem Hash.

Listing 4: Ocaml: Rörd (Nr.
50)

01 let sep_line = "@footnote:"
02 let ref_regexp = Str.regexp  "\[\([0-9]+\)\]"
03 
04 let ref_of_int n="[" ^ string_of_int n ^ "]"
05 
06 let output_endline c s = output_string c s;    output_char c 'n'
07 
08 exception End_of_body
09 
10 (* read body from inc, substitute references from table refs. If not in refs, evaluate unknown_ref; print to outc *)
11 let process_body inc outc refs unknown_ref =
12   let sub_ref l _ =
13     let old_n = int_of_string      (Str.matched_group 1 l) in
14     try ref_of_int (Hashtbl.find refs old_n)
15     with Not_found -> unknown_ref old_n
16   in
17   try
18     while true do
19     let l = input_line inc in
20      if l = sep_line then raise End_of_body;
21      output_endline outc
22        (Str.global_substitute ref_regexp  (sub_ref l) l)
23     done
24   with End_of_body -> output_endline outc sep_line
25 
26 (* read foots from inc, process lines *)
27 let process_foots inc process_foot  malformed_foot =
28   try
29    while true do
30      let l = input_line inc in
31      if Str.string_match ref_regexp l 0 then
32         process_foot l (int_of_string                   (Str.matched_group 1 l))
33      else malformed_foot l
34    done
35   with End_of_file -> ()
36 
37 (* insert a new reference for old_n into   refs and return the new n *)
38 let insert_ref refs old_n =
39   let n = Hashtbl.length refs + 1 in
40   Hashtbl.add refs old_n n;
41   n
42 
43 (* reorder foots by appearance in body *)
44 let renumber_by_body inc outc =
45   let refs = Hashtbl.create 1000000 in
46   let new_ref old_n = ref_of_int (insert_ref refs old_n) in
47   process_body inc outc refs new_ref;
48   let foots = Array.make              (Hashtbl.length refs) None in
49   let add_foot l old_n =
50     try
51       let n = Hashtbl.find refs old_n in
52       foots.(n-1) <- Some (Str.          string_after l (Str.match_end ()))
53     with
54       Not_found -> prerr_endline        ("unreferenced footnote: " ^ l)
55   and prerr_malformed l = prerr_endline        ("malformed footnote: " ^ l) in
56   process_foots inc add_foot         prerr_malformed;
57   for i = 1 to Array.length foots do
58     output_string outc (ref_of_int (i));
59     match foots.(i-1) with
60       None -> output_endline outc "Missing"
61     | Some l -> output_endline outc l
62   done
63 
64 (* renumber references by original order *)
65 let renumber_by_foots inc outc =
66   while input_line inc<>sep_line do () done;
67   let refs = Hashtbl.create 1000000 in
68   let add_foot_ref _ old_n =
69     if not (Hashtbl.mem refs old_n) then      ignore (insert_ref refs old_n)
70   in
71   process_foots inc add_foot_ref ignore;
72   seek_in inc 0;
73   process_body inc outc refs     (function _ -> "[?]");
74   let print_foot l old_n =
75     let n = Hashtbl.find refs old_n in
76     output_string outc (ref_of_int n);
77     output_endline outc (Str.string_after l (Str.match_end ()))
78   in
79   process_foots inc print_foot    (output_endline outc)
80 
81 (* renumber footnote references *)
82 let renumber by_foots =
83   if by_foots then renumber_by_foots else renumber_by_body
84 
85 (* process options and input files *)
86 let main () =
87   if Array.length Sys.argv > 1 then
88     let by_foots = ref false in
89     let do_file f =
90       let c = open_in f in
91       (try renumber !by_foots c stdout           with e -> close_in c; raise e);
92       close_in c
93     in
94     Arg.parse [("-f", Arg.Set by_foots,
95               "Renumber by original order")]
96      do_file "Usage: footnotes [OPT] [file]"
97   else renumber_by_body stdin stdout;;
98 main ()

Listing 5: C++: Christoph (Nr.
19)

01 #include <fstream>
02 #include <iostream>
03 #include <pcrecpp.h>
04 #include <tr1/unordered_map>
05 
06 pcrecpp::RE re_ref("^\[(\d+)\]");
07 pcrecpp::RE re_txt("(.*?)\[(\d+)\]");
08 
09 void process(char const * filename) {
10   std::ifstream file(filename);
11   std::string line;
12   while (getline(file, line) and
13          line != "@footnote:");
14   std::tr1::unordered_map<int, int> dict;
15   int counter = 1;
16   while (getline(file, line)) {
17     int number = -1;
18     if (re_ref.PartialMatch(line, &amp;number))
19       dict[number] = counter++;
20   }
21 
22   file.clear(); file.seekg(0);
23   while (getline(file, line)) {
24     pcrecpp::StringPiece input(line);
25     pcrecpp::StringPiece prefix;
26     int ref;
27     while (re_txt.
28            Consume(&amp;input,&amp;prefix,&amp;ref))
29       std::cout << prefix << "[" <<
30         (dict[ref] ? dict[ref] : ref) << "]";
31     std::cout << input << "n";
32   }
33 }
34 
35 int main(int argc, char **argv) {
36    std::ios::sync_with_stdio(false);
37    for (int i = 1; i != argc; ++i)
38       process(argv[i]);
39 }
Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark
Ähnliche Artikel
Ready, Set, Go! Google erfindet neue Programmiersprache
Wissenstransfer Aussichtsreiche Würfelkandidaten unter der Lupe
Eurovision Bot Contest Über 120 Teilnehmer stürmen beim Programmierwettbewerb die Würfelbecher
Babylon zu fünft Populäre Programmiersprachen treten gegeneinander an
Babylon zu fünft Populäre Programmiersprachen treten gegeneinander an
Parallelarbeit Bash-Skripte, die Multicore-Prozessoren auslasten
Whitepaper
Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele

Über die letzten Jahre hinweg haben sich Open Source Lösungen als fester Bestandteil des gesamten Datenintegrationsmarktes etabliert. Viele Unternehmen haben bereits das Open Source Modell für Ihre Datenintegrationsprojekte aufgegriffen. Das vorliegende White Paper illustriert anhand ausgewählter Fallstudien und Anwendungsbeispiele die Implementierung von Open Source Datenintegration in der Praxis und benennt die daraus resultierenden Vorteile.

Download PDF (Registrierung erforderlich)
The Role of Open Source in Data Integration

Obwohl in den letzten Jahren viele technische Fortschritte erzielt werden konnten, verfügen die meisten Datenintegrationsprozesse nach wie vor nur über eine sehr begrenzte Automatisierung. Das vorliegende White Paper von dem Industry Analyst Mark Madson wird zunächst ein grundlegendes Verständnis von Daten Integration vermitteln, die Vorzüge von Open Source Lösungen für Daten Integration erläutern und Ihnen professionelle Empfehlungen geben, damit Sie Ihre Integrationsjobs noch einfacher und produktiver gestalten können.

Download PDF (Registrierung erforderlich)
Kommentare (2)
von
hypnos,
20.11.2008 18:32
bild link
der bild link geht nicht wenn scripts verboten sind (noscript)
von
hypnos,
20.11.2008 18:31
bild link futsch
siehe titel