Schreiben Sie ein GOLF- Assemblerprogramm, das bei einer 64-Bit-Ganzzahl ohne Vorzeichen im Register n
einen Wert ungleich Null in das Register schreibt, s
wenn n
es sich um ein Quadrat handelt, andernfalls 0
in s
.
Ihre GOLF- Binärdatei (nach dem Zusammenbau) muss in 4096 Bytes passen.
Ihr Programm wird mit dem folgenden Python3-Programm bewertet (das im GOLF- Verzeichnis abgelegt werden muss ):
import random, sys, assemble, golf, decimal
def is_square(n):
nd = decimal.Decimal(n)
with decimal.localcontext() as ctx:
ctx.prec = n.bit_length() + 1
i = int(nd.sqrt())
return i*i == n
with open(sys.argv[1]) as in_file:
binary, debug = assemble.assemble(in_file)
score = 0
random.seed(0)
for i in range(1000):
cpu = golf.GolfCPU(binary)
if random.randrange(16) == 0: n = random.randrange(2**32)**2
else: n = random.randrange(2**64)
cpu.regs["n"] = n
cpu.run()
if bool(cpu.regs["s"]) != is_square(n):
raise RuntimeError("Incorrect result for: {}".format(n))
score += cpu.cycle_count
print("Score so far ({}/1000): {}".format(i+1, score))
print("Score: ", score)
Stellen Sie sicher, dass Sie GOLF mit auf die neueste Version aktualisieren git pull
. Führen Sie das Score-Programm mit python3 score.py your_source.golf
.
Es verwendet einen statischen Startwert, um eine Menge von Zahlen zu generieren, von denen ungefähr 1/16 ein Quadrat ist. Die Optimierung in Richtung dieser Menge von Zahlen ist gegen den Geist der Frage, ich kann den Samen jederzeit ändern. Ihr Programm muss für alle nicht negativen 64-Bit-Eingabenummern funktionieren, nicht nur für diese.
Die niedrigste Punktzahl gewinnt.
Da GOLF sehr neu ist, füge ich hier einige Hinweise ein. Sie sollten die GOLF- Spezifikation mit allen Anweisungen und Zykluskosten lesen . Im Github-Repository finden Sie Beispielprogramme.
Kompilieren Sie zum manuellen Testen Ihr Programm durch Ausführen in eine Binärdatei python3 assemble.py your_source.golf
. Führen Sie dann Ihr Programm mit aus python3 golf.py -p s your_source.bin n=42
. Dies sollte das Programm mit der n
Einstellung 42 starten und das Register s
und die Zykluszahl nach dem Beenden ausgeben. Zeigen Sie alle Werte des Registerinhalts beim Programmende mit dem -d
Flag an - verwenden Sie --help
diese Option, um alle Flags anzuzeigen.
git pull
. Ich habe einen Fehler im linken Operanden gefunden, bei dem der Zeilenumbruch nicht richtig war.Antworten:
Bewertung: 22120 (3414 Bytes)
Meine Lösung verwendet eine 3-KB-Nachschlagetabelle, um einen Newton-Methodenlöser zu generieren, der je nach Ergebnisgröße für null bis drei Iterationen ausgeführt wird.
quelle
Ergebnis: 27462
Mit der Zeit würde ich an einer GOLF- Herausforderung teilnehmen: D
quelle
Ergebnis: 161558
227038259038260038263068Ich habe den schnellsten Ganzzahl-Quadratwurzel-Algorithmus genommen, den ich finden und zurückgeben konnte, ob der Rest Null ist.
EDIT 1: Quadriertest entfernt, Rest direkt zurück, 3 Operationen pro Test sparen
BEARBEITEN 2: Verwenden Sie n direkt als Rest, speichern Sie 1 Operation pro Test
EDIT 3: Schleifenbedingung vereinfacht, 32 Operationen pro Test speichern
EDIT 4: Entrollt die Schleife, spart etwa 65 Operationen pro Test
quelle
0x4000000000000000
als1 << 62
:)Ergebnis: 344493
Führt eine einfache binäre Suche innerhalb des Intervalls durch, um
[1, 4294967296)
zu approximierensqrt(n)
, und prüft dann, obn
es sich um ein perfektes Quadrat handelt.quelle