ubuntuusers.de

Programmierwettbewerb des Linux-Magazins: Perl, Java, Python, Lisp, Smalltalk

Status: Ungelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

UbuntuFlo Team-Icon

Avatar von UbuntuFlo

Anmeldungsdatum:
8. Februar 2006

Beiträge: 12317

Wohnort: /home/flo

Linux Magazin schreibt:

Das Linux-Magazin zeigt unter dem Titel "Sprachwahl", wie Programmier-Profis Aufgaben in PHP, Perl, Python und Java lösen.

Die Redaktion lässt Größen wie Zeev Suravski, James Gosling und Randal L. Schwartz vorprogrammieren, um von ihnen zu lernen. Daneben zeigen die Oldtimer-Sprachen Smalltalk und Lisp, dass sie noch lange nicht zum alten Eisen gehören.

Die Sonderseite stellt die gesammelten Code-Listings sowie die Spezifikation der Aufgaben online zur Verfügung.

Wer kennt noch weitere Python-Kniffe? Wer kann die Java-Lösung kürzen oder die Perl-Variante effizienter gestalten? Welche anderen Programmiersprachen lösen das Problem vielleicht noch eleganter?

Daneben sind die Leser aufgerufen, unter redaktion@linux-magazin.de eigene Lösungsvorschläge einzureichen. Einsendeschluss ist der 30. September. Die Redaktion prämiert die kreativsten drei Lösungen mit je einem Fachbuch.

FLO

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Die Python-Lösung ist ja mal scheiße...

Und nebenbei ist sämtliche Einrückung weg.

PrairieDog

Anmeldungsdatum:
16. Februar 2006

Beiträge: 870

Wie, keine Benchmarks? Der Lesbarkeits-King steht mit Perl doch ohnehin fest. 🐸

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17625

Wohnort: Berlin

listing2.java, EndNotes.java, vermißt eine Datei sample-data.txt, die auf der Downloadseite nicht auftaucht.

listing5.java, BibReorder.java, endet mitten in einem Bezeichner:

1
	HashMap<String, BibliographyTag> tags = new HashMap<String, Bib

Beide sehen aus, als kämen sie aus der Mitte einer Email, da die Umbrüche keine Rücksicht auf den Kontext nehmen.

Greebo

Avatar von Greebo

Anmeldungsdatum:
21. November 2006

Beiträge: 3443

Wohnort: 97070 Würzburg

Ich hab heute einen Kneipentag gehabt und bin insofern wirklich weit davon entfernt ernsthaft Code kritisieren zu können, aber Java Code der Sachen wie

import java.util.*;
import java.util.ArrayList;

enthält ist wohl entweder eine Verschwörung oder einfach nur unheimlich schwachsinniger schlampiger Mist. Für ein Wettbewerbsbild jedenfalls ungeeignet und irgendwie auch (in meiner Weinlaune) extrem polemisch absichtlich missgestaltet. Sorry ich hatte vom Linux Magazin bis gerade keine Meinung, jetzt entwickelt sich eine.

Wh1sper

Avatar von Wh1sper

Anmeldungsdatum:
22. Mai 2007

Beiträge: Zähle...

Greebo schrieb: aber Java Code der Sachen wie

import java.util.*;
import java.util.ArrayList;

enthält ist wohl entweder eine Verschwörung oder einfach nur unheimlich schwachsinniger schlampiger Mist. Für ein Wettbewerbsbild jedenfalls ungeeignet und irgendwie auch (in meiner Weinlaune) extrem polemisch absichtlich missgestaltet. Sorry ich hatte vom Linux Magazin bis gerade keine Meinung, jetzt entwickelt sich eine.

Der Code ist nicht vom Linux-Magazin, sondern von ausgewiesenen Experten eingesandt worden. Experten sind allerdings auch nur Menschen. Aber du hast natürlich recht, das hätte auffallen müssen, aber es schadet ja nicht.

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Ich hab das Gefühl, dass ausser Randal Schwartz keiner was ordentliche eingeschickt hat 😀

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4695

Wohnort: Berlin

Die Vorgabe scheint gewesen zu sein: Hackt mal eben schnell was zusammen. So sieht jedenfalls die Python-Lösung mit der quadratischen Laufzeit von nodups() und ohne jegliche Fehlerbehandlung aus.

Der Aufruf nach Einsendungen hat auch einen komischen Beigeschmack. Die wollen die "kreativste" Lösung belohnen ─ dann fällt es ja schon einmal weg das ganze sauber und ohne komische Tricks und Kniffe zu implementieren. Lesbar und robust fänd ich irgendwie wichtiger.

Die Spezifikation ist auch nicht ganz fehlerfrei: Werden die Fussnoten nun mit @footnote: oder @footnotes: eingeleitet?

PrairieDog

Anmeldungsdatum:
16. Februar 2006

Beiträge: 870

Ich hab grad geantwortet und mein Posting wieder gelöscht. Daraufhin verabschiedete sich der Thread auf die letzte Seite. Dieses Posting solls wieder gutmachen. *amen*

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Hier mal ne ordentliche Python-Lösung:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env python
#-*- coding: utf-8 -*-
# Copyright (c) 2007 Jens Kadenbach <j.kadenbach@gmx.de>
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar. See
# http://sam.zoy.org/wtfpl/COPYING for more details.

from __future__ import with_statement

import re
from cStringIO import StringIO
from optparse import OptionParser
from itertools import imap, takewhile, count
from functools import partial

__version__ = '0.1'

SAMPLE = StringIO('''A great brown fox [13] jumped of a pile of lorem ipsum [4],
[7]. He met with a silver penguin, browsing the Linux Kernel
Mailinglist [3]. They debated whether to start a C-program with
"main (int argc, char **argv)" or with "main (int argc, char *argv[])".
Square brackets annoyed them [9999]. Multiple references exist [4].
@footnote:
[13] Al Fabetus: "On characters and animals", 1888, self published.
[4] Lorem Ipsum, <a href="http://link.org/Lorem_Ipsum">Web Link</a>
[9999] Annoying Link.
[7] B. Fox: "More on Blind Text".
[3] Linux Kernel Maintainers: LKML
''')

FOOTSPLIT = '@footnote:\n'
NUMBER = re.compile(r'\[(\d+)\]')

def _parse_args():
    parser = OptionParser(usage='%prog [options] FILE', version=__version__,
                          description=''
                          "Does nothing")
    parser.add_option('-t', '--test',
                      help='use test file', action="store_true", dest='test')
    parser.add_option('-a', help='order footnotes',
                       action="store_true", dest='foot')
    parser.set_defaults(test=False, foot=False)
    return parser.parse_args()

def as_num(line):
    """ [3] Linux Kernel Maintainers: LKML
        - > 3
    """ 
    try:
        start, _ = line[1:].split(']', 1)
        return int(start)
    except ValueError:
        # bad line, ignore it
        return None

# iterator that ends when it encounters FOOTSPLIT
def _end(l) : return not l == FOOTSPLIT
extract_body = partial(takewhile, _end)

def sort_footnotes(fh, sort_footer):
    body, foot = extract_body(fh), fh
    notes = {}
    c = count(1)
    def replace_num(match):
        """ return new index and assign
            it to current index in notes
        """
        n = int(match.group(1))
        if not n in notes:
            i = c.next()
            notes[n] = i
        else:
            i = notes[n]
        return "[%d]" % i

    for line in body:
        yield NUMBER.sub(replace_num, line)

    # orig footsplit was not saved
    yield FOOTSPLIT

    mapping = dict((n, "[%d]" % (i+1)) for i, n in enumerate(notes))
    def num_in_mapping(match):
        n = int(match.group(1))
        return mapping[n]

    footer = imap(partial(NUMBER.sub, num_in_mapping), foot)
    if sort_footer:
        footer = sorted(footer, key=as_num)
    for line in footer:
            yield line


def main():
    """ The main function
    """
    options, args = _parse_args()
    try:    
        if options.test:
            fh = SAMPLE
        else:
            fh = open(args[0], 'r')
        for line in sort_footnotes(fh, options.foot):
            print line,
    finally:
        fh.close()
    
if __name__ == '__main__':
    main()

€dit: Ist fehlerhalt.

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

diesmal sortiert er richtig herum:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env python
#-*- coding: utf-8 -*-
# Copyright (c) 2007 Jens Kadenbach <j.kadenbach@gmx.de>
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms of the Do What The Fuck You Want
# To Public License, Version 2, as published by Sam Hocevar. See
# http://sam.zoy.org/wtfpl/COPYING for more details.

from __future__ import with_statement

import sys
import re
from cStringIO import StringIO
from optparse import OptionParser
from itertools import imap, takewhile, count
from functools import partial

__version__ = '0.2'

SAMPLE = StringIO('''A great brown fox [13] jumped of a pile of lorem ipsum [4],
[7]. He met with a silver penguin, browsing the Linux Kernel
Mailinglist [3]. They debated whether to start a C-program with
"main (int argc, char **argv)" or with "main (int argc, char *argv[])".
Square brackets annoyed them [9999]. Multiple references exist [4].

@footnote:

[13] Al Fabetus: "On characters and animals", 1888, self published.
[4] Lorem Ipsum, <a href="http://link.org/Lorem_Ipsum">Web
Link</a>
[9999] Annoying Link.
[7] B. Fox: "More on Blind Text".
[3] Linux Kernel Maintainers: LKML
''')

FOOTSPLIT = '@footnote:\n'
NUMBER = re.compile(r'\[(\d+)\]')

def _parse_args():
    parser = OptionParser(usage='%prog [options] FILE', version=__version__,
                          description=''
                          "Does nothing")
    parser.add_option('-t', '--test',
                      help='use test file', action="store_true", dest='test')
    parser.add_option('-a', action="store_true", dest='foot',
                      help='order footnotes in order of appearance in text')
                       
    parser.set_defaults(test=False, foot=False)
    return parser.parse_args()

def as_num(line):
    """ [3] Linux Kernel Maintainers: LKML
        - > 3
    """ 
    try:
        start, _ = line[1:].split(']', 1)
        return int(start)
    except ValueError:
        # bad line, ignore it
        return None

# iterator that ends when it encounters FOOTSPLIT
def _end(l) : return not l == FOOTSPLIT
extract_body = partial(takewhile, _end)

def create_footer_index(fh):
    notes = {}
    c = count(1)
    footer = []
    for line in fh:
        try:    
            start, content = line[1:].split(']', 1)
            num = int(start)
        except ValueError:
            # concat lines of one footer
            try:    
                footer[-1] += line
            except IndexError:
            # happens maybe on first line
                footer.append(line)
        else:   
            idx = c.next()
            notes[num] = idx
            footer.append("[%d]%s" % (idx, content))
    # back to start
    fh.seek(0)
    return notes, footer

def make_replacer(notes, sort_footer):  
    if not sort_footer:
        def replace_num(match):
            n = int(match.group(1))
            # 0 when not found
            return "[%d]" % notes.get(n, 0)
        return replace_num, None
    else:
        foot_order = {}
        c = count()
        def replace_num(match):
            n = int(match.group(1))
            new = notes.get(n, 0)
            if new not in foot_order:
                foot_order[new] = c.next()
            # 0 when not found
            return "[%d]" % new
        return replace_num, foot_order

def make_foot_sorter(foot_order):
    def order(line):
        num = as_num(line)
        try:
            return foot_order[num]
        except KeyError:
            return None
    return order

def sort_footnotes(fh, sort_footer):
    for line in extract_body(fh):
        pass
    # fh is placed in footer
    notes, footer = create_footer_index(fh)
    replace_num, foot_order = make_replacer(notes, sort_footer)

    for line in extract_body(fh):
        yield NUMBER.sub(replace_num, line)

    yield FOOTSPLIT

    if sort_footer:
        footer = sorted(footer, key=make_foot_sorter(foot_order))
    for line in footer:
        yield line
               

def main():
    """ The main function
    """
    options, args = _parse_args()
    try:    
        fh = SAMPLE if options.test else open(args[0], 'r')
        w = sys.stdout.write
        for line in sort_footnotes(fh, options.foot):
            w(line)
    finally:
        fh.close()
    
if __name__ == '__main__':
    main()

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

Boost kann zaubern. Ich habe es schon immer geahnt, aber nachdem ich boost.xpressive gesehen habe, weiß ich es.

Der Einfachheit halber werden die Fußnoten in der Reihenfolge angeordnet, wie sie im Text vorkommen, es entspricht also eigentlich nicht der Aufgabenstellung. Diese hätte es erfordert, erst einmal von hinten durch die Zeilen zu iterieren, und dafür stellt die C++-Standardbibliothek m. W. keine Funktionalität bereit. Das Programm benötigt boost.xpressive 1.36, niedrigere Versionen gehen nicht.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <fstream>
#include <map>
#include <algorithm>
#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
using namespace xpressive;
typedef map<int,string> strmap;
class replacer {
    replacer();
    strmap& footnotes;
    int& counter;
public:
    replacer(strmap& s, int& i) :
            counter(i), footnotes(s) {}
    const string& operator()(const smatch& what) const {
        int footnote_num = lexical_cast<int>(what[1]);
        string& footnote = footnotes[footnote_num];
        if (footnote.empty())
            footnote = '[' + lexical_cast<string>(counter++) + ']';
        return footnote;
    }
};

int main(int argc, char** argv) {
    if (argc != 2) {
        cerr << "Usage: " << argv[0] << " <filename>\n";
        return 1;
    }
    fstream in_file(argv[1], ifstream::in);
    if (!in_file) {
        cerr << "Error opening " << argv[1] << ".\n";
        return 1;
    }

    strmap footnotes;
    int footnote_counter = 1;
    replacer repl(footnotes, footnote_counter);
    string line;
    sregex footnote_regex = '[' >> (s1= +_d) >> ']';
    vector<string> last_lines;
    last_lines.reserve(footnote_counter-1);
    bool in_footnotes = false;
    while (getline(in_file, line)) {
        line = regex_replace(line, footnote_regex, repl);
        if (in_footnotes)
            last_lines.push_back(line);
        else
            cout << line << '\n';
        if (line == "@footnote:")
            in_footnotes = true;
    }
    sort(last_lines.begin(), last_lines.end());
    copy(last_lines.begin(), last_lines.end(), ostream_iterator<string>(cout,"\n"));
}

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4695

Wohnort: Berlin

Mein Versuch in Python: http://paste.pocoo.org/show/84357/

@Hello World: Das was Du implementiert hast, ist ja auch in der Aufgabenstellung enthalten, die Hälfte hast Du also umgesetzt. ☺

UbuntuFlo Team-Icon

(Themenstarter)
Avatar von UbuntuFlo

Anmeldungsdatum:
8. Februar 2006

Beiträge: 12317

Wohnort: /home/flo

Kaum hielten die ersten Abonnenten das Linux-Magazin 10/2008 in Händen, füllten sich die Postfächer der Redaktion: Das Titelthema "Sprachwahl - Programmier-Päpste lösen und kommentieren vorgegebene Aufgaben" provozierte Fragen, Kritik und Anregungen - und außerdem einiges an selbstgeschriebenem Code, von Python über Ruby bis hin zu C++.

Auch auf ein Problem in Python wird eingegangen. Außerdem gibt es ein Video über die Djangolösung. Linux-Magazin

FLO

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

Autsch. So etwas hier tut ja einfach nur weh:

1
2
3
4
5
6
def nodups(lst):
  new = []
  for x in lst:
    if x not in new:
      new.append(x)
  return new

Wie wär's mit

1
2
def nodups(lst):
    return list(set(lst))

*Kopfschüttel*

Antworten |