Comprobación de bits prístina


28

Escriba un programa / función que tome dos enteros en el rango de 0 a 255 inclusive, y devuelva si las formas binarias de los números son exactamente un bit diferentes.

Por ejemplo, 1 y 0 tienen formas binarias 00000001y 00000000, que están un poco separadas. Del mismo modo, 152 y 24 son 010011000y 000011000, por lo que devuelven verdadero.

Sin embargo , su código debe ser impecable , de modo que si se voltea un bit de su programa, debería arrojar un error. Por ejemplo, si su programa era el byte únicoa(01100001), entonces los 8 programas modificados posibles:

á ! A q i e c `

Debe arrojar un error. Asegúrese de que está modificando por bytes (p. Ej. á, Allí arriba está representando el byte 225 , no el carácter real de dos bytes á).

Casos de prueba:

0,1     => Truthy
1,0     => Truthy
152,24  => Truthy
10,10   => Falsey
10,11   => Truthy
11,12   => Falsey
255,0   => Falsey

Reglas:

  • Proporcione un marco de prueba que pueda verificar que su programa esté correctamente prístino, ya que habrá muchos programas posibles (número de bytes * 8), o una prueba completa de impecabilidad.
    • Por favor asegúrese de que su programa es válido antes de publicarlo.
  • La salida debe ser verdadero / falso (de cualquier manera está bien), o bien dos valores distintos sin error
  • Los errores pueden ser tiempo de ejecución, compilador, intérprete, etc.

77
Si alguien está buscando una manera de generar todas las variaciones posibles de su solución, este programa Japt debería (alguien por favor verifique dos veces) hacer el trabajo: petershaggynoble.github.io/Japt-Interpreter/…
Shaggy

44
Aquí también hay uno en Python: ¡ Pruébelo en línea!
TFeld

Las funciones no están permitidas, ya que mencionó el programa?
Kevin Cruijssen

55
@KevinCruijssen He especificado que las presentaciones de funciones están bien
Jo King

44
¡Ese comentario tiene más +1de la mayoría de mis soluciones recientes! : \
Shaggy

Respuestas:


16

Python 2 , 35 bytes

lambda a,b:(a^b)&-(a^b)in[a^b or[]]

Pruébalo en línea!

Utiliza la verificación de potencia de dos n&-n==n, eliminando el n==0falso positivo.

Como referencia, estos son los pares de operadores binarios one-char que están separados un poco, lo que los hace difíciles de usar:

+ /
- /
* +
% -
< |
< >

Afortunadamente, &y ^no están entre estos.

También tenga en cuenta que ==puede convertirse <=, y +puede convertirse en el personaje de comentario #.


Python 2 , 41 bytes

lambda a,b:bin(a^b).count(`+True`)is+True

Pruébalo en línea!

Tomando TFeld's lambda a,b:bin(a^b).count('1')==1 y haciéndolo prístino cambiando los 1's a +Truey ==para is. Gracias a Jo King por 1 byte.


9

Python 2 , 72 67 50 bytes

lambda a,b:sum(map(int,'{:b}'.format(a^b)))is+True

Pruébalo en línea!

-5 bytes, gracias a Jo King


Devoluciones True/False para veracidad / falsey.

El programa es básicamente el mismo que lambda a,b:bin(a^b).count('1')==1 , pero sin números y otros caracteres que funcionan cuando se invierte el bit.

Funciona asegurándose de que casi todo sea una función con nombre (que son bastante inmaculadas)

La prueba prístina al final voltea un solo bit (para cada bit) y prueba la función en una entrada. Si eso funciona (correcto o no), se imprime esa variación. Sin programas impresos = función prístina.


8

Java 8, 68 61 56 45 bytes

a->b->(a.bitCount(a^b)+"").equals(-~(a^a)+"")

-11 bytes gracias a @EmbodimentOfIgnorance , reemplazando constante java.awt.Font.BOLD con -~(a^a).

Pruébalo en línea.

Explicación:

La función base más corta sería:

a->b->a.bitCount(a^b)==1

Pruébalo en línea.

Esto se modifica para que no haya un dígito, =ni uno de los +/*operandos en él para cálculos numéricos (entonces el+ concatenación de cadenas está bien):

Los +""y .equalsson para comparar en String.equals(String)lugar de int==int.
NOTA: Integer.equals(int)se podría utilizar aquí, pero sería más bytes, ya que tanto el .bitCounty java.awt.Font.BOLDson primitivos inten lugar de Integer-Objetos, por lo que un adicional new Integer(...)sería necesaria para transformar uno de los dos para un Integer-objeto, antes de poder utilizar el .equals.


(int) Math.log (Math.E) tiene 21 bytes
Datos


@ExpiredData Gracias, en realidad solo encontré una constante más corta con java.awt.Font.BOLD, pero tu Objects.equalses un buen golf, ¡gracias!
Kevin Cruijssen

@ExpiredData En realidad, Objectses parte de la java.util.importación, así que tengo que agregarlo al recuento de bytes, me temo, lo que hace 69 bytes .. :(
Kevin Cruijssen

3
¿ -~(a^a)Funcionaría para 1?
Encarnación de la ignorancia

7

C (gcc) , 56 bytes

d(a,b){return(sizeof((char)d))^__builtin_popcount(a^b);}

Pruébalo en línea!

Devuelve 0si el par difiere en 1, de lo contrario no es cero. Ligeramente inusual para C, a menos que considere volver EXIT_SUCCESSsi el par difiere en 1, cualquier otro valor de lo contrario.

Se utiliza sizeof((char)d))para producir la constante 1de una manera prístina y al mismo tiempo obliga al nombre de la función a ser impecable.

Luego XORs 1 con el popcount de XOR de los argumentos. Afortunadamente, el ^símbolo es fácil de mantener prístino, al igual que el identificador muy largo __builtin_popcount.

Mientras tanto, aquí está el script utilizado para probar la solución:

#!/bin/bash

SOURCE_FILE=$1
FOOT_FILE=$2
TMP_SRC=temp.c

LENGTH="$(wc -c <"$SOURCE_FILE")"
BITS=$((LENGTH*8))

cat "$SOURCE_FILE" >"$TMP_SRC"
cat "$FOOT_FILE" >>"$TMP_SRC"
if gcc -w $TMP_SRC -o t.out >/dev/null 2>&1; then
    if ./t.out; then
        echo "Candidate solution..."
    else
        echo "Doesn't even work normally..."
        exit
    fi
else
    echo "Doesn't even compile..."
    exit
fi

for i in $(seq 1 $BITS); do
    ./flipbit "$i" <"$SOURCE_FILE" >"$TMP_SRC"
    cat "$FOOT_FILE" >>"$TMP_SRC"
    if gcc -w $TMP_SRC -o t.out >/dev/null 2>&1; then
        echo "Testing flipped bit $i:"
        cat "$TMP_SRC"

        ./t.out >/dev/null 2>&1
        STATUS=$?
        if [ "$STATUS" -eq 0 ]; then
            echo "It works!"
            exit
        elif [ "$STATUS" -eq 1 ]; then
            echo "It doesn't work..."
            exit
        else
            echo "It crashes"
        fi
    fi
done

Que usa la ./flipbitherramienta que escribí cuya fuente es simplemente:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    int bittoflip = atoi(argv[1]) - 1;
    int ch;

    while ((ch = fgetc(stdin)) != EOF) {
        if (bittoflip < 8 && bittoflip >= 0) {
            putchar(ch ^ (1 << bittoflip));
        } else {
            putchar(ch);
        }

        bittoflip -= 8;
    }

    return 0;
}

Las partes difíciles fueron:

  • Espacio en blanco: todos los espacios en blanco (incluidas las nuevas líneas) tienen gemelos prístinos que funcionarán de manera similar
  • Comparación: =no funciona bien, ya que puede ser una comparación en todos los casos que pueda aparecer. Del mismo modo -no funciona bien. Así^ lo se utiliza para afirmar la igualdad con 1.
  • Nombres de variables: f entraría en conflicto con b, por lo que tuvo que usar d como el nombre de la función.

¿Cómo se mantiene el ^operador impecable? Si los bits en eso fueron cambiados, ¿qué puede evitar que se convierta en un operador diferente? Esto aún se compilaría, pero solo le daría la respuesta incorrecta. ¿Estoy malinterpretando algo sobre el significado de la palabra "prístino" aquí?
Cody Gray

44
Al voltear solo un bit, ^solo se puede cambiar a cualquiera de _\ZVN~Þlos caracteres no imprimibles en el punto de código 30. ~es el único de los que es un operador, pero es solo un operador unario.
Cadena no relacionada

1
O incluso usar en __LINE__lugar de sizeof(char). Creo que está bien suponer que su función estará en la línea 1 de su archivo .c. O incluso unixse define como 1 en TIO, y probablemente en la mayoría de los demás Linux.
Trauma digital

2
La razón principal del tamaño char-casted es que se dcuece en la fuente en la menor cantidad de bytes posible. De dlo contrario (o como se le llame a la función) simplemente se puede cambiar y el código seguirá funcionando. Incluso (__LINE__)con d();no funcionará porque d();se puede cambiar a cualquier otra letra y aún se compilará ya que la función nunca tiene que llamarse, por lo tanto, no está vinculada.
LambdaBeta

1
@LambdaBeta Si el nombre de la función cambia, habrá un error de enlace, incluso si d no es autorreferencial. Creo que esto es suficiente, personalmente.
Trauma digital

7

R , 38 37 bytes

-1 byte gracias a Nick Kennedy.

dpois(log2(bitwXor(scan(),scan())),T)

Pruébalo en línea! (Gracias a Giuseppe por configurar el TIO correctamente).

Prueba de que es impecable (usando el corrector de Nick Kennedy ).

Salidas 0 para falsey, y un valor positivo para la verdad, que entiendo es aceptable ya que R interpretará esto como Falso y Verdadero.

Explicación: bitwXor(a,b)da (como un entero) el XOR bit a bit entre ay b. Para verificar si es una potencia de 2, verifique si su registro en la base 2 es un entero. La función dpoisproporciona la función de densidad de probabilidad de la distribución de Poisson: su valor es 0 para valores no enteros y algo positivo para enteros no negativos. El Testá allí porque dpoisrequiere un segundo argumento (cualquier trabajo real positivo, yT se interpreta como 1).

Si insistimos en generar valores distintos, la siguiente versión genera FALSO o VERDADERO en 42 bytes (gracias a Giuseppe por -8 bytes):

dpois(log2(bitwXor(scan(),scan())),T)%in%F

y también es prístina . Pruébalo en línea!


2
¡Bien hecho por conseguir algo mucho más pequeño que el mío! Puede reemplazar picon Tpara guardar un byte (aún prístino). Además, su TIO no corresponde a su respuesta en este momento.
Nick Kennedy

@NickKennedy ¡Gracias! (¡Y gracias por escribir el código para verificar que sea perfecto!). El TIO al que me vinculé es una versión modificada que verifica todos los casos de prueba. Agregaré un TIO al código real, pero no puedo entender cómo hacer que TIO se ejecute correctamente con dos llamadas a scan(); ¿Tienes una idea? (El código funciona bien en una computadora.)
Robin Ryder

2
@NickKennedy ¿Quizás algo como esto? por conseguir que el TIO y el código coincidan?
Giuseppe

@Giuseppe Maravilloso, gracias!
Robin Ryder

1
su segunda versión podría usar en Flugar de exp(-Inf), en la misma línea que Nick T:-)
Giuseppe

6

R , 83 bytes

t(identical(sum(.<-as.double(intToBits(Reduce(bitwXor,scan())))),sum(T^el(.[-T]))))

Pruébalo en línea!

Prueba de que esto es prístino

Eludir el hecho de que as.integer, as.doubleetc. , están solo un poco lejos is.integer, is.doubleetc. fue lo más difícil. Al final, usar sum(T^el(.[-T])como una forma de generar uno y verificar que as.doubleha devuelto un vector de longitud> 1 fue lo mejor que pude hacer. La envoltura tes manejar el hecho de que de lo contrario identicalpuede convertirse ide~tical.


5

Julia 0.7 , 20 bytes

(a,b)->ispow2(ab)

Pruébalo en línea!

Aquí hay un validador prístino que intenta ejecutar cada función anónima modificada contra alguna entrada, y ninguna de las dos pasa con éxito. Tenga en cuenta que el código tiene un carácter unicode de varios bytes, y algunas posibles salidas del cambio de bits ni siquiera están incluidas, ya que producen cadenas UTF-8 no válidas.


xy yestán un poco separados, así que creo que este es un contraejemplo. yy xtambién están a 1 bit 9y 6respectivamente.
Datos

Maldición, mientras pensaba en cosas complejas, echaba de menos la más simple. Con suerte, cambiar las variables lo solucionará.
Kirill L.


4

C # (Visual C # interactivo Compilador) , 128 101 77 70 61 74 bytes

-27 bytes gracias a Ascii-Only

a=>b=>{var d=Math.Log(a^b,(int)Math.E);return d.Equals((int)Math.Abs(d));}

Pruébalo en línea!

Tienes que ser bastante creativo para obtener números en C # sin usar literales. Solo usa el operador ^. Las variables a, b están a más de 1 bit de distancia entre sí y todo lo demás es una palabra clave / nombre.


no es necesario contar bits; comprobar si es una potencia de 2 entre 1 y 128 inclusive es suficiente
solo ASCII el

@ Solo ASCII Buena suerte comprobando eso en un número razonable de bytes cuando no podemos usar números enteros ni +/*=para operaciones matemáticas o de validación. ;)
Kevin Cruijssen

@KevinCruijssen C # también tiene enumeraciones :(. Damnit
solo ASCII


1
O_o otro -24. por cierto ya no usas+
solo ASCII

3

JavaScript (ES6 en modo estricto), 61 bytes

(y,z,e)=>eval(`(y${(e='^=z)*!(y&~-y)')!='^=z)*!(y&~-y)'||e}`)

Pruébalo en línea! o asegúrese de que todos los programas modificados sean incorrectos


Oh, Dios mío, no me di cuenta de que hice clic en un enlace de código de golf y vi esta respuesta fuera de contexto y casi tuve un ataque al corazón. Como, OMG NO
Marie

44
@Marie ¡Precaución! Solo puede mirar este código con gafas de golf certificadas. De lo contrario, puede quemar su retina. : p
Arnauld


1

MATLAB, 37 bytes

@(c,e)eq(nnz(de2bi(bitxor(c,e))),eye)

Lo sentimos, no hay enlace TIO, porque no puedo hacer que el conjunto de pruebas funcione bajo Octave. Gracias @ExpiredData por algunos comentarios útiles.

Banco de pruebas:

program = '@(c,e)eq(nnz(de2bi(bitxor(c,e))),eye)';
number_of_characters = nnz(program);
success = [];
for character_counter = 0 : number_of_characters
    for bit_no = 1:8
        prog_temp = program;
        if(character_counter > 0)
            prog_temp(character_counter) = bitxor(double(prog_temp(character_counter)),2^(bit_no-1));
        elseif(bit_no<8) % Test the unmodified program once
            continue
        end
        try
            eval(prog_temp);
            eval('ans(2,3)');
            disp(prog_temp)
            success(end+1)=1;   
        catch
            success(end+1)=0;
        end 
    end
end
assert(nnz(success)==1)


@ExpiredData Gracias por la sugerencia. Fui por un MATLAB numel, porque mi suite de pruebas no parece estar funcionando en Octave.
Sanchises

38 bytes tal vez ... no obtuve una licencia matlab pero debería funcionar
Datos

1
@ExpiredData Gracias, ¡uno puede hacer un byte mejor eye!
Sanchises

1
@ExpiredData Lo sé, también estoy muy molesto con Octave. Pero usar el programa Python en los comentarios de OP es útil para ver si puedes introducir un nuevo personaje sin problemas.
Sanchises

1

Perl 6 , 77 43 bytes

Gracias a Jo King por -33 bytes.

{elems(i)eq(sum [+^](@_).polymod(+@_ xx*))}

Esto es equivalente a

{1 eq(sum [+^](@_).polymod(2 xx*))}

1 fue reescrito como elems([""]) . 2fue reescrito como sum(elems([""]),elems([""])); elems(["",""])puede parecer que funciona peroelems([""-""]) también es válido y parece colgar el probador.

Pruébalo en línea!


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.