Esta es una versión del desafío reciente ¿Es este número una potencia entera de -2? con un conjunto diferente de criterios diseñados para resaltar la naturaleza interesante del problema y hacer que el desafío sea más difícil. Puse algo de consideración aquí .
El desafío que Toby afirma maravillosamente en la pregunta vinculada es:
Hay formas inteligentes de determinar si un número entero es una potencia exacta de 2. Eso ya no es un problema interesante, así que determinemos si un entero dado es una potencia exacta de -2 . Por ejemplo:
-2 => yes: (-2)¹ -1 => no 0 => no 1 => yes: (-2)⁰ 2 => no 3 => no 4 => yes: (-2)²
Reglas:
- Un número entero es de 64 bits, con signo, complemento de dos. Este es el único tipo de datos con el que puede trabajar.
- Solo puede usar las siguientes operaciones. Cada uno de estos cuenta como una operación.
n << k
,n >> k
: Desplazamiento a la izquierda / derechan
pork
bits. El bit de signo se extiende en el desplazamiento a la derecha.n >>> k
: Desplazamiento a la derecha pero no extiende el bit de signo. Los 0 se desplazan.a & b
,a | b
,a ^ b
: Bitwise AND, OR, XOR.a + b
,a - b
,a * b
: Sumar, restar, multiplicar.~b
: Inversión bit a bit.-b
: Negación del complemento a dos.a / b
,a % b
: Divide (cociente entero, se redondea hacia 0) y módulo.- El módulo de números negativos utiliza las reglas especificadas en C99 :
(a/b) * b + a%b
será iguala
. Así5 % -3
es2
y-5 % 3
es-2
: 5 / 3
es1
,5 % 3
es2
, como 1 * 3 + 2 = 5.-5 / 3
es-1
,-5 % 3
es-2
, como -1 * 3 + -2 = -5.5 / -3
es-1
,5 % -3
es2
, como -1 * -3 + 2 = 5.-5 / -3
es1
,-5 % -3
es-2
, como 1 * -3 + -2 = -5.- Tenga en cuenta que el
//
operador de división de piso de Python no satisface la propiedad de "redondear hacia 0" de la división aquí, y el%
operador de Python tampoco cumple con los requisitos.
- El módulo de números negativos utiliza las reglas especificadas en C99 :
- Las asignaciones no cuentan como una operación. Como en C, las asignaciones evalúan el valor del lado izquierdo después de la asignación: se
a = (b = a + 5)
estableceb
ena + 5
, luego se establecea
enb
, y cuenta como una operación. - Las asignaciones compuestas pueden usarse como
a += b
mediosa = a + b
y contar como una operación.
- Puede usar constantes enteras, no cuentan como nada.
- Los paréntesis para especificar el orden de las operaciones son aceptables.
- Puedes declarar funciones. Las declaraciones de funciones pueden tener cualquier estilo que sea conveniente para usted, pero tenga en cuenta que los enteros de 64 bits son el único tipo de datos válido. Las declaraciones de funciones no cuentan como operaciones, pero una llamada de función cuenta como una. Además, para ser claros: las funciones pueden contener múltiples
return
declaraciones yreturn
se permiten mensajes de correo electrónico desde cualquier punto. Elreturn
sí mismo no cuenta como una operación. - Puede declarar variables sin costo.
- Puede usar
while
bucles, pero no puede usarif
ofor
. Los operadores utilizados en lawhile
condición cuentan para su puntaje.while
los bucles se ejecutan siempre que su condición se evalúe a un valor distinto de cero (un "verdadero" 0 en lenguajes que tienen este concepto no es un resultado válido). Ya que se permite a principios de retención, se le permite utilizarbreak
, así - Se permite el desbordamiento / subflujo y no se realizará una fijación de valor. Se trata como si la operación realmente sucediera correctamente y luego se truncara a 64 bits.
Criterios de puntuación / victoria:
Su código debe producir un valor que no sea cero si la entrada es una potencia de -2, y cero en caso contrario.
Este es el código atómico de golf . Su puntaje es el número total de operaciones presentes en su código (como se definió anteriormente), no el número total de operaciones que se ejecutan en tiempo de ejecución. El siguiente código:
function example (a, b) {
return a + ~b;
}
function ispowerofnegtwo (input) {
y = example(input, 9);
y = example(y, 42);
y = example(y, 98);
return y;
}
Contiene 5 operaciones: dos en la función y tres llamadas a funciones.
No importa cómo presente su resultado, use lo que sea conveniente en su idioma, ya sea en última instancia, almacenando el resultado en una variable, devolviéndolo de una función, o lo que sea.
El ganador es la publicación que es demostrablemente correcta (proporcione una prueba informal o formal si es necesario) y tiene el puntaje más bajo como se describió anteriormente.
Bonus muy difícil modo desafío!
Para tener la oportunidad de ganar absolutamente nada, excepto la capacidad potencial de impresionar a las personas en las fiestas, envíe una respuesta sin usar while
bucles Si se presentan suficientes de estos, incluso podría considerar dividir los grupos ganadores en dos categorías (con y sin bucles).
Nota: Si desea proporcionar una solución en un lenguaje que solo sea compatible con enteros de 32 bits, puede hacerlo, siempre que justifique suficientemente que seguirá siendo correcta para enteros de 64 bits en una explicación.
Además: ciertas características específicas del idioma pueden permitirse sin costo si no eluden las reglas, pero son necesarias para obligar a su idioma a comportarse de acuerdo con las reglas anteriores . Por ejemplo (artificial), permitiré una comparación libre no igual a 0 en while
bucles, cuando se aplica a la condición como un todo, como una solución para un lenguaje que tiene ceros "verdaderos". No se permiten intentos claros de aprovechar este tipo de cosas , por ejemplo, el concepto de valores "verdaderos" 0 o "indefinidos" no existe en el conjunto de reglas anterior, por lo que no se puede confiar en ellos.
m ^= s
que sea todavía impresionante, y creo que estaría totalmente bien hacer la sustitución para mejorarlo aún más.while
ybreak
no permitirif
?if (x) { ... }
es equivalente awhile (x) { ... break; }
.break
y los retornos tempranos son la parte lamentable) y es una larga historia y una lección aprendida en reglas para futuros desafíos. ¡Siempre existe la versión "bonus"! :)if
yfor
no están permitidos?int x=condition; while (x) { ... x=0; }
es gratis, solo más código. Lo mismo con c-stylefor
.Respuestas:
C ++, 15 operaciones
No tengo idea de por qué los
while
bucles están permitidos ya que destruyen todo el desafío. Aquí hay una respuesta sin ninguna:fuente
while
bucles destruyen todo el desafío ?while
va en contra de eso en todos los sentidos.n
o algo así.uint64_t
, porque esa es la única manera de conseguir el desplazamiento a la derecha sin extensión de signo.)Python 2 , 3 operaciones
Pruébalo en línea!
Las operaciones son
>>
,&
,/
.La idea es dividir repetidamente por -2. Powers de -2 cadena abajo a 1:
-8 -> 4 -> -2 -> 1
. Si damos con un1
, acepta. Si tocamos un número impar antes de golpear1
, rechazar. También tenemos que rechazar0
, lo que siempre se va solo.Los
while n>>1:
bucles hastan
son 0 o 1. Cuando el bucle se rompe,n
se devuelve y1
es una salida de0
Verdad y una de Falsey. Dentro del ciclo, rechazamos aplicar repetidamenten -> n/-2
y rechazamos cualquier imparn
.Como
/
solo se usa en valores pares, su comportamiento de redondeo nunca entra en juego. Por lo tanto, no importa que Python redondea de manera diferente a la especificación.fuente
while n&1
lugar deif n&1
?if
.Moho,
1412 operaciones (sin bucles)Requiere optimización (
-O
) o-C overflow-checks=no
para habilitar la resta desbordante en lugar de pánico.(Para aclarar:
!x
es bit a bit, NO aquí, no es lógico, NO)Casos de prueba:
Pruébalo en línea!
La idea es verificar si | x | es una potencia de 2 (usando
(y & (y - 1)) == 0
como de costumbre). Si x es una potencia de 2, entonces verificamos (1) cuándox >= 0
, también debería ser una potencia par de 2, o (2) cuándox < 0
, debería ser una potencia impar de 2. Verificamos esto&
marcando el "bad_power_of_two
"enmascara 0x ... aaaa cuandox >= 0
(produce 0 solo cuando es una potencia par), o 0x ... 5555 cuandox < 0
.fuente
~((r | -r) >> 63)
truco para terminar arreglando mi respuesta.Haskell,
23 operacionesDefine una función recursiva
f(n)
. Las operaciones utilizadas son la función call (f
), division (div
) y bitwise y (.&.
).No contiene bucles debido al hecho de que Haskell no tiene declaraciones de bucle :-)
fuente
f 0
,f 1
,f n ...
aquí, ya que son esencialmenteif
's en el encubrimiento, aunque, de nuevo, me permitowhile
+break
y principios delreturn
s, por lo que parece justo. Si bien parece aprovechar que mi conjunto de reglas se deja inadvertidamente abierto a la interpretación, es una buena solución.|
s están especialmente en el aire. Dicho esto, esto viola una regla en particular de una manera menos discutible: la comparación==
no está permitida. Nótese, sin embargo, que si mi interpretación de este código es correcto, el uso de booleanos aquí no parece aceptable como la sustitución de valores enteros arbitrarios en su lugar no parece cambiar los resultados, y son más de una forma de presentación final.==
porque no hay otra forma de transmitir desde oInt
haciaBool
"Truthy" en Haskell. Si la coincidencia de patrones y los guardias violan laif
regla de "no s" es su decisión ;-)Python 3,
10 u 119 operacionesDevoluciones
5
por poderes de-2
, de lo0
contrariofuente
C, 5 operaciones
C, 10 operaciones, sin bucles
C, 1 operación
fuente
Asamblea, 1 operación
Utiliza una gran tabla de búsqueda para determinar si el número es una potencia de 2. Puede expandir esto a 64 bits, pero encontrar una computadora para almacenar esa cantidad de datos queda como ejercicio para el lector :-P
fuente
C, 31 operaciones
Demo en vivo
Mi idea es simple, si es una potencia de dos, entonces si su registro es par, entonces tiene que ser positivo, de lo contrario su registro tiene que ser extraño.
fuente
C, 7 operaciones
o:
C, 13 operaciones sin bucles como condicionales
Explicación:
n&-n
produce el bit de ajuste más bajo den
.a
es el valor absoluto negado den/2
, necesariamente negativo porque/2
impide el desbordamiento de la negación.a/x
es cero solo sia
es una potencia exacta de dos; de lo contrario, se establece al menos otro bit, y es más alto quex
el bit más bajo, produciendo un resultado negativo.~(a/x >> 63)
luego produce una máscara de bits que es todo unon
o si-n
es una potencia de dos, de lo contrario, todos ceros.^s
se aplica a la máscara para verificar el signo den
para ver si es un poder de-2
.fuente
PHP, 3 operaciones
ternario y
if
no se permiten; así que maltratemoswhile
:$n>>1
: si el número es 0 o 1, devuelve el número$n&1
: si el número es impar, devuelve 0$n/-2
(+ cast a int)fuente
JavaScript ES6, 7 operaciones
Pruébalo en línea!
Explicación
Mientras x! = 0 yx% 2 == 0 4 operaciones
x / x es igual a 1 siempre que x no sea 0 (0/0 da NaN que se evalúa como falso)
y bit a bit y
x & 1 ^ 1 es igual a 1 si x es par (x y 1) xo 1
Esta es la forma de división definida por la pregunta 1 op
Mientras x! = 1 yx! = 0 1 op
La condición necesaria para salir cuando x == 0 o x == 1 ya que esos dos son los valores de retorno e ingresar un ciclo infinito no sería productivo. Teóricamente, esto podría extenderse para valores mayores aumentando el número hexadecimal. Actualmente funciona para hasta ± 2 ^ 32-1
Establezca x en 0 1 op.
Si bien podría haber usado return 0 para 0 ops, sentí que cualquier ciclo while que se rompe con otra declaración se parece demasiado a hacer trampa.
devuelve x (1 si la potencia de -2, de lo contrario 0)
fuente