Vérifier si un entier est une puissance de 2 sans utiliser les opérations +, - [fermé]


30

Écrivez un programme qui vérifie si l'entier est une puissance de 2.


Exemple d'entrée:

8

Exemple de sortie:

Yes

Exemple d'entrée:

10

Exemple de sortie:

No

Règles:

  • Ne pas utiliser +, les -opérations.

  • Utilisez une sorte de flux d'entrée pour obtenir le nombre. L'entrée n'est pas censée être initialement stockée dans une variable.

  • Le code le plus court (en octets) gagne.

Vous pouvez utiliser n'importe quelle réponse véridique / fausse (par exemple, true/ false). Vous pouvez supposer que le nombre d'entrée est supérieur à 0.


1
Est-il également autorisé de sortir "vrai" au lieu de "oui" et "faux" au lieu de "non"?
ProgramFOX

2
Oui, vous pouvez utiliser n'importe quelle réponse positive / négative. La question est mise à jour.
gthacoder

1
La predfonction, lorsqu'elle est appliquée à un entier n, renvoie n - 1. Les fonctions telles que celle-ci, qui sont de légers déguisements autour de l'opérateur interdit, sont-elles également interdites?
Wayne Conrad

1
@Wayne comme Golfscript ), ou la plupart des langages basés sur c » --.
Poignée de porte

2
Je sais que nous avons maintenant 3 ans dans le futur, mais les "opérateurs +/-" sont non observables, ou pour le moins faiblement définis.
ATaco

Réponses:


13

GolfScript, 6 caractères, pas de diminutions

~.3/&!

Voici une solution qui n'utilise la x & (x-1)méthode sous aucune forme. Il utilise à la x & (x/3)place. ;-) Sorties 0si faux, 1si vrai.

Explication:

  • ~ évalue la chaîne d'entrée pour la transformer en nombre,
  • .le duplique (pour le suivant &),
  • 3/ le divise par trois (tronquer),
  • & calcule l'ET au niveau du bit de la valeur divisée avec l'original, qui sera nul si et seulement si l'entrée est nulle ou une puissance de deux (c'est-à-dire a au plus un ensemble de bits), et
  • ! nie logiquement cela, mappant zéro à une et toutes les autres valeurs à zéro.

Remarques:

  • Selon les règles clarifiées, zéro n'est pas une entrée valide , donc ce code est OK, même s'il génère1 si l'entrée est zéro.

  • Si l'opérateur de décrémentation GolfScript (est autorisé, la solution à 5 caractères ~.(&! publiée par aditsu est suffisante. Cependant, cela semble aller à l' encontre de l'esprit des règles , sinon de la lettre.

  • J'ai trouvé cette x & (x/3)astuce il y a des années sur la liste de diffusion Fun With Perl. (Je suis sûr que je ne suis pas le premier à le découvrir, mais je l'ai (ré) inventé indépendamment.) Voici un lien vers le message d'origine , y compris une preuve qu'il fonctionne réellement.


Je pense que c'est un peu idiot vraiment, golfscript permet d'écrire la solution exacte que l'OP a voulu exclure sans réellement enfreindre les règles.
Tim Seguine

1
@Tim: OK, en voici un sans décrément, alors. ;)
Ilmari Karonen

comment cela peut-il fonctionner? Par exemple 7/3 = 2 (0010), alors 7 & 2 = 0111 & 0010 = 0010quel est clairement le dernier bit qui n'est pas 1
phuclv

@ LưuVĩnhPhúc: Non, mais le deuxième bit l'est. Essayez de faire une longue division par 3 en binaire et c'est assez évident pourquoi cela se produit toujours si le dividende a plus d'un bit défini.
Ilmari Karonen

ah j'ai mal lu ceci avec "divisible par 2"
phuclv

15

APL (7)

Oui, c'est 7 octets . Supposons pour le moment que j'utilise IBM codepage 907 au lieu d'Unicode, puis chaque caractère est un octet :)

0=1|2⍟⎕

c'est à dire 0 = mod(log(input(),2),1)


Je me demande simplement ce qui se passe si vous lui donnez 0 ou un nombre négatif?
aditsu

@aditsu Je ne sais pas ce qu'est le mod infini 1, mais il ne devrait certainement pas être nul.
Tim Seguine

1
@TimSeguine Mathematica me donne Indeterminatequand j'essaye.
LegionMammal978

7

GolfScript, 11 (pour 1 (vrai) et 0 (faux))

.,{2\?}%?0>

Mettez le numéro sur la pile, puis exécutez.

GolfScript, 22 (pour Oui / Non)

.,{2\?}%?0>'Yes''No'if

J'adore comment convertir 1/ 0vers Yes/No prend autant de code que le défi lui-même: D

Avertissement: EXTRÊMEMENT inefficace;) Cela fonctionne très bien pour les nombres jusqu'à 10000, mais une fois que vous atteignez ce niveau, vous commencez à remarquer un léger décalage.

Explication:

  • .,: se transforme nen n 0..n( .doublon, ,plage 0..n)
  • {2\?}: au pouvoir de 2
  • %: mappez "puissance de 2" sur "0..n" pour qu'il devienne n [1 2 4 8 16 ...]
  • ?0>: vérifie si le tableau contient le nombre (0 est supérieur à l'index)

1
1 octet plus court pour Oui / Non .,{2\?}%?0<'YesNo'3/=:; aussi je pense que vous trichez en demandant de "mettre le numéro sur la pile", vous devriez commencer par un ~.
aditsu

1
Échoue sur 1, qui est 2 ^ 0
Joachim Isaksson

6

Mathematica 28

Numerator[Input[]~Log~2]==1

Pour les puissances entières de 2, le numérateur du log de base 2 sera 1 (ce qui signifie que le log est une fraction unitaire).

Ici, nous modifions légèrement la fonction pour afficher l'entrée présumée. Nous utilisons #à la place de Input[]et ajoutons &pour définir une fonction pure. Il renvoie la même réponse que celle qui serait renvoyée si l'utilisateur saisissait le numéro dans la fonction ci-dessus.

    Numerator[#~Log~2] == 1 &[1024]
    Numerator[#~Log~2] == 1 &[17]

Vrai
Faux

Test de plusieurs numéros à la fois.

    Numerator[#~Log~2] == 1 &&/@{64,8,7,0}

{Vrai, vrai, faux, faux}


4

Perl 6 (17 caractères)

say get.log(2)%%1

Ce programme obtient une ligne de la getfonction STDIN , calcule le logarithme avec la base 2 dessus ( log(2)), et vérifie si le résultat se divise par 1 ( %%1, où %%est divisé par l'opérateur). Pas aussi court que la solution GolfScript, mais je trouve cela acceptable (GolfScript gagne tout de toute façon), mais beaucoup plus rapide (même si Perl 6 est lent en ce moment).

~ $ perl6 -e 'say get.log(2)%%1'
256
True
~ $ perl6 -e 'say get.log(2)%%1'
255
False

2
La raison pour laquelle +et -sont interdits pour ce défi, est que si x & (x - 1)est égal à 0, alors xest une puissance de 2.
ProgramFOX

@ProgramFOX: Je vois. Astuce intéressante.
Konrad Borowski

1
@ProgramFOX Mais x&~(~0*x)fonctionne toujours. Cela ne fait que 2 caractères de plus.
orlp

4

Octave ( 15 23)

EDIT: mis à jour en raison des exigences d'entrée de l'utilisateur;

~mod(log2(input('')),1)

Permet à l'utilisateur de saisir une valeur et de sortir 1 pour vrai, 0 pour faux.

Testé en Octave, devrait également fonctionner en Matlab.


Fonctionne également dans Matlab :)
jub0bs

4

R, 13 11

Basé sur la solution Perl. Renvoie FALSEou TRUE.

!log2(i)%%1

Le paramètre ireprésente la variable d'entrée.

Une version alternative avec entrée utilisateur:

!log2(scan())%%1

4

GolfScript, 5

Sorties 1 pour vrai, 0 pour faux. Basé sur l'idée de user3142747:

~.(&!

Remarque: (est décrément, j'espère que cela ne compte pas comme- :)
Si c'est le cas (et les commentaires du PO suggèrent que cela pourrait le faire), veuillez vous référer à la solution d'Ilmari Karonen à la place.
Pour la sortie Y / N, ajoutez 'NY'1/=à la fin (7 octets supplémentaires).


4

Python, 31

print 3>bin(input()).rfind('1')

31 si vous le faitesbin(input()).rfind('1')<3
Blender

@Blender Bien repéré. J'avais utilisé 2==parce que je pensais que cela devrait aussi fonctionner pour les nombres non positifs. Ce n'est explicitement pas requis par les règles, alors ...
boothby

1
+1. J'allais publier print bin(input()).count('1')<2un total de 31 caractères, mais il est trop similaire au vôtre.
Steven Rumbalski

4

C, 48

main(x){scanf("%i",&x);puts(x&~(x*~0)?"F":"T");}

Peut être plus court si la négation unaire est autorisée, plus longue si les constantes négatives ne sont pas autorisées. Suppose un complément à deux.
orlp

*a une priorité plus élevée que binaire &, vous n'avez pas besoin des parens. Et si la valeur de retour est acceptée (juste demandée), elle exit(x&x*-1)serait beaucoup plus courte.
Kevin

Il y a un -: x*-1.
klingt.net

@ klingt.net oui, mais cela fait partie d'une constante numérique. Techniquement, tel qu'il est libellé actuellement, seul l'opérateur -est interdit.
Kevin

1
@ klingt.net Il l'a remplacé par une version qui n'utilise aucun signe.
orlp

4

J'ai décidé d'utiliser une autre approche, basée sur le nombre d'habitants ou la somme latérale du nombre (le nombre de 1 bits). L'idée est que tous les pouvoirs de deux ont exactement un 1bit, et aucun autre nombre n'en a. J'ai ajouté une version JavaScript parce que je l'ai trouvée amusante, même si elle ne gagnera certainement pas de compétition de golf.

J, 14 15 caractères (sorties 0 ou 1)

1=##~#:".1!:1]1

JavaScript, 76 caractères (sorties vrai ou faux)

alert((~~prompt()).toString(2).split("").map(Number).filter(Boolean).length)

Cela utilise l'addition, qui est empêchée par le défi.
FUZxxl

Huh. Je n'ai aucune idée de ce à quoi je pensais quand j'ai écrit ceci ... Je l'ai corrigé maintenant donc il suit réellement les règles.
FireFly

4

Clip , 9 8 7

!%lnxWO

Lit un nombre depuis stdin.

Explication:

Pour commencer, Z= 0, W= 2et O= 1. Cela permet de placer de Wet à Ocôté de l'autre, alors que l' utilisation 2et 1serait interprété comme le nombre 21 sans espace de séparation (un caractère supplémentaire non désiré). Dans Clip, la fonction modulo ( %) fonctionne sur des non-entiers, donc, pour savoir si une valeur vest un entier, vous vérifiez si vmod 1 = 0. En utilisant la syntaxe Clip, cela s'écrit =0%v1. Cependant, comme les booléens sont stockés sous 1(ou quoi que ce soit d'autre) et 0, vérifier si quelque chose est égal à 0est simplement «ne pas le faire». Pour cela, Clip a l' !opérateur. Dans mon code, vc'est lnx2. xest une entrée de stdin,nconvertit une chaîne en nombre etlabest la base bde log de a. Le programme se traduit donc (de manière plus lisible) par 0 = ((log base 2 of parseInt(readLine)) mod 1).

Exemples:

8

les sorties

1

et

10

les sorties

0

Edit 1: remplacé 0, 1et 2avec Z, OetW .

Edit 2: remplacé =Zpar! .

Également:

Pyth , 5

Compresse encore plus la version Clip, car Pyth a Q pour une entrée déjà évaluée et une fonction log2 (a) au lieu d'un simple journal général (a, b).

!%lQ1

3

Javascript (37)

a=prompt();while(a>1)a/=2;alert(a==1)

Script simple qui se divise simplement par 2 à plusieurs reprises et vérifie le reste.


1
même idée avec une forboucle (également 37 caractères)for(i=prompt();i>1;i/=2){}alert(i==1)
Math chiller

3

Mathématique (21)

IntegerQ@Log2@Input[]

Sans entrée, c'est un peu plus court

IntegerQ@Log2[8]

Vrai

IntegerQ@Log2[7]

Faux


⌊#⌋==#&@Log2@Input[]
alephalpha

1
@alephalpha Cela finit par utiliser 24 octets pour les caractères UTF-8. Un autre programme de 21 octets est Log2@Input[]~Mod~1==0.
LegionMammal978

2

JavaScript, 41 40 caractères

l=Math.log;alert(l(prompt())/l(2)%1==0);

Comment cela fonctionne: vous prenez le logarithme à la base 2 en utilisant l(prompt()) / l(2), et si ce résultat modulo 1 est égal à zéro, alors c'est une puissance de 2.

Par exemple: après avoir pris le logarithme de 8 sur la base 2, vous obtenez 3. 3 modulo 1est égal à 0, donc cela renvoie vrai.

Après avoir pris le logarithme de 7 sur la base 2, vous obtenez 2.807354922057604. 2.807354922057604 modulo 1est égal à 0.807354922057604, ce qui renvoie false.


Vous n'avez pas besoin de convertir l'entrée en un nombre; Math.logle fera déjà : "Chacune des fonctions d'objet Math suivantes applique l'opérateur abstrait ToNumber à chacun de ses arguments ..."
apsillers

Ne souffre-t-il pas d'inexactitudes numériques?
Mark Jeronimus

@MarkJeronimus: Je ne sais vraiment pas. C'est possible, mais je n'ai pas encore rencontré de résultat incorrect.
ProgramFOX

2

JavaScript, 35

Fonctionne pour les octets.

alert((+prompt()).toString(2)%9==1)

Version à 46 caractères , fonctionne pour les nombres à 16 bits.

x=(+prompt()).toString(2)%99;alert(x==1|x==10)

L'astuce fonctionne dans la plupart des langues dynamiques.

Explication: Convertissez le nombre en base 2, interprétez cette chaîne comme base 10, faites modulo 9 pour obtenir la somme des chiffres, qui doit être 1.


Et 0x2ffqu'en est-il de la base 2 1111111111?
Peter Taylor

@PeterTaylor Vous avez raison, corrigé
copie du

donc la vraie chose que vous faites est de vérifier le modulo 10 sans reste, mais vous avez utilisé 9 pour raser un caractère de votre code +1,!
Math chiller

C'est un peu de la triche mais une autre méthode:alert(!(Number.MAX_VALUE%prompt()))
Pluton


2

python 3, 38

print(1==bin(int(input())).count('1'))

python, 32

Cependant, le code ne fonctionne pas dans toutes les versions.

print 1==bin(input()).count('1')

Notez que la solution fonctionne également pour 0 (affichez False).


A voté parce que c'était aussi ma solution.
Josh Caswell

1
Et si vous remplacez ==par &?
SimonT

@SimonT Ce n'est pas vrai. Remplacer le '==' par '&' affichera 1 pour chaque nombre qui a un nombre impair de '1' dans sa représentation binaire. Vérifiez par exemple 7 = 111. Il y en a 3 = 11. Il renverra 11 & 1 = 1.
Gari BN

2

Ruby - 17 caractères (quatrième essai)

p /.1/!~'%b'%gets

Mon meilleur moment est une fusion de la réponse de @ steenslag avec la mienne. Voici mes précédentes tentatives.

Ruby - 19 caractères (troisième essai)

p /10*1/!~'%b'%gets

Ruby - 22 caractères (deuxième essai)

p !('%b'%gets)[/10*1/]

Ruby - 24 caractères (premier essai)

p !!('%b'%gets=~/^10*$/)

il y a toujours un "+" dans votre programme
phuclv

Je sais. : - / J'ai demandé des éclaircissements si «+» et «-» sont strictement interdits, ou s'ils peuvent être utilisés dans d'autres contextes que l'addition et la soustraction. Je suis en train de réécrire malgré tout.
OI

Grande amélioration. Il semble que ce soit le meilleur résultat Ruby jusqu'à présent. J'ai mis à jour le tableau des leaders dans le texte de la question.
gthacoder

@gthacoder Je viens de combiner l'expression régulière de steenslag avec mon formatage binaire. Ne peut certainement pas prendre tout le crédit.
OI

2

K / Kona ( 24 17)

d:{(+/(2_vs x))~1

Renvoie 1 si vrai et 0 si faux. Toute puissance de 2 a un seul bit égal à 1:

2_vs'_(2^'(!10))
(,1
1 0
1 0 0
1 0 0 0
1 0 0 0 0
1 0 0 0 0 0
1 0 0 0 0 0 0
1 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0)

(cela affiche toutes les puissances de 2 (de 0 à 9) en binaire)

Je résume donc toutes les composantes de l'expression binaire de x et vois si elle est égale à 1; si oui x=2^n, sinon non.

... je savais que je pouvais le rendre plus petit


@gthacoder: J'ai réduit le code, j'espère que vous pourrez mettre à jour votre message principal pour refléter cela!
Kyle Kanos

N'est-ce pas une addition supplémentaire? Et la question, euh, ne l'interdit-elle pas?
zgrep

2

C # (54 caractères)

 Math.Log(int.Parse(Console.ReadLine()),2)%1==0?"Y":"N"

La tâche indique clairement que l'entrée n'est pas stockée dans une variable, elle doit être obtenue à partir d'un flux d'entrée d'une sorte (comme stdin), aussi, c'est code-golf , essayez de raccourcir un peu votre code, au moins en supprimant les espaces blancs
mniip

Je pense que tu veux juste dire Int32, pas ToInt32...
Chris

Ouais. Merci d'avoir signalé Chris. Auparavant, c'était Convert.ToInt32 et je voulais le changer en Int32.Parse pour le raccourcir. : D
Merin Nakarmi

2
utiliser intau lieu de Int32pour 2 caractères de moins.
Rik

2

Rebmu (9 caractères)

z?MOl2A 1

Tester

>> rebmu/args [z?MOl2A 1] 7
== false

>> rebmu/args [z?MOl2A 1] 8 
== true

>> rebmu/args [z?MOl2A 1] 9 
== false

Rebmu est un dialecte resserré de Rebol. Le code est essentiellement:

z? mo l2 a 1  ; zero? mod log-2 input 1

Alternative

14 caractères — Rebmu n'a pas de bit au niveau «ET» ET ~

z?AND~aTIddA 3

À Rebol:

zero? a & to-integer a / 3


1

Python, 35

print bin(input()).strip('0')=='b1'

N'utilise pas seulement les opérations +/-, mais toutes les opérations mathématiques à part la conversion en forme binaire.

Autres trucs (intéressants, mais pas pour la compétition):

J'ai également une version regexp (61) :

import re;print re.match(r'^0b10+$',bin(input())) is not None

(J'adore l'idée, mais la fonction d'importation et de correspondance la rend trop longue)

Et une version d'opérations au niveau du bit sympa mais ennuyeuse (31) :

x=input();print x and not x&~-x

(oui, c'est plus court, mais il utilise ~ -x pour décrémenter ce qui contient - opération)


Les réponses de boothby utilisent la même idée que la première, mais sont plus courtes :(
Ivan Anishchuk

1

Python 2.7 ( 30 29 39 37)

EDIT: mis à jour en raison des exigences d'entrée de l'utilisateur;

a=input()
while a>1:a/=2.
print a==1

Force brute, essayez de diviser jusqu'à = 1 (succès) ou <1 (échec)


1
not a%2peut être écrit comme a%2==0. Certes, ce serait plus long dans de nombreuses langues, mais pas en Python.
Konrad Borowski

@xfix Merci, testé et mis à jour.
Joachim Isaksson

1
ou mieux encore, a%2<1.
stand

vous avez un espace après la 2.suppression qui permettrait d'économiser un octet!
Keerthana Prabhakaran

1

Python (33)

print int(bin(input())[3:]or 0)<1

int(bin(input()*2)[3:])<1fonctionne également à partir du shell python avec seulement 25 caractères.
gmatht


1

APL (12 pour 0/1, 27 pour oui / non)

≠/A=2*0,ιA←⍞ 

ou, si nous devons sortir du texte:

3↑(3x≠/A=2*0,ιA←⍞)↓'YESNO '

Lire en A. Former un vecteur 0..A, puis un vecteur 2 0 ..2 A (oui, c'est bien plus que nécessaire), puis un vecteur comparant A à chacun d'eux (résultant en un vecteur de 0 et au plus un 1), puis xor que (il n'y a pas d'opérateur xor dans APL, mais ≠ appliqué aux booléens agira comme un.) Nous avons maintenant 0 ou 1.

Pour obtenir OUI ou NON: multipliez le 0 ou 1 par 3, supprimez ce nombre de caractères de 'OUI NON', puis prenez les 3 premiers caractères de cela.


1

C, 65 octets

main(k){scanf("%i",&k);while(k&&!(k%2))k/=2;puts(k==1?"T":"F");}

Vous pouvez couper 5 caractères en utilisant main(k){..., en vous appuyant sur le inttypage implicite . C'est peut-être UB, mais c'est du golf de code. NE JAMAIS utiliser quelque chose comme ça dans la production, bien sûr.
Kevin

1

Haskell ( 52 50)

k n=elem n$map(2^)[1..n]
main=interact$show.k.read
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.