Golf: Häufigkeit der Zeichen in einer Textdatei

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Dobi
User
Beiträge: 31
Registriert: Mittwoch 28. September 2011, 17:04

Hallo zusammen,

gerade bin ich am Golfen. ;)
Wenn in meiner Eingabedatei beispielsweise das hier steht:

Code: Alles auswählen

Python ist eine universelle, üblicherweise interpretierte höhere Programmiersprache. Ihre Entwurfsphilosophie betont Programmlesbarkeit. Ihr Gebrauch von Einrückung zur Blockbegrenzung unterscheidet sie von den meisten verbreiteten Programmiersprachen.
möchte ich diese Ausgabe erhalten:

Code: Alles auswählen

e 37
r 27
  24
i 17
n 17
t 14
h 12
s 11
o 10
a 7
c 7
m 7
u 7
b 6
g 6
l 6
p 5
v 4
P 4
. 3
k 3
E 2
I 2
d 2
w 2
z 2
ü 2
, 1
B 1
G 1
f 1
ö 1
y 1
Da ich Python aber erst seit ein paar Wochen lerne, vermute ich natürlich, dass es auch in wesentlich weniger Zeichen geht als ich benötigt hab:

Code: Alles auswählen

d=open('komischer_langer_Dateiname_dessen_Zeichen_aber_nicht_mitzaehlen.txt','r').read()
print(''.join((k+' '+str(v)+'\n')for k,v in sorted(dict((c,d.count(c))for c in d).items(),reverse=True,key=lambda x:x[1])))
Also, habt ihr Vorschläge, wo man da noch was sparen könnte? :)

Gruß
Dobi
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hab jetzt nicht gezählt, aber eleganter ist dieses:

Code: Alles auswählen

from collections import Counter
with open("komischer_langer_Dateiname_dessen_Zeichen_aber_nicht_mitzaehlen.txt", "r") as f:
    print("\n".join("{} {}".format(*item) for item in Counter(f.read()).most_common()))
Edit: Ok, da wir Golf spielen, hier die verkrüppelte Variante:

Code: Alles auswählen

import collections as c
with open("komischer_langer_Dateiname_dessen_Zeichen_aber_nicht_mitzaehlen.txt", "r") as f:
    print("\n".join("{} {}".format(*t) for t in c.Counter(f.read()).most_common()))
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
Dobi
User
Beiträge: 31
Registriert: Mittwoch 28. September 2011, 17:04

Nicht gezählt und deine ungekürzte Variante war zufällig schon genau ein Zeichen kürzer als meins. Nicht schlecht. :D
Den Counter kannte ich noch gar nicht, und mit Format ist es wirklich schicker. Wieder was gelernt, Danke.
PS: Die Leerzeichen nach den schliessenden Klammern und nach dem Komma kann man übrigens noch weglassen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Fürs nächste golfen würde ich mal vorschlagen, das Einlesen der Daten wegzulassen. Letztlich sieht das immer gleich aus und erzeugt fürs Zählen eher Overhead. Man könnte definieren, dass der Text an einen Namen gebunden zur Verfügung steht, etwa `t`, um es schön kurz zu lassen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
/me
User
Beiträge: 3560
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Dobi hat geschrieben:Also, habt ihr Vorschläge, wo man da noch was sparen könnte? :)
Hyperion hat ja schon eine sehr schöne kurze und pythonische Lösung geliefert. Basierend auf deinem Ansatz kann man, wenn t den Text enthält, Folgendes produzieren:

Code: Alles auswählen

print('\n'.join((k+' '+str(v))for k,v in sorted({c:t.count(c) for c in t}.items(),key=lambda z:z[1])[::-1]))
Benutzeravatar
Dobi
User
Beiträge: 31
Registriert: Mittwoch 28. September 2011, 17:04

Ah, auch hübsch. Die Geschweiften klammern sind hier natürlich besser als dict auszuschreiben. Auf [::-1] zum umdrehen hätte ich allerdings auch selbst kommen können, sollen, müssen. ; )
Pythonische Lösungen sind aber natürlich die, die ich langfristig hinbekommen möchte (nicht nur beim Golfen).
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Hab nur 2.7 zur Hand:

Code: Alles auswählen

s=open('.....').read()
print '\n'.join(b+' %s'%a for a,b in sorted((s.count(i),i) for i in set(s))[::-1])
Antworten