Problem:
Schreiben Sie in der von Ihnen gewählten Sprache die kürzeste Funktion, die den Grund der Quadratwurzel einer 64-Bit-Ganzzahl ohne Vorzeichen zurückgibt.
Testfälle:
Ihre Funktion muss für alle Eingaben korrekt funktionieren. Die folgenden Beispiele veranschaulichen die Idee:
INPUT ⟶ OUTPUT
0 ⟶ 0
1 ⟶ 1
2 ⟶ 1
3 ⟶ 1
4 ⟶ 2
8 ⟶ 2
9 ⟶ 3
15 ⟶ 3
16 ⟶ 4
65535 ⟶ 255
65536 ⟶ 256
18446744073709551615 ⟶ 4294967295
Regeln:
- Sie können Ihre Funktion beliebig benennen. (Unbenannte, anonyme oder Lambda-Funktionen sind in Ordnung, sofern sie irgendwie aufrufbar sind.)
- Die Anzahl der Zeichen ist das Wichtigste bei dieser Herausforderung, aber auch die Laufzeit ist wichtig. Ich bin sicher, Sie könnten iterativ nach der Antwort in O (√n) -Zeit mit einer sehr kleinen Zeichenanzahl suchen, aber die O (log (n)) -Zeit wäre wirklich besser (das heißt, wenn Sie einen Eingabewert von n annehmen würden). keine Bitlänge von n).
- Möglicherweise möchten Sie die Funktion mit rein ganzzahliger und / oder boolescher Artithmetik implementieren. Wenn Sie jedoch wirklich Gleitkommaberechnungen verwenden möchten, ist dies in Ordnung, solange Sie keine Bibliotheksfunktionen aufrufen. Einfach
return (n>0)?(uint32_t)sqrtl(n):-1;
in C zu sagen ist also tabu, obwohl es das richtige Ergebnis liefern würde. Wenn Sie mit Fließkommaarithmetik, können Sie verwenden*
,/
,+
,-
, und Potenzierung (zB**
oder^
wenn es eine eingebauter Operator in der Sprache Ihrer Wahl, sondern nur Potenzierung der Kräfte nicht weniger als 1 ). Diese Einschränkung soll das "Betrügen" verhindern, indem Siesqrt()
eine Variante aufrufen oder einen Wert auf die halbe Potenz erhöhen. - Wenn Sie Gleitkommaoperationen verwenden (siehe Nr. 3), ist es nicht erforderlich, dass der Rückgabetyp eine Ganzzahl ist. Nur, dass der Rückgabewert eine Ganzzahl ist, z. B. floor (sqrt (n)), und in der Lage ist, jeden vorzeichenlosen 32-Bit-Wert zu speichern.
- Wenn Sie C / C ++ verwenden, können Sie davon ausgehen, dass 64-Bit- und 32-Bit-Integer-Typen ohne Vorzeichen vorhanden sind, z. B.
uint64_t
unduint32_t
wie in definiertstdint.h
. Stellen Sie andernfalls sicher, dass Ihr Integer-Typ 64-Bit-Integer ohne Vorzeichen aufnehmen kann. - Wenn Ihre Sprache keine 64-Bit-Ganzzahlen unterstützt (z. B. hat Brainfuck anscheinend nur 8-Bit-Ganzzahlenunterstützung), tun Sie Ihr Bestes, und geben Sie die Einschränkung in Ihrem Antworttitel an. Das heißt, wenn Sie herausfinden können, wie Sie eine 64-Bit-Ganzzahl codieren und die Quadratwurzel mit einer primitiven 8-Bit-Arithmetik korrekt erhalten, dann haben Sie mehr Power!
- Viel Spaß und kreativ werden!
code-golf
math
arithmetic
Todd Lehman
quelle
quelle
O(log_2 n) === O(log_4 n)
.log_4(n) = log_2(n) / log_2(2) = log_2(n) / 2
Antworten:
CJam, 17 (oder 10) Bytes
Probieren Sie es online aus, indem Sie die Testfälle überprüfen:
Der letzte Testfall wird aufgrund von Rundungsproblemen nicht bestanden, aber da
18446744073709551615
es in CJam keine Ganzzahl gibt (es ist eine große Ganzzahl ), sind wir immer noch gut, oder?Wenn nicht, korrigiert der folgende (und etwas längere) Code diese Fehler:
Nicht mehr die kürzeste Lösung, aber schnell .
Wie es funktioniert
quelle
<.@%~^&1.5
. Kann ich dies als separate Antwort posten (da es im Grunde genommen ein exakter Port von dir ist)?4294967295
und sehr ähnlich4294967296
aussehen ...Haskell,
2826Ich glaube, dass dies der kürzeste Eintrag aus einer Sprache ist, die nicht zum Golfen gedacht ist.
Es benennt eine Funktion
s
mit einem Parametera
und gibt eins minus der ersten Zahl zurück, deren Quadrat größer als ista
. Läuft unglaublich langsam (O (sqrt n), vielleicht?).quelle
[...]!!0
) nicht kürzer als head?Golfscript, 17 Zeichen
Ich konnte meine Funktion so benennen, wie ich wollte, aber ich beschloss, sie überhaupt nicht zu benennen. Fügen Sie zwei Zeichen hinzu, um es zu benennen, fügen Sie drei hinzu, um es zu benennen, und belassen Sie es nicht auf dem Stapel. Subtrahieren Sie ein Zeichen, wenn ein vollständiges Programm in Ordnung ist.
Diese Abscheulichkeit läuft nicht in logaritmischer Zeit im Wert der Eingabe, nicht in O (sqrt n) Zeit, es dauert eine lange lineare Zeit, um das Ergebnis zu erzeugen. Es braucht auch so viel Platz. Absolut schrecklich. Aber ... das ist Code-Golf.
Der Algorithmus ist:
quelle
Pyth , 14 Zeichen
Stellt eine benannte Funktion s bereit, die die Quadratwurzel berechnet, indem sie die Liste von 0 bis n filtert, damit das Quadrat größer als die Eingabe ist, und dann die letzte solche Zahl ausgibt. Verwendet keine Exponentiation oder Floats.
Beispielverwendung:
quelle
Retina (nicht konkurrierend - Sprache ist neuer als die Herausforderung), 43
Bei der Arbeit an dieser Antwort ist mir aufgefallen, dass eine ähnliche Methode zum Berechnen ganzzahliger Quadratwurzeln mit der Netzhaut verwendet werden kann:
Dies beruht auf der Tatsache, dass perfekte Quadrate wie
1+3+5+7+...
folgt ausgedrückt werden können: Die Anzahl der Terme in diesem Ausdruck ist die Quadratwurzel.Probieren Sie es online aus. (Erste Zeile hinzugefügt, damit mehrere Testfälle ausgeführt werden können.)
Offensichtlich funktioniert dies aufgrund der Umwandlung von Dezimalstellen in unäre Werte nur für relativ kleine Eingaben.
quelle
Perl, 133 Zeichen
Bei weitem nicht die kürzeste, verwendet jedoch einen ziffernweisen Algorithmus zur Verarbeitung von Eingaben beliebiger Größe und wird in O-Zeit (log n) ausgeführt. Konvertiert frei zwischen Zahlen als Zeichenfolgen und Zahlen als Zahlen. Da das größtmögliche Produkt die bisherige Wurzel mit dem Quadrat einer einzelnen Ziffer ist, sollte es in der Lage sein, die Quadratwurzel von etwa 120-Bit-Zahlen auf einem 64-Bit-System zu bilden.
Dekomprimiert, das heißt:
quelle
if length%2
anstattif(length)%2
? Das würde 1 Charakter abschneiden. Würde es auch funktionieren,$y=$z,$d=$_ if
statt zu sagen($y,$d)=($z,$_)if
? Ich denke, das würde 3 weitere Charaktere abschneiden.for
Schleife wie$a<($z=$_*(20*$r+$_))or$y=$z,$d=$_ for(1..9);
%2
), die anderen Vorschläge sind jedoch gültig. Ich werde siefor
benötigt keine Klammern. Wenn ich das zu deinen Vorschlägen hinzufüge, bekomme ich insgesamt 6 Zeichen. Vielen Dank!Matlab (56) / Octave (55)
Es berechnet die Quadratwurzel mit einer Festpunktmethode. Es konvergiert in maximal 36 Schritten (für 2 ^ 64-1 als Argument) und prüft dann, ob es die niedrigere der 'möglichen' Ganzzahlwurzeln ist. Da es immer 36 Iterationen verwendet, hat es eine Laufzeit von O (1) = P
Als Argument wird uint64 angenommen.
Matlab:
Oktave:
quelle
Ruby - 36 Zeichen
quelle
while
Schleife genau dann endet, wenn g zum Boden (√n) konvergiert, was der gewünschte Wert ist. Sehen Sie einen Fall, in dem dies nicht zutrifft?Python (39)
Der natürliche rekursive Ansatz. Zählt mögliche Quadratwurzeln, bis ihr Quadrat zu hoch ist, und verringert sich dann um 1. Verwenden Sie Stackless Python, wenn Sie befürchten, die Stapeltiefe zu überschreiten.
Die
and/or
Redewendung entspricht dem ternären Operator asEdit: Ich kann stattdessen bekommen 25 Zeichen durch die Regel „Schöpfen Sie verwenden können
*
,/
,+
,-
, und Potenzierung (zB**
oder^
wenn es eine eingebauter Operator in der Sprache Ihrer Wahl, aber nur Potenzierung der Kräfte nicht weniger als 1). " (Edit: Anscheinend hat Dennis diesen Trick bereits gefunden und ausgenutzt.)Ich verwende den Ganzzahlteilungsoperator
//
von Python 3, um abzurunden. Leidern=0
gebe ich eine Menge Zeichen für den Fall aus , um keine Division durch 0 Fehler zu geben. Wenn es nicht so wäre, könnte ich 18 Zeichen machenDie Regeln sahen auch nicht vor, dass die Funktion benannt werden muss (je nachdem, wie Sie "Sie können Ihre Funktion beliebig benennen" interpretieren), aber wenn ja, sind das zwei weitere Zeichen.
quelle
C99 (58 Zeichen)
Dies ist ein Beispiel für eine Antwort, die ich nicht für gut halte, obwohl sie aus Sicht des Code-Golfs für mich interessant ist, weil sie so pervers ist, und ich dachte nur, es würde Spaß machen, sie in die Mischung zu werfen:
Original: 64 Zeichen
Der Grund, warum dies schrecklich ist, ist, dass es eher in O (√n) als in O (log (n)) läuft. (Wobei n der Eingabewert ist.)
Bearbeiten: 63 Zeichen
Ändern
r-1
von--r
und Anfügen anreturn
:Bearbeiten: 62 Zeichen
Verschieben des Schleifeninkrements in den bedingten Teil der Schleife (Hinweis: Dieses Verhalten ist nicht garantiert, da die Reihenfolge der Operationen in Bezug auf den Operator vor dem Inkrementieren compilerspezifisch ist):
Bearbeiten: 60 Zeichen
Hinzufügen eines
typedef
zu verbergenden Elementsuint64_t
(Gutschrift an den Technosaurus- Benutzer für diesen Vorschlag).Bearbeiten: 58 Zeichen
Jetzt muss der zweite Parameter beim Aufruf der Funktion als 0 übergeben werden, z. B.
r(n,0)
statt nurr(n)
. Ok, für mein ganzes Leben kann ich jetzt nicht mehr sehen, wie ich das weiter komprimieren kann ... irgendjemand?quelle
uint64_t s(uint64_t n){for(uint64_t r=n;--n>r/n;);return n;}
.--n
wennn==0
–1 wäre und dies vorzeichenlose Werte sind, wäre –1 2⁶⁴ – 1.#define Z uint64_t
... oder typedef wird ein paar rettenn/++r/r
hat undefiniertes Verhalten ....Golfscript - 14 Zeichen
Suchen Sie die kleinste Zahl, die
i
kleiner ist als die Eingabe,n
für dien < i*i
. Rückkehri - 1
.Dh
[0..n-1].first(i => n < i*i) - 1
Erklärung für diejenigen, die Golfscript nicht kennen, für einen Beispielaufruf mit Eingabe
5
:quelle
1
wahrscheinlich zwei Zeichen erforderlich .Haskell,
147138134128 BytesNicht der kürzeste Code der Welt, aber er wird in O (log n) und auf Zahlen beliebiger Größe ausgeführt:
Dies führt eine binäre Suche im Bereich [0..n] durch, um die beste untere Annäherung an sqrt (n) zu finden. Hier ist eine ungolfed Version:
Bearbeiten: Zwei Bytes wurden gespeichert, indem die "else" -Klauseln durch "0 <1" als kürzere Version von "True" und einige weitere durch Inlining von g * g ersetzt wurden.
Wenn Sie mit O (sqrt (n)) zufrieden sind, können Sie dies auch einfach tun
für 35 Zeichen, aber was macht das für einen Spaß?
Bearbeiten 2: Ich habe gerade festgestellt, dass Paare nach Wörterbuchreihenfolge sortiert sind, anstatt min2Cycle auszuführen. map fst, ich kann einfach fst machen. min2Cycle. Im Code für Golf bedeutet dies, dass f $ map fst durch fst $ f ersetzt wird, wodurch 4 weitere Bytes eingespart werden.
Edit 3: Dank proudhaskeller sechs weitere Bytes gespeichert!
quelle
JavaScript
918886: Optimiert für GeschwindigkeitJavaScript 46: Nicht für Geschwindigkeit optimiert
Hier ist eine JSFiddle: http://jsfiddle.net/rmadhuram/1Lnjuo4k/
quelle
function s(n){for(a=1;++a*a<n;);return a}
C 95
97Bearbeiten Typedef, vorgeschlagen von @Michaelangelo
Dies sollte mehr oder weniger eine einfache Implementierung des Heron-Algorithmus sein. Das einzige Manko ist die Berechnung des durchschnittlichen Vermeidungsüberlaufs von ganzen Zahlen: a = (m + n) / 2 funktioniert nicht für große Zahlen.
quelle
C #
646255Da dies ein Code-Golf ist (und ich bin schrecklich mit Mathematik) und die Laufzeit nur ein Vorschlag ist, habe ich den naiven Ansatz gewählt, der in linearer Zeit abläuft:
( Test auf dotnetfiddle )
Natürlich ist es für größere Eingänge furchtbar langsam.
quelle
return i-1
zureturn--i
?i*i<=a
garantiert eine ganzzahlige Arithmetik des üblichen Typs? (C # ist mir nicht vertraut.) Wenn dies der Fall ist und C # eine implizite Ganzzahlkonvertierung in einen Booleschen Wert zulässt, können Sie möglicherweise ein weiteres Zeichen speichern, indem Sie dies in änderna/i/i
.Decimal
höherer Maximalwert und höhere Genauigkeit), um den Überlauf zu vermeiden, da das Multiplikationsergebnis möglicherweise einen Schritt zurückgehen könnteUInt64.MaxValue
. Aber C # hat sowieso keine impliziten Konvertierungen nach Boolean. Ich sollte das aber ändern könnenreturn
, danke. Ich werde es tun, wenn ich wieder an einen Computer gehe.Clojure - 51 oder 55 Bytes
Überprüft alle Zahlen von n bis 0 und gibt die erste Stelle an
x^2 <= n
. Laufzeit istO(n - sqrt n)
Unbenannt:
Genannt:
Beispiel:
quelle
Befunge 93 - 48 Bytes oder 38 Zeichen
Probieren Sie es hier.
quelle
Cobra - 62
Batch - 74
quelle
Haskell,
535049 Zeichen, O (log n)Diese Lösung implementiert die Newton-Raphson-Methode, sucht jedoch nach ganzen Zahlen anstelle von Gleitkommazahlen. wiki: http://en.wikipedia.org/wiki/Newton%27s_method
Die Komplexität scheint bei O (log n) zu liegen, aber gibt es einen Beweis dafür? Bitte antworten Sie in den Kommentaren.
quelle
\g->div(n+g^2)$2*g
spart 7 Bytes.J (10)
Sehr, sehr, sehr inspiriert von der Antwort von @Dennis :
Und ein bisschen länger, aber mit besserer Leistung (ich vermute):
floor(halve under log)
Zur Ausführung werden eingerückte Teile eingegeben:
quelle
APL - 12 chars, 19 bytes
example use:
returns 4
Test vector
returns
1 1 1 1 2 2 3 3 4 255 256 4294967296
Try Online
Big thanks to: user "ssdecontrol" for algorithm
quelle
0
→1
! Using Dyalog APL, you can set⎕DIV←1
(which many use as default) to obtain the correct result.C99 (108 characters)
Here is my own solution in C99, which is adapted from an algorithm in an article on Wikipedia. I'm sure it must be possible to do much better than this in other languages.
Golfed:
Partially golfed:
Ungolfed:
quelle
a
, usen
.n
so that just before returning I could make the assertion (not shown) that r^2 <= n < (r+1)^2. With that assertion omitted, it's longer necessary to keepn
intact.const
in the ungolfed version.JavaScript
7381 (to comply with 64-bit numbers requirement)n=prompt();g=n/3;do{G=g,g=(n/g+g)/2}while(1E-9<Math.abs(G-g))alert(Math.floor(g))
Implementing Heron of Alexandria's algorithm...
quelle
|0
affects up to 32-bit whereasMath.floor
is more effective at 64-bit... I've updated my code, having to take an extra 8 characters in order to do so...Powershell (52) Limited to Int32 (-2,147,483,648 to 2,147,483,647)
I'm screaming at Powershell right now trying to make the last test case work but no matter what I do Powershell winds up using the pipeline variable $_ as an Int32, and I can't find a way around it right now.
So I'll just limit my answer for now. If I can find a better way to handle uint64s I will edit. (The last test case is too big for Powershell's normal Int64 type, by the way!)
Here are a few test cases (with a bit of extra output I used to track the time)
I don't know my O()s, but this seems like a pretty dramatic jump.
quelle
Caveat: as of 2011, R had no built-in support for 64 bit integers as I had assumed it did. These answers might be invalid on that technicality, but then again R has changed a lot in the last 3 years.
R, 85
Using Newton's method:
which converges quadratically. +2 characters to assign the function to a variable for benchmarking:
R, 37
Brute force:
And the same check:
R, 30
The cheap/brilliant exponentiation trick:
which also happens to be very fast (although not as fast as the built-in):
quelle
C, 38
Translation of my Forth submission. Slow but correct. O(√n). Tested on OS X (64 bit).
quelle
dc, 50 bytes
Spaced out and explained:
quelle
C,
139137136 bytesMy first try at code golf. It looks like it's the shortest in C that fits the "efficient" requirement, as it runs in
O(log n)
time, using only addition and bit shifts. Though I'm sure it could be shorter yet...It should work just fine for larger integer values too as long as the
a=32
part is changed toa=NUMBITS/2
.quelle
(t++)
instead of justt++
in the assignment tor
?a--+1
as a way to avoid writinga-- != UINT64_C(-1)
. Did you learn that trick somewhere or invent it yourself?C - 50 (61 without global)
It use global variables as parameter and return value to save space.
No global version :
quelle
C++ 125
quelle
x+=(d<0)-0.5;
... saves 5 more characters?main
is a function, but it's not callable from inside a program like anf(y)
would be.)while((d=x*x-y)>0.5)
instead ofwhile((d=(x*x-y))>0.5)
. Saves 2 more characters. :)