Pour trouver la dureté numérique d'un entier, prenez sa représentation binaire et comptez le nombre de fois où un début et un retour
1
peuvent être supprimés jusqu'à ce qu'il commence ou se termine par a0
. Le nombre total de bits supprimés est sa dureté numérique.
C'est une explication assez verbeuse - alors décomposons-la avec un exemple concret.
Pour cet exemple, nous utiliserons le nombre 3167. En binaire, c'est:
110001011111
(Notez que, lors de la conversion en binaire, vous devez vous assurer de supprimer les zéros non significatifs)
Il ne commence ni ne se termine par 0
, nous supprimons donc 1 paire de bits:
1 1000101111 1
Et un autre:
11 00010111 11
Mais maintenant, il y a un 0 au début, donc nous ne pouvons plus supprimer de 1
paires. Au total, 4 bits que nous avons supprimés, et donc 4 est la dureté numérique de 3167.
Cependant, pour les nombres qui peuvent être écrits comme 2 n -1 pour n positif (c'est-à-dire qu'ils ne contiennent que 1
dans une représentation binaire), 0 ne sera jamais atteint, et donc tous les bits peuvent être supprimés. Cela signifie que la dureté est simplement la longueur de bits de l'entier.
Le défi
Votre tâche consiste à écrire un programme ou une fonction qui, étant donné un entier non négatif n >= 0
, détermine sa dureté numérique.
Vous pouvez soumettre un programme complet qui effectue des E / S, ou une fonction qui renvoie le résultat. Votre soumission doit fonctionner pour des valeurs comprises n
dans la plage d'entiers standard de votre langue.
Cas de test
Veuillez m'informer si l'une de ces erreurs est incorrecte ou si vous souhaitez suggérer des cas supplémentaires à ajouter.
0 -> 0
1 -> 1
8 -> 0
23 -> 2
31 -> 5
103 -> 4
127 -> 7
1877 -> 2
2015 -> 10
Voici la solution Python non golfée que j'ai utilisée pour générer ces cas de test (non garantis sans bug):
def hardness(num) -> int:
binary = bin(num)[2:]
if binary.count('0') == 0:
return num.bit_length()
revbin = binary[::-1]
return min(revbin.find('0'), binary.find('0')) * 2
1
retourne 1 quand il n'y0
en a pas du tout? Je veux dire, vous ne pouvez pas supprimer suffisamment de 1 de la chaîne pour que cela commence ou se termine0
.Réponses:
Gelée ,
1110 octetsEssayez-le en ligne!
Comment ça marche
la source
Python ,
76696863626057 octetsEssayez-le en ligne!
Comment ça marche
Il s'agit d'une solution récursive qui prend une entrée n et continue à incrémenter k - à partir de 0 - tandis que LSB k (n) (bit à l'index k de droite) et MSB k (n) (bit à l'index k de gauche) sont définis. Une fois terminé, il retourne k si tous les bits de n sont définis et 2k sinon.
Commençons par réécrire le lambda f en fonction nommée F , avec une variable auxiliaire t .
Dans chaque invocation de F , nous décalons d'abord n un total de k unités vers la droite et stockons le résultat dans t . De cette façon, LSB 0 (t) = LSB k (n) , donc t est impair si et seulement si LSB k (n) est défini.
Il est légèrement plus difficile de déterminer si MSB k (n) est défini; c'est ce qui
n & t > t >> 1
réussit. Pour illustrer son fonctionnement, considérons un entier n = 1αβγδεζη 2 de longueur binaire 8 et analysons l'appel de fonction F (n, 3) , c'est-à-dire k = 3 .Nous essayons de déterminer si MSB 3 (n) = γ est défini en examinant la valeur de vérité de la comparaison (n & t> t >> 1) = (1αβγδεζη 2 & 1αβγδ 2 > 1αβγ 2 ) . Examinons les entiers impliqués.
Nous affirmons que γ = 1 si et seulement si n & t> t >> 1 .
Si γ = 1 , alors n & t a une longueur de bit 5 tandis que t >> 1 a une longueur de bit 4 , donc n & t> t >> 1 .
Cela prouve que γ = 1 implique n & t> t >> 1 .
Si n & t> t >> 1 , il y a deux options: soit γ = 1, soit γ = 0 . Dans le premier cas, il n'y a plus rien à prouver.
Dans le second cas, on a que αβγδ 2 ≥ n & t> t >> 1 = 1αβγ 2 .
Puisque αβγδ 2 > 1αβγ 2 , nous devons avoir MSB 0 (αβγδ 2 ) ≥ MSB 0 (1αβγ 2 ) , ce qui signifie que α = 1 .
De cette façon, 1βγδ 2 > 11βγ 2 , nous devons donc avoir MSB 1 (1βγδ 2 ) ≥ MSB 1 (11βγ 2 ) , ce qui signifie que β = 1 .
À son tour, cela implique que 11γδ 2 > 111γ 2 . En se souvenant que γ = 0 dans le second cas, on obtient l'inégalité 110δ 2 > 1110 2 , ce qui est faux puisque MSB 2 (110δ 2 ) = 0 <1 = MSB 2 (1110 2 ) .
Ainsi, seul le premier cas est possible et n & t> t >> 1 implique γ = 1 .
En résumé, si LSB k (n) et MSB k (n) sont définis, t sera impair et n & t> t >> 1 sera Vrai , donc t & (n & t> t >> 1) sera rendement 1 . Cependant, si LSB k (n) ou MSB k (n) n'est pas défini (ou si les deux le sont), t sera pair ou n & t> t >> 1 sera faux , donc t & (n & t> t> > 1) donnera 0 .
L'appel de F avec un seul argument initialise k = 0 . Bien que la condition dont nous avons discuté précédemment soit vérifiée, le code suivant
and
est exécuté, qui (entre autres) appelle récursivement F avec k incrémenté .Une fois que LSB k (n) ou MSB k (n) n'est pas défini, la condition échoue et F (n, k) renvoie 0 . Chacun des k appels de fonction précédents ajoute (n & (n + 1)> 0) + 1 à F (n, k) = 0 , donc F (n) renvoie ((n & (n + 1)> 0) + 1) k .
Maintenant, si tous les bits de n sont égaux (c'est-à-dire, si n est soit 0 ou que tous ses bits sont définis), n + 1 n'aura aucun bit en commun avec n , donc n & (n + 1) = 0 et F (n) renvoie k . Cependant, si n a à la fois des bits définis et non définis, n & (n + 1)> 0 et F (n) renvoie 2k .
la source
input()
,while
Etprint
sont déjà 17 octets ...MATL ,
1312 octetsEssayez-le en ligne! Ou vérifiez tous les cas de test .
Explication
Le code répète chaque chiffre binaire et compte le nombre de fois où il est possible d'en supprimer deux externes.
la source
Python, 82 octets
J'ai l'impression qu'il peut encore être joué au golf, mais j'ai passé un certain temps à essayer différentes méthodes et c'était la plus courte.
Essayez-le en ligne
Bien que cela fonctionne de manière similaire au programme Python de l'OP, je l'ai créé avant la publication de la question, après avoir consulté la question dans le bac à sable, qui ne contenait pas un tel programme.
la source
Python 2, 66 octets
Divise la représentation binaire de l'entrée en morceaux de 1. Compte le nombre de 1 dans le plus petit du premier et du dernier morceau, puis le double, à moins qu'il n'y ait un seul morceau que cela double.
la source
PowerShell ,
109106octetsEssayez-le en ligne!
Prend entrée
$args[0]
, utilise l'appel .NETconvert
iltoString
avec une base2
( par exemple, rendre binaire), puis-split
s cette chaîne sur0
s, les magasins qui en$a
. Important à noter: l'appel .NET ne renvoie pas de zéros non significatifs, donc le premier chiffre est toujours a1
.Il y a donc deux possibilités - la chaîne binaire est toute une, ou il y avait au moins un zéro. On différencie ceux avec un pseudo-ternaire indexé par
$a.count-eq1
. Si le binaire a au moins un zéro, le cas de gauche, on prend le minimum de la longueur de la première[0]
chaîne de1
s et de la dernière[-1]
chaîne (trouvée par|sort
puis[0]
). Le plus court de ceux-ci est le plus de paires que nous pourrions retirer, donc nous multiplions cela par2
. Notez que si la chaîne binaire d'origine se termine par un0
, comme pour l'entrée8
, le[-1].length
sera également0
(car il s'agit d'une chaîne vide), qui, lorsqu'il est multiplié par,2
est toujours0
.Sinon, avec la chaîne binaire tous les uns, nous prenons juste
$b
(qui était précédemment défini pour être la longueur de la première[0]
chaîne, dans ce cas, l'intégralité de la chaîne binaire).Dans les deux cas, ce résultat est laissé sur le pipeline et la sortie est implicite.
la source
JavaScript (ES6), 57 octets
Prend le binaire et essaie de faire correspondre tous
1s
ou à défaut un nombre égal de début et de fin1s
.la source
Rétine , 48 octets
Essayez-le en ligne
Explication:
la source
C #, 133 octets
Fonction qui rend la dureté. Prend un entier de l'argument.
Eh bien, aujourd'hui, je l'ai découvert
'1' + '1' = 98
en C #.la source
'1'
le caractère ASCII 49, et 49 + 49 = 98.1 + 1 = 2
cela ne fonctionnait pas. @FlipTackC,
898885 octetsEnregistré deux octets en raison de @FlipTack soulignant une déclaration inutile.
Appelez
f()
avec le numéro à tester, la sortie est renvoyée par la fonction.Essayez-le sur ideone .
la source
JavaScript (ES6),
5958 octetsCas de test
Afficher l'extrait de code
la source
Gelée , 14 octets
Essayez-le en ligne!
la source
C,
137132122119 1191171149894928785 OctetsIl est temps de commencer à jouer au golf B-)
Voici la preuve
et la sortie;
la source
Java (OpenJDK) ,
181156150 octetsEssayez-le en ligne!
la source
Mathematica,
6356 octetsExplication
Générez la représentation en base 2 de l'entrée, enveloppée d'un
List
. Stockez cela dansl
Si l'élément min de
l
est 1, sortie 1. Sinon, sortie 2. Multipliez ceci par ...Divisé
l
en pistes.Prenez le premier et le dernier élément.
Prenez le total des deux.
Trouvez le plus petit entre les deux.
(Multipliez le premier résultat (1 ou 2) par ce résultat).
la source
Octave,
5654 octetsEssayez-le en ligne!
Explication:
représentation binaire de
n
Prendre les minutes cumulées
d
et les minutes cumulées de retournéesd
faire une multiplication matricielle
multipliez par 2 si tous les chiffres sont 1;
la source
Pyth, 18 octets
Un programme qui prend l'entrée d'un entier et imprime le résultat.
Suite de tests (première ligne de mise en forme)
Comment ça marche
la source
APL, 26 octets
Cas de test:
Explication:
la source
J, 22 octets
Ceci est basé sur l'astuce soignée tirée de ce défi .
Essayez-le en ligne!
Explication
la source
PHP,
8374 octets3 + 6 octets enregistrés par Jörg
prend l'entrée de STDIN; courir avec
-nR
.panne
la source
<?=~($s=decbin($argn))[$a=strspn($s,1)]?2*min($a,strspn(strrev($s),1)):$a;
JavaScript (ES6), 83 octets
Non golfé:
la source
Mathematica, 62 octets
Fonction pure où
#
représente le premier argument.(h=0;...;h)&
définith=0
, fait un tas de choses...
, puis retourneh
(la dureté). Regardons le tas de choses:Merci à Greg Martin de m'avoir présenté cette astuce .
la source
Haskell ,
9492 octetsEssayez-le en ligne! Usage:
Explication:
b
convertit un nombre en binaire et renvoie en premier une liste de zéro et de uns avec le bit le moins significatif. Dansh
, cette liste est inversée et multipliée par élément avec la liste d'origine, puisspan(>0)
se divise après le1
s initial :Le tuple résultant est mis en correspondance avec le modèle
(c,_:_)
où_:_
correspond à toute liste non vide, doncc = [1,1]
. Parce que les octets sont supprimés à l'avant et à l'arrière, ilc++c = [1,1,1,1]
est renvoyé et finalement résumé pour donner la dureté numérique .Si la deuxième liste du tuple est vide, alors la représentation binaire n'en contient que quelques-unes, et le nombre de celles-ci est la dureté numérique. Avec le modèle correspondant, les
h
retours ont échouén
, ce qui est à nouveau résumé.la source
Perl, 61 octets
Le cœur de ceci est le regex
/^(1+).*\1$/
où 2 fois la longueur de$1
est la réponse. Le reste du code est en surcharge et traite du cas spécial de all 1.la source
sprintf
arguments. En outre, l'utilisation de-p
flag vous permettra d'écrire un programme complet qui sera plus court que votre fonction, car vous pourrez l'omettresub f{...}
(à la place, vous devrez terminer$_=...
mais c'est toujours une amélioration de 4 octets). Enfin, au lieu de votrelength(...)
, vous pouvez le faire/0/&&s/^(1+).*\1$/$1$1/;$_=y///c
. Cela devrait vous amener à 51 octets.PHP, 65 octets
Version en ligne
la source
CJam, 14 octets
Explication:
la source