Ich bin neugierig, ob ich richtig Code Golf spiele. Ich habe es mir zur Aufgabe gemacht, ein kleines Hashing-Programm in Python in eine einzige Anweisung umzuwandeln. Ich habe angefangen mit:
from itertools import permutations
from string import ascii_lowercase
from random import sample
def test():
chars = sample(ascii_lowercase, 9)
sums = list(map(h, permutations(chars)))
if len(set(sums)) == len(sums):
print("unique results for permutations of given string")
else:
print("duplicate entries present in test results")
def h(s):
r = 0
for i in range(len(s)):
r += ord(s[i]) << (i * len(s))
return r
test()
Ich habe dann die Funktion rekursiv gemacht:
def h(s, i=0):
if i < len(s) - 1: return h(s, i+1) + ord(s[i]) << (i * len(s))
else: return ord(s[i]) << (i * len(s))
Ich habe versucht, es mit einem Lambda zu verkürzen, um den Code zu wiederholen (es hat nicht funktioniert):
def h(s, i=0, f=lambda s,i: ord(s[i]) << (i * len(s))):
if i < len(s) - 1: return h(s, i+1) + f(s,i)
else: return f(s,i)
Am Ende hatte ich ein Lambda:
h=lambda s,i=0:h(s,i+1)+ord(s[i])<<(i*len(s))if i<len(s)-1 else ord(s[i])<<(i*len(s))
Ich wollte, dass das Programm eine Aussage ist, also kam ich zuerst auf:
def test():
chars = sample(ascii_lowercase, 9)
sums = list(map((lambda s,i=0,f=lambda s,i,f:f(s,i+1,f)+ord(s[i])<<(i*len(s))if i<len(s)-1 else ord(s[i])<<(i*len(s)):f(s,i,f)), permutations(chars)))
if len(set(sums)) == len(sums):
print("unique results for permutations of given string")
else:
print("duplicate entries present in test results")
Und zum Schluss kam ich mit:
print((lambda x=list(map((lambda s,i=0,f=lambda s,i,f:f(s,i+1,f)+ord(s[i])<<(i*len(s))if i<len(s)-1 else ord(s[i])<<(i*len(s)):f(s,i,f)), permutations(sample(ascii_lowercase, 9)))): "unique results for permutations of given string" if len(set(x)) == len(x) else "duplicate entries present in test results")())
Werden so Codegolf-Probleme gelöst? Ich habe so etwas noch nie gemacht, also möchte ich jetzt nur wissen, ob ich es richtig mache.
Änderung: Dieses Programm erledigt die ganze Arbeit für Sie; Ich werde hier also auf die Funktion verweisen: Als Eingabe nimmt das Programm alle Permutationen eines gegebenen Strings auf; Hier besteht die Zeichenfolge aus neun zufällig ausgewählten Zeichen ascii_lowercase
. Die Ausgabe ist eine vom Menschen lesbare Zeichenfolge, die definiert, ob das Ergebnis jeder Permutation der angegebenen Zeichenfolge ein Duplikat eines anderen Ergebnisses für eine andere Zeichenfolge ist. Wenn für alle Permutationen keine Duplikate vorhanden sind, zeigt das Programm den Erfolg an. Neun Zeichen wurden als die größte Anzahl von Zeichen ausgewählt, die auf meiner Box wiederholt berechnet wurden.
Änderungsantrag II Wie ein aufmerksamer Leser hervorhebt, wird der beschriebene Verwendungszweck nicht durch den beigefügten Code erreicht. Der Testfall ist offensichtlich unzureichend.
print"x"
anstelle vonprint("x")
list()
?Antworten:
Es gibt keinen "richtigen" Weg zum Golf. Du hast es gut gemacht und der Prozess, den du benutzt hast, ist ziemlich normal. Es ist jedoch normalerweise nicht erforderlich, das Programm in eine einzige Anweisung umzuwandeln.
Wenn es hilft, würde ich wie folgt vorgehen, um Ihr Programm abzurunden ...
In der Hashing-Funktion kann die for-Anweisung durch eine Summe ersetzt werden:
Dies kann dann als Lambda-Funktion definiert werden:
Und jetzt entfernen wir unnötige Leerzeichen und Klammern:
Wie Sp3000 hervorhob, kann dies mit enumerate weiter verkürzt werden:
Bei der Testfunktion werden die ersten beiden Zeilen zusammengeführt:
Da beide Funktionen nur einmal verwendet werden, können wir alles inline verschieben:
Dies ist als Listenverständnis kürzer:
Als nächstes geben wir ihm einen kürzeren Namen und entfernen wieder unnötige Leerzeichen:
Die if-Anweisung kann innerhalb der Druckfunktion verschoben werden:
Normalerweise ist es jedoch kürzer und / oder:
Da
len(x)
sich nichts ändert, können wir seinen Wert berechnen und fest codieren:Nach dem Entfernen unnötiger Leerzeichen und dem Umschalten des Vergleichs erhalten wir:
So können wir alles in einer Anweisung zusammenfassen:
Und jetzt können wir stattdessen ein Mengenverständnis verwenden:
Das Ergebnis ist 210 Byte, ohne Importe. Der nächste Schritt wäre wahrscheinlich, die Importe oder die langen Saiten herunterzuspielen.
quelle
enumerate
ist kürzer:h=lambda s:sum(ord(x)<<i*len(s)for i,x in enumerate(s))