Dies ist eine Version der letzten Herausforderung. Ist diese Zahl eine ganzzahlige Potenz von -2? mit einem anderen Satz von Kriterien, um die interessante Natur des Problems hervorzuheben und die Herausforderung zu erschweren. Ich habe einige Überlegungen in sie hier .
Die Herausforderung, die Toby in der verknüpften Frage so wunderbar formuliert hat, ist:
Es gibt clevere Methoden, um festzustellen, ob eine Ganzzahl eine exakte Potenz von 2 ist. Das ist kein interessantes Problem mehr. Lassen Sie uns also feststellen, ob eine bestimmte Ganzzahl eine exakte Potenz von -2 ist . Beispielsweise:
-2 => yes: (-2)¹ -1 => no 0 => no 1 => yes: (-2)⁰ 2 => no 3 => no 4 => yes: (-2)²
Regeln:
- Eine Ganzzahl ist 64 Bit, vorzeichenbehaftet, Zweierkomplement. Dies ist der einzige Datentyp, mit dem Sie arbeiten können.
- Sie dürfen nur die folgenden Vorgänge ausführen. Jede davon zählt als eine Operation.
n << k
,n >> k
: Links- / Rechtsverschiebungn
umk
Bits. Vorzeichenbit wird bei Rechtsverschiebung verlängert.n >>> k
: Rechtsverschiebung, aber Vorzeichenbit nicht verlängern. Nullen werden verschoben.a & b
,a | b
,a ^ b
: Logisches AND, OR, XOR.a + b
,a - b
,a * b
Addieren, subtrahieren, multiplizieren.~b
: Bitweise invertieren.-b
: Zweierkomplement-Negation.a / b
,a % b
: Dividieren (ganzzahliger Quotient, rundet in Richtung 0) und Modulo.- Das Modulo negativer Zahlen verwendet die in C99 angegebenen Regeln :
(a/b) * b + a%b
muss gleich seina
. So5 % -3
ist2
und-5 % 3
ist-2
: 5 / 3
ist1
,5 % 3
ist2
, als 1 * 3 + 2 = 5.-5 / 3
ist-1
,-5 % 3
ist-2
, als -1 * 3 + -2 = -5.5 / -3
ist-1
,5 % -3
ist2
, als -1 * -3 + 2 = 5.-5 / -3
ist1
,-5 % -3
ist-2
, als 1 * -3 + -2 = -5.- Beachten Sie, dass der
//
Floor Division Operator von Python die Divisionseigenschaft "round towards 0" hier%
nicht erfüllt und der Operator von Python auch nicht die Anforderungen erfüllt.
- Das Modulo negativer Zahlen verwendet die in C99 angegebenen Regeln :
- Aufträge zählen nicht als Vorgang. Wie in C werden Zuweisungen nach der Zuweisung mit dem Wert auf der linken Seite bewertet:
a = (b = a + 5)
setztb
aufa + 5
, setzta
aufb
und zählt als eine Operation. - Verbindung Zuordnungen verwendet werden
a += b
Mittela = a + b
und als eine Operation zählen.
- Sie können Integer-Konstanten verwenden, sie zählen nicht als etwas.
- Klammern zur Angabe der Operationsreihenfolge sind zulässig.
- Sie können Funktionen deklarieren. Funktionsdeklarationen können in jedem für Sie geeigneten Stil vorliegen. Beachten Sie jedoch, dass 64-Bit-Ganzzahlen der einzige gültige Datentyp sind. Funktionsdeklarationen gelten nicht als Operationen, sondern eine Funktion Anruf zählt. Um auch klar zu sein: Funktionen können mehrere
return
Anweisungen enthalten und sindreturn
von jedem Punkt aus erlaubt. Dasreturn
selbst zählt nicht als Operation. - Sie können Variablen kostenlos deklarieren.
- Sie können
while
Schleifen verwenden, jedoch nichtif
oderfor
. In derwhile
Bedingung verwendete Operatoren zählen zu Ihrer Punktzahl.while
Schleifen werden ausgeführt, solange ihre Bedingung einen Wert ungleich Null ergibt (eine "wahrheitsgemäße" 0 in Sprachen mit diesem Konzept ist kein gültiges Ergebnis). Seit früh Rückkehr erlaubt ist, werden Sie nutzenbreak
als auch - Überlauf / Unterlauf ist erlaubt und es erfolgt keine Werteklemmung. Es wird so behandelt, als ob die Operation tatsächlich korrekt ausgeführt und dann auf 64 Bit gekürzt wurde.
Bewertungskriterien / Gewinnkriterien:
Ihr Code muss einen Wert ungleich Null erzeugen, wenn die Eingabe eine Potenz von -2 ist, und ansonsten Null.
Das ist Atomic-Code-Golf . Ihre Punktzahl ist die Gesamtzahl der in Ihrem Code vorhandenen Vorgänge (wie oben definiert), nicht die Gesamtzahl der Vorgänge, die zur Laufzeit ausgeführt werden. Der folgende Code:
function example (a, b) {
return a + ~b;
}
function ispowerofnegtwo (input) {
y = example(input, 9);
y = example(y, 42);
y = example(y, 98);
return y;
}
Enthält 5 Operationen: zwei in der Funktion und drei Funktionsaufrufe.
Es spielt keine Rolle, wie Sie Ihr Ergebnis präsentieren, was auch immer in Ihrer Sprache angezeigt wird, ob Sie das Ergebnis letztendlich in einer Variablen speichern, von einer Funktion zurückgeben oder was auch immer.
Der Gewinner ist der Beitrag, der nachweislich korrekt ist (ggf. einen beiläufigen oder formellen Beweis vorlegen) und die niedrigste Punktzahl aufweist, wie oben beschrieben.
Bonus Very Hard Mode Challenge!
Senden Sie eine Antwort, ohne while
Schleifen zu verwenden, um eine Chance zu haben, absolut nichts zu gewinnen, außer die potenzielle Fähigkeit, Leute auf Partys zu beeindrucken ! Wenn genug von diesen eingereicht werden, kann ich sogar in Betracht ziehen, die Gewinnergruppen in zwei Kategorien (mit und ohne Schleifen) zu unterteilen.
Hinweis: Wenn Sie eine Lösung in einer Sprache bereitstellen möchten, die nur 32-Bit-Ganzzahlen unterstützt, können Sie dies tun, sofern Sie hinreichend begründen, dass dies für 64-Bit-Ganzzahlen in einer Erläuterung weiterhin korrekt ist.
Außerdem: Bestimmte sprachspezifische Funktionen sind möglicherweise kostenlos zulässig, wenn sie sich nicht den Regeln widersetzen, aber erforderlich sind, um Ihre Sprache dazu zu zwingen, sich gemäß den obigen Regeln zu verhalten . Zum Beispiel (erfunden), erlaube ich ein freies entspricht nicht 0 Vergleich in while
Schleifen, wenn die Bedingung als Ganze angewandt, als Behelfslösung für eine Sprache , die „truthy“ 0 hat. Eindeutige Versuche, diese Art von Dingen auszunutzen, sind nicht zulässig - z. B. gibt es in dem obigen Regelsatz kein Konzept für "wahrheitsgemäße" 0- oder "undefinierte" Werte, und daher kann man sich möglicherweise nicht auf sie verlassen.
m ^= s
es ist immer noch beeindruckend, und ich denke, es wäre völlig in Ordnung, den Ersatz zu machen, um es noch weiter zu verbessern.while
undbreak
nichtif
?if (x) { ... }
ist äquivalent zuwhile (x) { ... break; }
.break
und frühe Renditen sind der bedauerliche Teil) und ist eine lange Geschichte und eine Lektion in Regeln für zukünftige Herausforderungen. Es gibt immer die "Bonus" -Version! :)if
undfor
sind nicht erlaubt?int x=condition; while (x) { ... x=0; }
ist kostenlos, nur mehr Code. Das Gleiche gilt für C-Stylefor
.Antworten:
C ++, 15 Operationen
Ich habe keine Ahnung, warum
while
Schleifen zulässig sind, da sie die gesamte Herausforderung zerstören. Hier ist eine Antwort ohne:quelle
while
Schleifen die gesamte Herausforderung ?while
dem in jeder Hinsicht entgegenzuwirken.n
oder etwas.uint64_t
da dies der einzige Weg ist, die richtige Schicht ohne Vorzeichenerweiterung zu erreichen.)Python 2 , 3 Operationen
Probieren Sie es online!
Die Operationen sind
>>
,&
,/
.Die Idee ist, immer wieder durch -2 zu teilen. Potenzen von -2 Kette von bis zu 1:
-8 -> 4 -> -2 -> 1
. Wenn wir a drücken1
, akzeptieren Sie. Wenn wir vor dem Schlagen eine ungerade Zahl treffen1
, lehnen Sie ab. Wir müssen auch ablehnen0
, was für immer für sich bleibt.Die
while n>>1:
Schleife bisn
ist 0 oder 1. Wenn die Schleife unterbrochen wird , wird sien
selbst zurückgegeben und1
ist eine Wahrheits- und0
eine Falschausgabe. Innerhalb der Schleife lehnen wir wiederholt das Anwenden abn -> n/-2
und lehnen jede ungerade abn
.Da das
/
immer nur für gerade Werte verwendet wird, kommt sein Rundungsverhalten nie ins Spiel. Es spielt also keine Rolle, dass Python anders rundet als die Spezifikation.quelle
while n&1
stattif n&1
?if
.Rost,
1412 Operationen (keine Schleifen)Erfordert Optimierung (
-O
) oder-C overflow-checks=no
um die überlaufende Subtraktion anstelle von Panik zu aktivieren.(Zur Verdeutlichung:
!x
ist bitweise-NICHT hier, nicht logisch-NICHT)Testfälle:
Probieren Sie es online!
Die Idee ist zu prüfen, ob | x | ist eine Potenz von 2 (
(y & (y - 1)) == 0
wie üblich). Wenn x eine Potenz von 2 ist, dann weiter wir Prüfung (1) , wennx >= 0
, sollte es auch eine gerade Potenz von 2 sein, oder (2) wennx < 0
, sollte es eine ungerade Potenz von 2 sein wir dies überprüfen , indem&
-Ing die "bad_power_of_two
"mask 0x ... aaaa whenx >= 0
(erzeugt nur 0, wenn es eine gerade Potenz ist), oder 0x ... 5555 whenx < 0
.quelle
~((r | -r) >> 63)
Trick gestohlen , um meine Antwort zu korrigieren.Haskell,
23 OperationenDefiniert eine rekursive Funktion
f(n)
. Verwendete Operationen sind Funktionsaufruf (f
), Division (div
) und bitweise und (.&.
).Enthält keine Schleifen, da Haskell keine Schleifenanweisungen hat :-)
quelle
f 0
,f 1
,f n ...
hier , weil sie im Wesentlichen istif
‚s in der Verkleidung, obwohl dann wieder, ich erlaubtewhile
+break
und frühreturn
s, so , es ist fair zu sein scheint. Obwohl es den Vorteil zu haben scheint, dass mein Regelsatz versehentlich zur Interpretation freigegeben wird, ist es eine gute Lösung.|
s sind besonders in der Luft. Dies verstößt jedoch in weniger umstrittener Weise gegen eine bestimmte Regel: Der Vergleich==
ist nicht zulässig. Beachten Sie jedoch, dass , wenn meine Interpretation dieser Code korrekt ist, die Verwendung von booleans hier nicht akzeptabel erscheinen als beliebige ganzzahlige Werte an ihrer Stelle ersetzt wird nicht angezeigt , die Ergebnisse zu ändern, und sie sind eher eine endgültige Präsentationsform.==
weil es in Haskell keine andere Möglichkeit gibt, vonInt
bisBool
oder "Truthy" zu casten. Ob der Pattern Matching und die Guards gegen die "noif
s" -Regel verstoßen, ist dein Anliegen ;-)Python 3,
10 oder 119 OperationenRückgabe
5
für Potenzen von-2
,0
ansonstenquelle
C, 5 Operationen
C, 10 Operationen, ohne Schleifen
C, 1 Operation
quelle
Montage, 1 Operation
Verwendet eine große Nachschlagetabelle, um festzustellen, ob die Zahl eine Potenz von 2 ist. Sie können diese auf 64 Bit erweitern, aber einen Computer zu finden, auf dem so viele Daten gespeichert sind, bleibt dem Leser als Übung :-P
quelle
C, 31 Operationen
Live-Demo
Meine Idee ist einfach, wenn es eine Zweierpotenz ist, wenn das Protokoll gerade ist, muss es positiv sein, andernfalls muss das Protokoll ungerade sein.
quelle
C, 7 Operationen
oder:
C, 13 Operationen ohne Schleifen als Bedingungen
Erläuterung:
n&-n
ergibt das niedrigste gesetzte Bit vonn
.a
ist der negierte Absolutwert vonn/2
, der notwendigerweise negativ ist, weil ein/2
Überlaufen der Negation ausgeschlossen ist.a/x
ist nur dann Null, wenna
es sich um eine exakte Zweierpotenz handelt; Andernfalls wird mindestens ein anderes Bit gesetzt und es ist höher alsx
das niedrigste Bit, was zu einem negativen Ergebnis führt.~(a/x >> 63)
dann ergibt sich eine Bitmaske, die nur Einsen enthält, wennn
oder-n
eine Zweierpotenz ist, andernfalls nur Nullen.^s
wird auf die Maske angewendet, um das Vorzeichen von zu überprüfen, um festzustellenn
, ob es sich um eine Potenz von handelt-2
.quelle
PHP, 3 Operationen
ternär und
if
unzulässig sind; Also lasst uns missbrauchenwhile
:$n>>1
: Wenn die Zahl 0 oder 1 ist, wird die Zahl zurückgegeben$n&1
: Wenn die Zahl ungerade ist, wird 0 zurückgegeben$n/-2
(+ cast to int)quelle
JavaScript ES6, 7 Operationen
Probieren Sie es online!
Erläuterung
Während x! = 0 und x% 2 == 0 4 ops
x / x gleich 1 ist , solange x nicht 0 (0/0 gibt NaN , die als falsch bewertet wird)
& bitweise und
x & 1 ^ 1 gleich 1 wenn x gerade ist (x und 1) xoder 1
Dies ist die Form der Teilung, die durch die Frage 1 op
Solange x! = 1 und x! = 0 1 op
Die Bedingung, die zum Beenden erforderlich ist, wenn x == 0 oder x == 1 die Rückgabewerte sind und eine Endlosschleife eingegeben wird, wäre nicht produktiv. Dies könnte theoretisch durch Erhöhen der Hexadezimalzahl für größere Werte erweitert werden. Funktioniert derzeit für bis zu ± 2 ^ 32-1
Setze x auf 0 1 op
Während ich 0 für 0 ops hätte zurückgeben können, hatte ich das Gefühl, dass jede while-Schleife, die durch eine andere Anweisung unterbrochen wird, zu sehr nach Schummeln aussieht.
gibt x zurück (1 wenn Potenz von -2, sonst 0)
quelle