Problème:
Dans votre choix de langue, écrivez la fonction la plus courte qui renvoie le plancher de la racine carrée d'un entier 64 bits non signé.
Cas de test:
Votre fonction doit fonctionner correctement pour toutes les entrées, mais voici quelques-unes qui aident à illustrer l'idée:
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
Règles:
- Vous pouvez nommer votre fonction comme bon vous semble. (Les fonctions sans nom, anonymes ou lambda sont correctes, du moment qu'elles sont en quelque sorte appelables.)
- Le nombre de caractères est ce qui compte le plus dans ce défi, mais l'exécution est également importante. Je suis sûr que vous pourriez numériser vers le haut de manière itérative pour la réponse en temps O (√n) avec un très petit nombre de caractères, mais le temps O (log (n)) serait vraiment meilleur (c'est-à-dire, en supposant une valeur d'entrée de n, pas un bit de n).
- Vous voudrez probablement implémenter la fonction en utilisant une arithmétique purement entière et / ou booléenne. Cependant, si vous voulez vraiment utiliser des calculs à virgule flottante, c'est bien tant que vous n'appelez aucune fonction de bibliothèque. Donc, dire simplement
return (n>0)?(uint32_t)sqrtl(n):-1;
en C est hors limites même si cela produirait le résultat correct. Si vous utilisez l' arithmétique à virgule flottante, vous pouvez utiliser*
,/
,+
,-
et exponentiation (par exemple,**
ou^
si elle est un opérateur intégré dans votre langue de choix, mais seulement exponentiation des pouvoirs au moins 1 ). Cette restriction vise à empêcher la "tricherie" en appelantsqrt()
ou une variante ou en élevant une valeur à la ½ puissance. - Si vous utilisez des opérations à virgule flottante (voir # 3), vous n'êtes pas obligé que le type de retour soit entier; seulement que la valeur de retour est un entier, par exemple, floor (sqrt (n)), et pouvoir contenir n'importe quelle valeur 32 bits non signée.
- Si vous utilisez C / C ++, vous pouvez supposer l'existence de types entiers 64 bits et 32 bits non signés, par exemple,
uint64_t
etuint32_t
comme défini dansstdint.h
. Sinon, assurez-vous simplement que votre type entier est capable de contenir n'importe quel entier non signé 64 bits. - Si votre jauge ne prend pas en charge les entiers 64 bits (par exemple, Brainfuck n'a apparemment que la prise en charge des entiers 8 bits), faites de votre mieux avec cela et indiquez la limitation dans le titre de votre réponse. Cela dit, si vous pouvez comprendre comment coder un entier 64 bits et en obtenir correctement la racine carrée en utilisant l'arithmétique primitive 8 bits, alors plus de puissance pour vous!
- Amusez-vous et soyez créatif!
code-golf
math
arithmetic
Todd Lehman
la source
la source
O(log_2 n) === O(log_4 n)
.log_4(n) = log_2(n) / log_2(2) = log_2(n) / 2
Réponses:
CJam, 17 (ou 10) octets
Essayez-le en ligne en vérifiant les cas de test:
Il ne passera pas le dernier cas de test en raison de problèmes d'arrondi, mais comme il
18446744073709551615
n'y a pas un entier dans CJam (c'est un gros entier ), nous sommes toujours bons, non?Sinon, le code suivant (et légèrement plus long) corrigera ces erreurs:
Ce n'est plus la solution la plus courte, mais faaast .
Comment ça fonctionne
la source
<.@%~^&1.5
. Puis-je poster ceci en tant que réponse distincte (car il s'agit essentiellement de votre port exact)?4294967295
et4294967296
apparence très similaire ...Haskell,
2826Je crois que c'est l'entrée la plus courte de toute langue qui n'a pas été conçue pour le golf.
Il nomme une fonction
s
avec paramètrea
et renvoie un moins le premier nombre dont le carré est supérieur àa
. Fonctionne incroyablement lentement (O (sqrt n), peut-être?).la source
[...]!!0
) ne serait-il pas plus court que head?Golfscript, 17 caractères
Je pouvais nommer ma fonction comme je le souhaitais, mais j'ai décidé de ne pas la nommer du tout. Ajoutez deux caractères pour le nommer, ajoutez trois pour le nommer et ne le laissez pas sur la pile, soustrayez un caractère si la fourniture d'un programme complet est OK.
Cette abomination ne s'exécute pas en temps logarithmique dans la valeur de l'entrée, pas en temps O (sqrt n), il faut un temps linéaire de coqueluche pour produire le résultat. Cela prend aussi beaucoup d'espace. Absolument horrible. Mais ... c'est du code-golf.
L'algorithme est:
la source
Pyth , 14 caractères
Fournit une fonction nommée, s, qui calcule la racine carrée en filtrant la liste de 0 à n pour le carré étant plus grand que l'entrée, puis imprime le dernier de ces nombres. N'utilise aucune exponentiation ou flotteur.
Exemple d'utilisation:
la source
Rétine (sans compétition - La langue est plus récente que le défi), 43
En travaillant sur cette réponse , il m'est venu à l'esprit qu'une méthode similaire peut être utilisée pour calculer les racines carrées entières en utilisant la rétine:
Cela repose sur le fait que les carrés parfaits peuvent être exprimés par
1+3+5+7+...
, et par corollaire que le nombre de termes dans cette expression est la racine carrée.Essayez-le en ligne. (Première ligne ajoutée pour permettre l'exécution de plusieurs tests.)
Évidemment, en raison de la conversion décimale en unaire, cela ne fonctionnera que pour des entrées relativement petites.
la source
Perl, 133 caractères
Pas le plus court de loin, mais utilise un algorithme chiffre par chiffre pour gérer n'importe quelle entrée de taille et s'exécute en temps O (log n). Convertit librement entre des nombres sous forme de chaînes et des nombres sous forme de nombres. Étant donné que le plus grand produit possible est la racine jusqu'à présent avec le carré d'un seul chiffre, il devrait être capable de prendre la racine carrée de 120 bits ou plus sur un système 64 bits.
Décompressé, c'est-à-dire:
la source
if length%2
place deif(length)%2
? Cela raserait 1 caractère. En outre, cela fonctionnerait-il de dire à la$y=$z,$d=$_ if
place de($y,$d)=($z,$_)if
? Je pense que cela raserait 3 personnages de plus.for
boucle comme:$a<($z=$_*(20*$r+$_))or$y=$z,$d=$_ for(1..9);
%2
), mais les autres sont valides. Je vais les travailler.for
n'a pas besoin de parenthèses; ajouter cela à vos suggestions me rapporte 6 caractères au total. Merci!Matlab (56) / Octave (55)
Il calcule la racine carrée en utilisant une méthode à point fixe. Il converge en 36 étapes maximum (pour 2 ^ 64-1 comme argument) et vérifie ensuite s'il s'agit de la plus basse des racines entières «possibles». Comme il utilise toujours 36 itérations, il a un temps d'exécution de O (1) = P
L'argument est supposé être uint64.
Matlab:
Octave:
la source
Ruby - 36 caractères
la source
while
boucle se termine précisément lorsque g converge vers le sol (√n) qui est la valeur souhaitée. Voyez-vous des cas où cela ne serait pas vrai?Python (39)
L'approche récursive naturelle. Compte les racines carrées potentielles jusqu'à ce que leur carré soit trop élevé, puis diminue de 1. Utilisez Stackless Python si vous craignez de dépasser la profondeur de la pile.
L'
and/or
idiome est équivalent à l'opérateur ternaire commeEdit: je peux au lieu obtenir 25 caractères en exploitant la règle « vous pouvez utiliser
*
,/
,+
,-
et exponentiation (par exemple,**
ou^
si elle est un opérateur intégré dans votre langue de choix, mais seulement exponentiation des pouvoirs au moins 1). " (Edit: Apparemment, Dennis a déjà trouvé et exploité cette astuce.)J'utilise l'opérateur
//
de division entière de Python 3 pour arrondir. Malheureusement, je passe beaucoup de caractères pour que le casn=0
ne donne pas une division par 0 erreur. Sinon, je pourrais faire 18 caractèresLes règles ne disaient pas non plus que la fonction devait être nommée (selon la façon dont vous interprétez "Vous pouvez nommer votre fonction comme vous voulez."), Mais si c'est le cas, ce sont deux autres caractères.
la source
C99 (58 caractères)
Ceci est un exemple de réponse que je ne considérerais pas comme une bonne, même si elle est intéressante pour moi du point de vue du code de golf car elle est tellement perverse, et je pensais juste que ce serait amusant de jeter dans le mélange:
Original: 64 caractères
La raison pour laquelle celui-ci est terrible est qu'il s'exécute en temps O (√n) plutôt qu'en temps O (log (n)). (Où n est la valeur d'entrée.)
Modifier: 63 caractères
Changer le
r-1
to--r
et le joindre àreturn
:Modifier: 62 caractères
Déplacement de l'incrément de boucle à l'intérieur de la partie conditionnelle de la boucle (remarque: cela a un comportement non garanti car l'ordre des opérations par rapport à l'opérateur de pré-incrémentation est spécifique au compilateur):
Modifier: 60 caractères
Ajout d'un
typedef
pour masqueruint64_t
(crédit à l'utilisateur technosaurus pour cette suggestion).Modifier: 58 caractères
Maintenant, le deuxième paramètre doit être passé à 0 lors de l'invocation de la fonction, par exemple,
r(n,0)
au lieu de simplementr(n)
. Ok, pour la vie de moi, à ce stade, je ne vois pas comment comprimer cela plus loin ... n'importe qui?la source
uint64_t s(uint64_t n){for(uint64_t r=n;--n>r/n;);return n;}
.--n
quandn==0
serait –1, et que ce sont des valeurs non signées, donc –1 serait 2⁶⁴ – 1.#define Z uint64_t
... ou typedef sauvera un couplen/++r/r
a un comportement indéfini ....Golfscript - 14 caractères
Trouvez le plus petit nombre
i
inférieur à l'entréen
pour laquellen < i*i
. Retouri - 1
.C'est à dire
[0..n-1].first(i => n < i*i) - 1
Explication pour ceux qui ne connaissent pas également Golfscript, pour un exemple d'appel avec entrée
5
:la source
1
prend probablement deux caractères.Haskell,
147138134128 128 octetsCe n'est pas le code le plus court du monde, mais il s'exécute en O (log n) et sur des nombres de taille arbitraire:
Cela fait une recherche binaire de la plage [0..n] pour trouver la meilleure approximation inférieure à sqrt (n). Voici une version non golfée:
Edit: enregistré deux octets en remplaçant les clauses "sinon" par "0 <1" comme une version plus courte de "True", et quelques autres en insérant g * g.
De plus, si vous êtes satisfait de O (sqrt (n)), vous pouvez simplement faire
pour 35 personnages, mais qu'est-ce que c'est amusant?
Edit 2: Je viens de réaliser que puisque les paires sont triées par ordre de dictionnaire, au lieu de faire min2Cycle. carte fst, je peux juste faire fst. min2Cycle. Dans le code golfed, cela se traduit par le remplacement de f $ map fst par fst $ f, économisant 4 octets supplémentaires.
Edit 3: sauvé six octets supplémentaires grâce à proudhaskeller!
la source
JavaScript
918886: optimisé pour la vitesseJavaScript 46: non optimisé pour la vitesse
Voici un JSFiddle: http://jsfiddle.net/rmadhuram/1Lnjuo4k/
la source
function s(n){for(a=1;++a*a<n;);return a}
C 95
97Modifier Typedef, suggéré par @Michaelangelo
Cela devrait être plus ou moins une implémentation simple de l'algorithme Heron. La seule bizarrerie réside dans le calcul du débordement d'entier moyen évitant: a = (m + n) / 2 ne fonctionne pas pour les nombres biiiig.
la source
C #
646255Comme il s'agit d'un code-golf (et je suis horrible avec les mathématiques), et que l'exécution n'est qu'une suggestion, j'ai fait l'approche naïve qui s'exécute en temps linéaire:
( test sur dotnetfiddle )
Bien sûr, c'est terriblement lent pour les entrées plus importantes.
la source
return i-1
enreturn--i
?i*i<=a
, est-il garanti que ce soit une arithmétique entière du type habituel? (Je ne connais pas C #.) Si c'est le cas, et si C # permet la conversion implicite d'entiers en booléen comme C le fait, alors vous pourriez être en mesure d'enregistrer un caractère de plus en le changeant ena/i/i
.Decimal
, valeur maximale et précision plus élevées), pour éviter le débordement, car le résultat de la multiplication pourrait potentiellement dépasser un pasUInt64.MaxValue
. Mais C # n'a de toute façon pas de conversions implicites en booléen. Je devrais pouvoir changer lareturn
chose, merci. Je le ferai quand je reviendrai à un ordinateur.Clojure - 51 ou 55 octets
Vérifie tous les nombres de n à 0, donnant le premier où
x^2 <= n
. Le temps d'exécution estO(n - sqrt n)
Anonyme:
Nommé:
Exemple:
la source
Befunge 93 - 48 octets ou 38 caractères
Essayez-le ici.
la source
Cobra - 62
Lot - 74
la source
Haskell,
535049 caractères, O (log n)cette solution implémente la méthode newton-raphson, bien qu'elle recherche des entiers au lieu de flottants. wiki: http://en.wikipedia.org/wiki/Newton%27s_method
la complexité semble concerner O (log n), mais y en a-t-il une preuve? veuillez répondre dans les commentaires.
la source
\g->div(n+g^2)$2*g
enregistre 7 octets.J (10)
Très, très, très inspiré par la réponse de @Dennis :
Et un peu plus long, mais avec de meilleures performances (je suppose):
floor(halve under log)
Pour exécuter, des pièces en retrait sont entrées:
la source
APL - 12 caractères, 19 octets
exemple d'utilisation:
renvoie 4
Vecteur de test
Retour
1 1 1 1 2 2 3 3 4 255 256 4294967296
Essayez en ligne
Un grand merci à : l'utilisateur "ssdecontrol" pour l'algorithme
la source
0
→1
! En utilisant Dyalog APL , vous pouvez définir⎕DIV←1
(que beaucoup utilisent par défaut) pour obtenir le résultat correct.C99 (108 caractères)
Voici ma propre solution en C99, qui est adaptée d'un algorithme dans un article sur Wikipedia . Je suis sûr qu'il doit être possible de faire bien mieux que cela dans d'autres langues.
Golfé:
Partiellement golfé:
Non golfé:
la source
a
, utilisezn
.n
telle sorte que juste avant de revenir, je pouvais affirmer (non illustré) que r ^ 2 <= n <(r + 1) ^ 2. Avec cette assertion omise, il est plus nécessaire de restern
intact.const
dans la version non golfée.JavaScript
7381 (pour se conformer à l'exigence de nombres 64 bits)n=prompt();g=n/3;do{G=g,g=(n/g+g)/2}while(1E-9<Math.abs(G-g))alert(Math.floor(g))
Implémentation de l' algorithme de Heron of Alexandria ...
la source
|0
affecter jusqu'à 32 bits alors qu'ilMath.floor
est plus efficace à 64 bits ... J'ai mis à jour mon code, devant prendre 8 caractères supplémentaires pour le faire ...Powershell (52) Limité à Int32 (-2.147.483.648 à 2.147.483.647)
Je crie sur Powershell en ce moment en essayant de faire fonctionner le dernier cas de test, mais peu importe ce que je fais, Powershell finit par utiliser la variable de pipeline $ _ en tant qu'Int32, et je ne trouve pas de moyen de le contourner pour le moment.
Je vais donc limiter ma réponse pour l'instant. Si je peux trouver une meilleure façon de gérer les uint64, je les modifierai. (Le dernier cas de test est trop gros pour le type Int64 normal de Powershell, au fait!)
Voici quelques cas de test (avec un peu de sortie supplémentaire, j'ai utilisé pour suivre le temps)
Je ne connais pas mes O (), mais cela semble être un saut assez dramatique.
la source
Mise en garde: en 2011, R n'avait pas de support intégré pour les entiers 64 bits comme je l'avais supposé. Ces réponses peuvent être invalides sur cette technicité, mais là encore, R a beaucoup changé au cours des 3 dernières années.
R, 85
En utilisant la méthode de Newton:
qui converge quadratique. +2 caractères pour affecter la fonction à une variable pour l'analyse comparative:
R, 37
Force brute:
Et le même contrôle:
R, 30
L' astuce d'exponentiation bon marché / brillant :
qui se trouve également être très rapide (bien que pas aussi rapide que le intégré):
la source
C, 38
Traduction de ma soumission. Lent mais correct. O (√n). Testé sous OS X (64 bits).
la source
dc, 50 octets
Espacé et expliqué:
la source
C,
139137136 136 octetsMon premier essai au code golf. Il semble que ce soit le plus court en C qui réponde à l'exigence «efficace», car il s'exécute dans le
O(log n)
temps, en utilisant uniquement l'addition et les décalages de bits. Bien que je sois sûr qu'il pourrait être encore plus court ...Cela devrait fonctionner très bien pour les valeurs entières plus grandes aussi longtemps que la
a=32
pièce est remplacée para=NUMBITS/2
.la source
(t++)
au lieu de simplementt++
dans l'affectation àr
?a--+1
comme un moyen d'éviter d'écrirea-- != UINT64_C(-1)
. Avez-vous appris ce truc quelque part ou l'avez-vous inventé vous-même?C - 50 (61 sans global)
Il utilise des variables globales comme paramètre et renvoie une valeur pour économiser de l'espace.
Pas de version globale:
la source
C ++ 125
la source
x+=(d<0)-0.5;
... enregistre 5 caractères supplémentaires?main
c'est une fonction, mais elle ne peut pas être appelée depuis un programme comme lef(y)
serait un.)while((d=x*x-y)>0.5)
place dewhile((d=(x*x-y))>0.5)
. Enregistre 2 caractères supplémentaires. :)