Compruebe si un número entero es una potencia de 2 sin usar operaciones +, - [cerrado]

30

Escriba un programa que verifique si el entero es una potencia de 2.


Entrada de muestra:

8

Salida de muestra:

Yes

Entrada de muestra:

10

Salida de muestra:

No

Reglas:

  • No utilices +, -operaciones.

  • Use algún tipo de flujo de entrada para obtener el número. No se supone que la entrada se almacene inicialmente en una variable.

  • El código más corto (en bytes) gana.

Puede usar cualquier respuesta de verdad / falsedad (por ejemplo, true/ false). Puede suponer que el número de entrada es mayor que 0.

gthacoder
fuente
1
¿También se permite mostrar "verdadero" en lugar de "sí" y "falso" en lugar de "no"?
ProgramFOX
2
Sí, puedes usar cualquier respuesta positiva / negativa. La pregunta está actualizada.
gthacoder
1
La predfunción, cuando se aplica a un número entero n, devuelve n - 1. ¿Están también prohibidas funciones como esta, que son disfraces delgados alrededor del operador prohibido?
Wayne Conrad el
1
@Wayne como los de golfscript ), o la mayoría de los lenguajes basados ​​en c ' --.
Pomo de la puerta
2
Sé que tenemos 3 años en el futuro ahora, pero "operadores +/-" no es observable, o al menos débilmente definido.
ATaco

Respuestas:

13

GolfScript, 6 caracteres, sin decrementos

~.3/&!

Aquí hay una solución que no usa el x & (x-1)método de ninguna forma. Utiliza en su x & (x/3)lugar. ;-) Salidas 0si es falso, 1si es verdadero.

Explicación:

  • ~ evalúa la cadena de entrada para convertirla en un número,
  • .lo duplica (para el subsiguiente &),
  • 3/ lo divide por tres (truncando)
  • & calcula el AND a nivel de bit del valor dividido con el original, que será cero si y solo si la entrada es cero o una potencia de dos (es decir, tiene como máximo un conjunto de bits), y
  • ! lógicamente niega esto, asignando cero a uno y todos los demás valores a cero.

Notas:

  • De acuerdo con las reglas aclaradas, el cero no es una entrada válida , por lo que este código está bien, aunque salga 1si la entrada es cero.

  • Si (se permite el operador de decremento GolfScript , entonces la solución de 5 caracteres ~.(&! publicada por aditsu es suficiente. Sin embargo, parece ir en contra del espíritu de las reglas , si no de la carta.

  • Se me ocurrió el x & (x/3)truco hace años en la lista de correo Fun With Perl. (Estoy seguro de que no soy el primero en descubrirlo, pero lo (re) inventé independientemente). Aquí hay un enlace a la publicación original , que incluye una prueba de que realmente funciona.

Ilmari Karonen
fuente
Creo que es un poco tonto realmente, golfscript le permite a uno escribir la solución exacta que el OP quería excluir sin romper las reglas.
Tim Seguine
1
@Tim: OK, aquí hay uno sin decrementos, entonces. ;)
Ilmari Karonen
¿Cómo puede funcionar esto? Por ejemplo 7/3 = 2 (0010), así 7 & 2 = 0111 & 0010 = 0010que claramente el último bit no es 1
phuclv
@ LưuVĩnhPhúc: No, pero el segundo bit es. Intente hacer una división larga por 3 en binario y es bastante obvio por qué esto siempre sucede si el dividendo tiene más de un bit establecido.
Ilmari Karonen
ah, leí mal esto con "divisible por 2"
phuclv
15

APL (7)

Sí, eso es 7 bytes . Suponga por el momento que estoy usando la página de códigos 907 de IBM en lugar de Unicode y luego cada carácter es un byte :)

0=1|2⍟⎕

es decir 0 = mod(log(input(),2),1)

marinus
fuente
Me pregunto, ¿qué sucede si le das 0 o un número negativo?
aditsu
@aditsu No sé qué es infinity mod 1, pero ciertamente no debería ser cero.
Tim Seguine
1
@TimSeguine Mathematica me da Indeterminatecuando lo intento.
LegionMammal978
7

GolfScript, 11 (para 1 (verdadero) y 0 (falso))

.,{2\?}%?0>

Pon el número en la pila y luego corre.

GolfScript, 22 (para Sí / No)

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

Me encanta cómo convertir 1/ 0a Yes/ Notoma tanto código como el desafío en sí: D

Advertencia: EXTREMADAMENTE ineficiente;) Funciona bien para números de hasta 10000, pero una vez que llega tan alto, comienza a notar un ligero retraso.

Explicación:

  • .,: se convierte nen n 0..n( .duplicado, ,0..n rango)
  • {2\?}: al poder de 2
  • %: asigna "potencia de 2" sobre "0..n" para que se convierta n [1 2 4 8 16 ...]
  • ?0>: comprueba si la matriz contiene el número (0 es mayor que el índice)
Pomo de la puerta
fuente
1
1 byte más corto para Sí / No .,{2\?}%?0<'YesNo'3/=:; También creo que estás haciendo trampa al preguntar "Pon el número en la pila", debes comenzar con a ~.
aditsu
1
Falla en 1, que es 2 ^ 0
Joachim Isaksson
6

Mathematica 28

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

Para potencias enteras de 2, el numerador del registro de base 2 será 1 (lo que significa que el registro es una fracción unitaria).

Aquí modificamos la función ligeramente para mostrar la entrada presunta. Usamos #en lugar de Input[]y agregamos &para definir una función pura. Devuelve la misma respuesta que se devolvería si el usuario ingresara el número en la función anterior.

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

Verdadero
falso

Prueba de varios números a la vez.

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

{Verdadero, verdadero, falso, falso}

DavidC
fuente
4

Perl 6 (17 caracteres)

say get.log(2)%%1

Este programa obtiene una línea de la getfunción STDIN , calcula el logaritmo con la base 2 ( log(2)), y comprueba si el resultado se divide por 1 ( %%1, donde %%se divide por operador). No es tan corto como la solución GolfScript, pero me parece aceptable (GolfScript gana todo de todos modos), pero mucho más rápido (incluso teniendo en cuenta que Perl 6 es lento en este momento).

~ $ perl6 -e 'say get.log(2)%%1'
256
True
~ $ perl6 -e 'say get.log(2)%%1'
255
False
Konrad Borowski
fuente
2
La razón de que +y -están prohibidos para este desafío, es porque si x & (x - 1)es igual 0, entonces xes una potencia de 2.
ProgramFOX
@ProgramFOX: Ya veo. Truco interesante
Konrad Borowski
1
@ProgramFOX Pero x&~(~0*x)aún funciona. Eso es solo 2 caracteres más.
orlp
4

Octava ( 15 23)

EDITAR: actualizado debido al requisito de entrada del usuario;

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

Permite al usuario ingresar un valor y generar 1 para verdadero, 0 para falso.

Probado en Octave, debería funcionar también en Matlab.

Joachim Isaksson
fuente
También funciona en Matlab :)
jub0bs
4

R, 13 11

Basado en la solución Perl. Devoluciones FALSEo TRUE.

!log2(i)%%1

El parámetro irepresenta la variable de entrada.

Una versión alternativa con entrada del usuario:

!log2(scan())%%1
Sven Hohenstein
fuente
4

GolfScript, 5

Salidas 1 para verdadero, 0 para falso. Según la idea del usuario3142747:

~.(&!

Nota: (es decremento, es de esperar que no cuente como -:)
Si lo hace (y los comentarios del OP sugieren que podría serlo ), consulte la solución de Ilmari Karonen .
Para salida Y / N, agregue 'NY'1/=al final (7 bytes más).

aditsu
fuente
4

Python, 31

print 3>bin(input()).rfind('1')
boothby
fuente
31 si lo hacesbin(input()).rfind('1')<3
Blender
@Blender Bien manchado. Lo usé 2==porque pensé que también debería funcionar para números no positivos. Que explícitamente no está requerido por las reglas, así que ...
boothby
1
+1. Iba a publicar print bin(input()).count('1')<2en un total de 31 caracteres, pero es muy similar al tuyo.
Steven Rumbalski
4

C, 48

main(x){scanf("%i",&x);puts(x&~(x*~0)?"F":"T");}
orlp
fuente
Puede ser más corto si se permite negación unaria, es más largo si no se permiten constantes negativas. Asume el complemento de dos.
orlp
*tiene mayor prioridad que el binario &, no necesita los parens. Y si se acepta el valor de retorno (solo preguntado) exit(x&x*-1)sería mucho más corto.
Kevin
Hay una -: x*-1.
klingt.net
@ klingt.net sí, pero eso es parte de una constante numérica. Técnicamente, como está redactado ahora, solo el operador -está prohibido.
Kevin
1
@ klingt.net Lo reemplazó con una versión que no usa signos.
orlp
4

Decidí usar otro enfoque, basado en el recuento de población o la suma lateral del número (el número de 1 bits). La idea es que todas las potencias de dos tienen exactamente un 1bit, y ningún otro número lo tiene. Agregué una versión de JavaScript porque me pareció divertido, aunque ciertamente no ganará ninguna competencia de golf.

J, 14 15 caracteres (salidas 0 o 1)

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

JavaScript, 76 caracteres (salidas verdaderas o falsas)

alert((~~prompt()).toString(2).split("").map(Number).filter(Boolean).length)
Luciérnaga
fuente
Esto utiliza la suma, que está impedido por el desafío.
FUZxxl
Huh No tengo idea de lo que estaba pensando cuando escribí esto ... Lo arreglé ahora, por lo que en realidad sigue las reglas.
FireFly
4

Clip , 9 8 7

!%lnxWO

Lee un número de stdin.

Explicación:

Para empezar, Z= 0, W= 2y O= 1. Esto permite la colocación de Wy Ojunto a la otra, mientras que el uso 2y 1sería interpretado como el número 21 sin un espacio de separación (un carácter adicional no deseado). En Clip, la función de módulo ( %) funciona en no enteros, por lo tanto, para determinar si algún valor ves un entero, verifica si vmod 1 = 0. Usando la sintaxis de Clip, esto se escribe como =0%v1. Sin embargo, como los booleanos se almacenan como 1(o cualquier otra cosa) y 0, comprobar si algo es igual a 0'simplemente' no es así. Para esto, Clip tiene el !operador. En mi código, ves lnx2. xes una entrada de stdin,nconvierte una cadena en un número y labes la base bde registro de a. Por lo tanto, el programa se traduce (más legible) a 0 = ((log base 2 of parseInt(readLine)) mod 1).

Ejemplos:

8

salidas

1

y

10

salidas

0

Edición 1: reemplazado 0, 1y 2con Z, Oy W.

Edición 2: reemplazado =Zcon !.

También:

Pyth , 5

Comprime aún más la versión de Clip, ya que Pyth tiene Q para la entrada ya evaluada y una función log2 (a) en lugar de solo el registro general (a, b).

!%lQ1
bcsb1001
fuente
3

Javascript (37)

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

Script simple que solo divide por 2 repetidamente y verifica el resto.

Joachim Isaksson
fuente
1
misma idea con un forbucle (también 37 caracteres)for(i=prompt();i>1;i/=2){}alert(i==1)
Enfriador matemático
3

Mathematica (21)

IntegerQ@Log2@Input[]

Sin entrada es un poco más corto

IntegerQ@Log2[8]

Cierto

IntegerQ@Log2[7]

Falso

ybeltukov
fuente
⌊#⌋==#&@Log2@Input[]
alephalpha
1
@alephalpha Eso termina usando 24 bytes para los caracteres UTF-8. Otro programa de 21 bytes es Log2@Input[]~Mod~1==0.
LegionMammal978
2

JavaScript, 41 40 caracteres

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

Cómo funciona: tomas el logaritmo en la base 2 usando l(prompt()) / l(2), y si ese resultado el módulo 1 es igual a cero, entonces es una potencia de 2.

Por ejemplo: después de tomar el logaritmo de 8 en la base 2, obtienes 3. 3 modulo 1es igual a 0, por lo que esto devuelve verdadero.

Después de tomar el logaritmo de 7 en la base 2, obtienes 2.807354922057604. 2.807354922057604 modulo 1es igual a 0.807354922057604, entonces esto devuelve falso.

ProgramFOX
fuente
No necesita emitir la entrada a un número; Math.logya lo hará : "Cada una de las siguientes funciones de objetos matemáticos aplica el operador abstracto ToNumber a cada uno de sus argumentos ..."
apsillers
¿No sufre de imprecisiones numéricas?
Mark Jeronimus
@ MarkJeronimus: En realidad no lo sé. Podría ser, pero aún no he encontrado un resultado incorrecto.
ProgramFOX
2

JavaScript, 35

Funciona para bytes.

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

Versión de 46 caracteres , funciona para números de 16 bits.

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

El truco funciona en la mayoría de los lenguajes dinámicos.

Explicación: Convierta el número a base 2, interprete esa cadena como base 10, haga el módulo 9 para obtener la suma de dígitos, que debe ser 1.

dupdo
fuente
¿Qué pasa 0x2ff, que en la base 2 es 1111111111?
Peter Taylor
@PeterTaylor Tienes razón, arreglado
copia el
así que lo que estás haciendo es verificar el módulo 10 sin resto, ¡pero usaste 9 para depilar un carácter de tu código +1!
Enfriador de matemáticas el
Esto es un poco trampa pero otro método:alert(!(Number.MAX_VALUE%prompt()))
Plutón
2

Perl 5.10+, 13 + 1 = 14 caracteres

say!($_&$_/3)

Utiliza el mismo método de un hilo antiguo de FWP como mi entrada de GolfScript . Imprime 1si la entrada es una potencia de dos, y una línea vacía de lo contrario.

Necesita ser manejado con perl -nE; El n costo es de un personaje adicional , para un total de 14 caracteres. Alternativamente, aquí hay una versión de 18 caracteres que no necesita n:

say!(($_=<>)&$_/3)
Ilmari Karonen
fuente
2

pitón 3, 38

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

pitón, 32

Sin embargo, el código no funciona en todas las versiones.

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

Tenga en cuenta que la solución también funciona para 0 (print False).

Gari BN
fuente
Votaron porque esta también era mi solución.
Josh Caswell
1
¿Qué pasa si reemplazas ==con &?
SimonT
@SimonT Esto no es cierto. Reemplazando el '==' con '&' imprimirá 1 por cada número que tenga un número impar de '1' en su representación binaria. Verifique, por ejemplo, 7 = 111. Hay 3 = 11 unos. Volverá 11 & 1 = 1.
Gari BN
2

Ruby - 17 caracteres (cuarto intento)

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

Mi mejor momento actual es una fusión de la respuesta de @ steenslag con la mía. A continuación están mis intentos anteriores.

Ruby - 19 caracteres (tercer intento)

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

Ruby - 22 caracteres (segundo intento)

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

Ruby - 24 caracteres (primer intento)

p !!('%b'%gets=~/^10*$/)
OI
fuente
todavía hay un "+" en su programa
phuclv
Lo sé. : - / He pedido aclaraciones si '+' y '-' están estrictamente prohibidos, o si se pueden usar en otros contextos además de la suma y la resta. Estoy en el proceso de reescribir independientemente.
OI
Gran mejora. Parece que es el mejor resultado de Ruby hasta ahora. Actualicé la tabla de líderes en el texto de la pregunta.
gthacoder
@gthacoder Acabo de combinar la expresión regular de steenslag con mi formato binario. Definitivamente no puedo tomar todo el crédito.
OI
2

K / Kona ( 24 17)

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

Devuelve 1 si es verdadero y 0 si es falso. Cualquier potencia de 2 tiene un solo bit igual a 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)

(esto imprime todos los poderes de 2 (de 0 a 9) en binario)

Así que resumo todos los componentes de la expresión binaria de xy veo si es igual a 1; en caso afirmativo x=2^n, de lo contrario no.

... sabía que podía hacerlo más pequeño

Kyle Kanos
fuente
@gthacoder: Hice el código más pequeño, ¡espero que pueda actualizar su publicación principal para reflejar esto!
Kyle Kanos
¿No usa esto además? ¿Y la pregunta, err, no lo prohíbe?
zgrep
2

C # (54 caracteres)

 Math.Log(int.Parse(Console.ReadLine()),2)%1==0?"Y":"N"
Merin Nakarmi
fuente
La tarea establece claramente que la entrada no se almacena en una variable, debe obtenerse de un flujo de entrada de algún tipo (como stdin), también, esto es código golf , intente acortar un poco su código, al menos eliminando espacios en blanco
mniip
Creo que solo quieres decir Int32, no ToInt32...
Chris
Ya ya Gracias por señalar a Chris. Anteriormente era Convert.ToInt32 y quería cambiarlo a Int32.Parse para acortarlo. : D
Merin Nakarmi
2
use en intlugar de Int322 caracteres menos.
Rik
2

Rebmu (9 caracteres)

z?MOl2A 1

Prueba

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

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

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

Rebmu es un dialecto restringido de Rebol. El código es esencialmente:

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

Alternativa

14 caracteres: Rebmu no tiene un bit 'mushed' Y ~

z?AND~aTIddA 3

En Rebol:

zero? a & to-integer a / 3
rgchris
fuente
1

GTB , 46 bytes

2→P`N[@N=Pg;1P^2→P@P>1E90g;2]l;2~"NO"&l;1"YES"
Timtech
fuente
1

Python, 35

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

No utiliza no solo operaciones +/-, sino también operaciones matemáticas además de la conversión a forma binaria.

Otras cosas (interesantes, pero no para la competencia):

También tengo una versión regexp (61) :

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

(Me encanta la idea, pero la función de importar y combinar hace que sea demasiado larga)

Y agradable, pero aburrida versión de operaciones bit a bit (31) :

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

(sí, es más corto, pero usa ~ -x para la disminución que contiene la operación)

Ivan Anishchuk
fuente
Las respuestas de boothby usan la misma idea que la primera, pero es más corta :(
Ivan Anishchuk
1

Python 2.7 ( 30 29 39 37)

EDITAR: actualizado debido al requisito de entrada del usuario;

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

Fuerza bruta, intente dividir hasta = 1 (éxito) o <1 (fracaso)

Joachim Isaksson
fuente
1
not a%2se puede escribir como a%2==0. De acuerdo, esto sería más largo en muchos idiomas, pero no en Python.
Konrad Borowski
@xfix Gracias, probado y actualizado.
Joachim Isaksson
1
o incluso mejor, a%2<1.
stand de
Tienes un espacio después de 2.Eliminar que ahorraría un byte.
Keerthana Prabhakaran
1

Pitón (33)

print int(bin(input())[3:]or 0)<1
Licuadora
fuente
int(bin(input()*2)[3:])<1También funciona desde el shell de Python con solo 25 caracteres.
gmatht
1

Rubí, 33 , 28 , 25

p /.1/!~gets.to_i.to_s(2)
steenslag
fuente
1

APL (12 para 0/1, 27 para sí / no)

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

o, si debemos generar texto:

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

Lea en A. Forme un vector 0..A, luego un vector 2 0 ..2 A (sí, eso es mucho más de lo necesario), luego un vector que compara A con cada uno de ellos (lo que resulta en un vector de 0 y como máximo uno 1), luego xor que (no hay operador xor en APL, pero ≠ aplicado a booleanos actuará como uno.) Ahora tenemos 0 o 1.

Para obtener SÍ o NO: multiplique el 0 o 1 por 3, elimine este número de caracteres de 'SÍ NO', luego tome los primeros 3 caracteres de este.

Mark Plotnick
fuente
1

C, 65 bytes

main(k){scanf("%i",&k);while(k&&!(k%2))k/=2;puts(k==1?"T":"F");}
vershov
fuente
Puede cortar 5 caracteres mediante el uso main(k){..., confiando en la intescritura implícita . Puede ser UB, pero este es el código de golf. NUNCA use algo así en la producción, por supuesto.
Kevin
1

Haskell ( 52 50)

k n=elem n$map(2^)[1..n]
main=interact$show.k.read
Zeta
fuente