Die beste Lösung, die ich bisher für ein Golf-Code-Puzzle gefunden habe, an dem ich arbeite, sind zwei ziemlich fett aussehende Aufrufe von range
. Ich bin sehr neu im Code Golf, besonders in Python, also könnte ich ein paar Tipps gebrauchen.
Das relevante Fragment ist dies
[x for x in range(n+1,7**6)if`x`==`x`[::-1]*all(x%i for i in range(2,x))]
Die Obergrenze der ersten range
ist nicht scharf. Es sollte mindestens 98690 sein, und alles andere ist gleich ( dh golfmäßig). Je kleiner der Unterschied zwischen dieser Obergrenze und 98690 ist, desto besser ist die Leistung 1 . Ich verwende 7 6 (= 117649), weil dies 7**6
der kürzeste Python-Ausdruck ist, den ich mir vorstellen kann.
Im Gegensatz dazu sind die Untergrenze in der ersten range
sowie beide Grenzen in der zweiten fest. IOW, das Programm (in seiner aktuellen Form) führt zu falschen Ergebnissen, wenn diese Grenzwerte geändert werden.
Gibt es eine Möglichkeit, einen oder beide Ausdrücke zu verkürzen?
range(n+1,7**6)
range(2,x)
?
Übrigens, in diesem Fall gewinnt das Aliasing range
von beispielsweise r
nichts:
r=range;rr
rangerange
EDIT: FWIW, das vollständige Programm ist das folgende:
p=lambda n:[x for x in range(n+1,7**6)if`x`==`x`[::-1]*all(x%i for i in range(2,x))][0]
p(n)
sollte die kleinste palindromische Primzahl größer sein als n
. Auch p
sollte nicht rekursiv sein. Achtung: Es ist schon obszön langsam!
1 Ja, ich weiß: Leistung ist beim Code-Golf irrelevant, aber deshalb habe ich geschrieben, dass "alles andere gleich ist (was das Golf betrifft)". Zum Beispiel meine Wahl 7**6
und nicht die unmittelbar offensichtliche, aber leistungsschwächere "Golf-Äquivalent" -Alternative 9**9
. Ich mag es , meine Code-Golf-Versuche tatsächlich auszuführen , was bedeutet, dass die Leistung nicht so stark beeinträchtigt wird, dass es Jahre dauern würde, bis der Code ausgeführt wird. Wenn ich helfen kann, natürlich.
p=lambda n:(x for x in xrange(n+1,7**6)if`x`==`x`[::-1]*all(x%i for i in xrange(2,x))).next()
. Während Sie dabei sind, können Sie natürlich genauso gutxrange(2,x)
zuxrange(2,int(x**.5+1))
Ihren Tests wechseln und diese sehr schnell durchführen. Dieser Code entspricht eindeutig Ihrem Code, nur länger und schneller.Antworten:
Machen Sie es zu einer einzigen Schleife
Wie es ist, haben Sie zwei Schleifen: eine, die über
x
palindromische Primzahlen iteriert, eine andere, die iteriert, umi
zu überprüfen, obx
es sich um eine Primzahl handelt, die durch die Testteilung primiert wird. Wie Sie bemerkt haben, benötigt Python in vielen Schleifen viele Zeichen, oft zum Schreibenrange
, aber auch zum Schreibenwhile _:
oderfor x in _
. Eine Golf-Python-Lösung sollte sich also Mühe geben, so wenig Loops wie möglich zu verwenden.Der Kommentar von feersum "Die besten Golfprogramme stellen oft überraschende Verbindungen zwischen verschiedenen Teilen der Programme her" ist hier sehr zutreffend. Die Primprüfung scheint wie eine separate Unterroutine zu sein, für die
all(x%i for i in range(2,x))
der klassische Ausdruck gilt. Aber wir machen es anders.Die Idee ist, Wilsons Theorem zu verwenden . Für jede potenzielle Primzahl
k
behalten wir ein laufendes Produkt von(k-1)!
bei und prüfen, ob es ein Vielfaches von istk
. Wir können den Überblick behalten,(k-1)!
während wir das Potenzial testenk
, erstklassige Palindrome zu sein, indem wir ein laufendes Produkt behaltenP
.Eigentlich werden wir die stärkere Version von Wilsons Satz verwenden , die
(k-1)! % k
0 für Verbunde gleichk
und nur für zusammengesetzte Zahlen, mit Ausnahmek=4
gibt2
, und so(k-1)!**2 % k
entspricht0
genau für zusammengesetzte Zahlen. Wir werden über das UpdateP
auf gleichk!**2
aktualisierenP*=k*k
.(Siehe diese Antwort für diese Methode zum Suchen von Primzahlen in Python.)
Alles zusammen:
Dies ist noch nicht vollständig golfen - insbesondere die Bedingung ist ineffizient geschrieben. Wir können die Bedingung komprimieren, um zu überprüfen, ob
k
es sich um ein Palindrom handelt, während wir gleichzeitig die anderen Bedingungen über eine verkettete Ungleichung erzwingen.quelle
str
, aber diese Tricks bekommen nur einen viel ... die großen Verbesserungen kommen wie immer von besseren Algorithmen.`k`*(k>n)*(P%k>0)!=`k`[::-1]
, der sichAFAIK, nicht wirklich.
Die Reichweite wird häufig in Python-Golfspielen verwendet, da dies der kürzeste Weg ist, um Listen mit zunehmenden / abnehmenden Zahlen zu erstellen.
Das heißt, es scheint etwas (7 Bytes) kürzer zu sein, um die Verwendung von range zu vermeiden und stattdessen eine umschlossene while-Schleife aufzurufen:
Vielen Dank an @xnor (wie immer) für die Verbesserung der Logik der while-Bedingung :)
quelle
while(`n`!=`n`[::-1])+0in(n%i for i in range(2,n)):n+=1
. Ich kann das erste Paar von Parens aufgrund von Problemen mit der Priorität des Bedieners nicht loswerden.while`n`*all(n%i for i in range(2,n))!=`n`[::-1]:n+=1
Wenn Sie iterative Algorithmen wie die Newton-Methode oder die Berechnung von Fraktalen verwenden, bei denen Sie normalerweise Iterationen durchführen müssen , ohne sich um den Index zu kümmern , können Sie einige Zeichen speichern, indem Sie stattdessen über kurze Zeichenfolgen iterieren.
Bei sieben Iterationen ist dies ausgeglichen
range
. Verwenden Sie für weitere Iterationen Backtics und große ZahlenDies läuft 56349 Mal, was für alle praktischen Zwecke ausreichen sollte. Wenn Sie mit Zahlen und Operatoren herumspielen, können Sie auf diese Weise eine Vielzahl von Zahlen fest codieren.
quelle
'1'*4
kürzer ist als'asdf'
)