Programación con bits y bytes

40

En este desafío, vas a escribir un intérprete para un lenguaje simple que he inventado. El lenguaje se basa en un único acumulador A, que tiene exactamente un byte de longitud. Al comienzo de un programa, A = 0. Estas son las instrucciones de idiomas:

!: Inversión

Esta instrucción simplemente invierte cada bit del acumulador. Cada cero se convierte en uno y cada uno se convierte en cero. ¡Simple!

>: Desplazar a la derecha

Esta instrucción cambia cada bit en un lugar a la derecha. El bit más a la izquierda se convierte en un cero y el bit más a la derecha se descarta.

<: Desplazar a la izquierda

Esta instrucción cambia cada bit en A un lugar a la izquierda. El bit más a la derecha se convierte en cero y el bit más a la izquierda se descarta.

@: Intercambiar Nybbles

Esta instrucción intercambia los cuatro bits superiores de A con los cuatro bits inferiores. Por ejemplo, si A es 01101010y ejecutas @, A será 10100110:

 ____________________
 |                  |
0110 1010    1010 0110
      |_______|

¡Esas son todas las instrucciones! Simple, verdad?

Reglas

  • Su programa debe aceptar la entrada una vez al principio. Esta será una línea de código. ¡Este no es un intérprete interactivo! Solo puede aceptar la entrada una vez y no tiene que volver al inicio una vez que se ha ejecutado esa línea.
  • Su programa debe evaluar dicha entrada. Todos los personajes que no se mencionan anteriormente se ignoran.
  • Su programa debería imprimir el valor final del acumulador, en decimal.
  • Se aplican las reglas habituales para lenguajes de programación válidos.
  • Las lagunas estándar no están permitidas.
  • Este es el , el recuento de bytes más pequeño gana.

Aquí hay algunos pequeños programas para probar sus envíos. Antes de que la flecha sea el código, después es el resultado esperado:

  • ! -> 255
  • !>> -> 63
  • !<@ -> 239
  • !nop!&6*! -> 255

¡Disfrutar!

bitsnbites
fuente
¿Supongo ! -> 255que debemos usar 8 bits por byte aquí? La pregunta no es explícita.
Toby Speight
3
@TobySpeight Un byte, por definición, es de 8 bits.
HyperNeutrino

Respuestas:

15

Pyth, 36 35 bytes

u%@[t_G/G2yGi_jGJ16JG)x"!><@"H256z0

Arnés de prueba

La representación interna del acumulador es un número entero. Este número entero es modificado por 256 en cada iteración, según se desee. Las operaciones realizadas son -G-1, G/2, G*2y Gconvierten a la base 16, invertido, y de vuelta convertida a la base 10, en donde Ges el acumulador.

Me perdí la frase sobre ignorar todo lo demás. Esto ha sido remediado. Gracias, Dennis.

isaacg
fuente
Entonces, ¿ -G-1es más corto que ~Gen Pyth? De alguna manera lo dudo.
CalculatorFeline
El código en cuestión es t_G, en realidad , dónde _está la negación y dónde testá -1. En Pyth, ~significa algo totalmente diferente.
isaacg
Me refería a Python ~(NO a nivel de bit)
CalculatorFeline
@CalculatorFeline Mi punto era que no hay una función de 1 carácter con ese efecto en Pyth, por lo que el código anterior (al menos para esa operación) es tan bueno como va a ser.
isaacg
13

C, 96

Asumiendo entrada ASCII (o compatible):

a;main(c){while(c=getchar()+1)a=(c^34?c^61?c^63?c^65?a:a*257/16:a/2:a*2:~a)&255;printf("%u",a);}

Tidier

a;
main(c){
  while(c=getchar()+1)
    a=(c^34?
      c^61?
        c^63?
          c^65?
            a
          :
            a*257/16
        :
          a/2
      :a*2:~a
    )&255;
  printf("%u",a);
}

Básicamente es solo una colección de expresiones ternarias anidadas. Estoy incrementando el valor obtenido de getchar()modo que un EOF (-1) resulte en un valor de cero y el programa salga.

(enlace ideone)

ossifrage aprensivo
fuente
1
Probé el desafío yo mismo y escribí casi exactamente el mismo código. Por cierto. su programa no pierde el bit cuando se desplaza hacia arriba (entrada: !<>debería resultar 127y no 255). Defina su acomo charo use la línea a&=255(y use %u) para obtener el efecto correcto. También puedes acortar tu negación a^255a ~a. a>>4&15También es más corto que tu (a&240)/16.
MarcDefiant
Ah, buen punto. Resulta que fue más eficiente enmascarar los 8 bits inferiores en cada iteración.
aprensivo ossifrage
1
En este caso, incluso puede usar la cadena de formato en %ulugar de%hhu
MarcDefiant
1
Lo acabo de ver ahora, pero también puedes usarlo en a/16|a*16lugar de a/16|(a&15)*16. Los pocos bits en la parte superior se eliminan por el &255.
MarcDefiant
1
Una pequeña mejora: a*257/16es un byte más corto que a/16|a*16.
Toby Speight
11

Python 3, 133 bytes

Utiliza un diccionario para compensar la falta de sintaxis de mayúsculas y minúsculas en Python. Ver más aquí .

a="0"*8
for i in input():a={"!":''.join(str(1-int(b))for b in a),"<":a[1:]+"0",">":"0"+a[:-1],"@":a[4:]+a[:4]}.get(i,a)
print(int(a,2))

El acumulador es una cadena que se convierte en un número base 10 al final.

Ejemplo de E / S:

$ python3 bitsnbytes.py
!
255
$ python3 bitsnbytes.py
!>>
63
$ python3 bitsnbytes.py
!<@
239
$ python3 bitsnbytes.py
!nop!&6*!
255
Decaimiento Beta
fuente
Si fuera un intérprete real e interactivo, sería for i in sys.stdin::)
Zizouz212
44
@ Zizouz212 Creo que te refieres a si era interactivo; me parece un verdadero intérprete. ;)
Alex A.
9

Javascript (ES6), 80 91 90 bytes

a=>[...a].reduce((p,c)=>c=='!'?p^255:c=='<'?p*2%256:c=='>'?p>>1:c=='@'?p/16|0+p%16*16:p,0)

Casi tan corto como puede ser. Define una función anónima que toma el programa como entrada.

  • Para !, tomas x XOR 255, ya que JS ~consideraría xun número de 32 bits.
  • Para <, se multiplica xpor 2 y toma el resultado mod 256.
  • Para >, realmente desplaza los bits de x1 bit a la derecha.
  • Para @, pisos x/16y agrega a x%16*16.

Gracias a @vihan por sugerir el uso de reducepara guardar un byte.

ETHproducciones
fuente
Puede usar <para guardar alrededor de 4 bytes. El uso de reducir también podría ahorrar algunos bytes
Downgoat
1
@vihan ¿Quieres decir <en lugar de ==? Si es así, eso no funcionaría, ya que los caracteres no operativos realizarían incorrectamente una operación. Lo usé en mi solución anterior de 80 bytes.
ETHproductions
¿No es estándar la flecha de grasa ES6 en PPCG que tiene que definirlo?
MayorMonty
@SpeedyNinja No conozco ninguno de esos estándares, pero si pudieras señalarme una publicación sobre uno, modificaré mi respuesta.
ETHproductions
8

CJam, 37 bytes

0q{"!><@"#"~ 2/ 2* GmdG*+ "S/=~255&}/

Pruébelo en línea en el intérprete de CJam .

Cómo funciona

0                   e# Push 0 (accumulator).
q                   e# Read from STDIN.
{                   e# For each character in the input:
  "!><@"#           e#   Find its index in "!><@" (-1 if not found).
  "~ 2/ 2* GmdG*+ " e#   Push that string.
  S/                e#   Split at spaces to push ["~" "2/" "2*" "GmdG*+" ""].
                    e#     "~"      : signed 64-bit bitwise NOT
                    e#     "2/"     : divide by 2
                    e#     "2*"     : multiply by 2
                    e#     "GmdG*+" : (x) -> (x/16) (x%16) -> (16(x%16) + (x/16))
                    e#     ""       : NOOP
  =~                e#  Select the corresponding string and evaluate it.
  255&              e#  Zero all but the 8 least significant bits.
}/                  e#
Dennis
fuente
8

Java (8), 514 483 411 366 359 239 224 229 198 194 187 186 184 182 181 180 177 caracteres

¡Guau, esto se ha jugado MUCHO! ¡Gracias a todos los que me dieron sugerencias! ¡Lo aprecio mucho!

interface T{static void main(String[]g)throws Exception{int i,a=0;while((i=System.in.read())!=10)a=(i==33?255-a:i==62?a/2:i==60?a*2:i==64?a>>4|a<<4:a)%256;System.out.print(a);}}

Golfó 31 (!) Bytes optimizando el intercambio de mordisco con operaciones bit a bit en lugar de Integer.???métodos largos .

Golfé 72 (!!!!) caracteres al eliminar la cadena innecesaria creada para intercambiar mordiscos. ¿Mucho mejor que antes?

Golfé 45 (!!) caracteres eliminando el uso java.util.Scannery la lectura System.indirectamente. Tenga en cuenta que ahora que la expresión lambda se ha ido, ¡Java 8 ya no es necesario! ¡Simplemente Java 1 lo haría!

Golfó 7 caracteres haciendo clase (default)( publicpalabra clave eliminada ), gracias a @bmarks

Golfed 120 (!!!!!!!) caracteres girando todas esas largas Integeroperaciones de clase en el volteo de bits a 255 - a. Ahora que es mucho más corto!

Golfé 15 (!) Caracteres al convertir los turnos en multiplicación y división, quitando los corchetes de la declaración while y haciendo alocales dentro del mainmétodo.

Ungolfed 9 = (caracteres debido a un problema con el desplazamiento a la izquierda que no descarta el byte más a la izquierda. Por lo tanto, ahora sí mod (256). El desplazamiento a la derecha hará que el número resultante sea un poco más corto que antes, por lo que no es necesario utilizarlo moden el desplazamiento a la derecha. Mi cosa de nibble-swap intercambiará los últimos 4 bits y el penúltimo nibble, y and (&)truncará todos los demás bits. Mi programa de inversión no causa ningún problema si el número original es menor que 256.

Golfed 31 35 caracteres gracias a @Geobits al convertir la switchdeclaración en muchas declaraciones ternarias, y también convirtiendo caracteres en ints, acortando los literales.

Golfó 7 caracteres al eliminar innecesarios &240en el intercambio de mordisco ( (a&240)>>4a a>>4y convertir (a&15)<<4a a<<4&240. Sin embargo, el último cambio solo arrojó un personaje.

Golfed 1 Char mediante la eliminación innecesaria =en a /= 2, porque a = a /= 2es equivalente a a = a / 2.

Golfé 2 caracteres recurriendo printlna print.

Golfó 2 caracteres al eliminar accidental a=en a=255-a( a=a=255-aes equivalente a a=255-a)

Golfó 1 char convirtiéndose a<<4&240en a%16<<4.

Golfé 1 personaje agregando corchetes al exterior de la declaración ternaria y haciendo %256. De esa manera, no %16es necesario en la parte de desplazamiento a la izquierda del intercambio de mordisco. Los corchetes agregan 2 caracteres y el %16salva 3 caracteres.

Golfed 3 caracteres cambiando classa interfacey eliminar publicutilizando la función de método de interfaz estática de Java 8. Gracias a @TheNumberOne (sin comentarios, pero encuentre su respuesta en "Consejos para jugar al golf en Java"

Hiperneutrino
fuente
No creo que la clase tenga que ser pública. Además, creo que si haces un Integer en lugar de un int, que podría hacer a.parseInt, a.toString, etc., en lugar de Integer.parseInt, Integer.toString, etc.
bmarks
Gracias por la primera sugerencia; Sin Integerembargo, voy a eliminar todos los métodos de clase.
HyperNeutrino
¿Quizás pueda hacer while ((i = System.in.read ())> 10) en lugar de! = 10 para guardar un byte?
comentarios
Buena idea, pero cualquier cosa por debajo de 10 hará que el programa finalice, y se supone que debo ignorar a otros personajes, no hacer el fin del mundo (o al menos mi programa :)) Sin embargo, lo consideraré; quizás no hay caracteres ascii válidos por debajo de 10.
HyperNeutrino
44
Es casi no vale la pena utilizar un switchgolf tiempo. Los case/ breakson demasiado largos. Debería poder ahorrar un montón haciendo que todo sea ternario; algo así comoa=i=='!'?255-a:i==62?a/2:i=='<'?a*2%256:i=='@'?(a&240)>>4|(a&15)<<4:a;
Geobits
7

Óxido, 121115 bytes

fn r(s:&str)->u8{let mut n=0u8;for t in s.chars(){match t{'!'=>n=!n,'>'=>n/=2,'<'=>n<<=1,'@'=>n=n>>4|n<<4,_=>()}}n}

Ejecución de muestra:

fn main() {
    println!("{}", r("!"));    //=> 255
    println!("{}", r("!>>"));  //=> 63
    println!("{}", r("!<@"));  //=> 239
}

Sin golf:

fn run_ungolfed(s: &str) -> u8 {
    let mut n = 0u8;
    for t in s.chars() {
        match t {
            '!' => n = !n,
            '>' => n >>= 1,
            '<' => n <<= 1,
            '@' => n = (n >> 4) | (n & 15) << 4,
            _ => ()
        }
    }
    n
}

Sorprendentemente corto para Rust. Nada más realmente interesante aparte del hecho de que aprendí más reglas de precedencia hoy, ¿ quién sabía (a>>b)|clo mismo que a>>b|c?

Afeitado de un byte cambiando n>>=1a n/=2; sin embargo, no se puede hacer lo mismo con la multiplicación, porque el desbordamiento aritmético es un pánico (es decir, un bloqueo) en Rust.

Pomo de la puerta
fuente
2
Lo de la precedencia tiene sentido cuando te convences de que >>es una especie de división y |una especie de suma.
Lynn
6

HP 41C / CV / CX (? Bytes, 42 pasos)

Solo para risas, aquí está para la calculadora HP 41C / CV / CX. (Requiere el módulo Funciones ampliadas o un 41CX para la función ATOX). Lamentablemente, la calculadora no informa los tamaños de los programas en bytes.

¡Pon tu programa en el registro Alpha, lo cual es un poco complicado, ya que no hay forma de ingresar! o @ directamente desde el teclado (use XTOA con los códigos ASCII 33 y 64 respectivamente para agregarlos).

Los pasos 08 y 10 permiten ignorar códigos de operación inválidos; eliminarlos para guardar 2 pasos, pero el programa se bloqueará en la entrada no válida.

01 LBL"BB
02 0
03 LBL A
04 ATOX
05 X=0?
06 GTO E
07 X<>Y
08 SF 25
09 XEQ IND Y
10 CF 25
11 GTO A
12 LBL 33
13 255
14 X<>Y
15 -
16 RTN
17 LBL 60
18 2
19 *
20 256
21 MOD
22 RTN
23 LBL 62
24 2
25 /
26 INT
27 RTN
28 LBL 64
29 RCL X
30 16
31 /
32 INT
33 X<>Y
34 16
35 *
36 256
37 MOD
38 +
39 RTN
40 LBL E
41 RDN
42 RTN
db2
fuente
6

Python 2, 79 bytes

Me di cuenta de que he hecho algo muy similar a esto en Python anteriormente. Este es solo un puerto de mi respuesta Ruby , pero por cierto es la respuesta más corta de Python a partir de ahora: D

a=0
for i in raw_input():a=[~a,a/2,a*2,a*16+a/16,a]["!><@".find(i)]&255
print a

La diferencia con la versión de Ruby es que esta no ignora las instrucciones no válidas mientras itera sobre la entrada. En cambio, aprovecho el hecho de que Python tiende a regresar en -1lugar de nilcuando no hay coincidencia: el valor actual de ase agrega al final de la matriz de resultados, de modo que todas las instrucciones no válidas se asignan al mismo valor sin cambios.

daniero
fuente
4

Python 3, 124 94 93 bytes

a=0
for i in input():
 if i in"!><@":a=(i=='!')*(255-a)+(i==">")*a//2+(i=="<")*(a+a)%256+(i=="@")*(16*(a%16)+a//16)
print(a)

"!" es lo mismo que restar de 255.
"<" es lo mismo que multiplicar por 2. Pero el registro de 8 bits significa mod 256.
">" es lo mismo que la división de enteros por 2.
"@" significa cambiar los últimos 4 bits ( a%16) por 4 bits ( *16) y agregando los primeros cuatro bits ( a/16).

EDITAR (leer copia descarada)
Vio la otra respuesta en python (por Beta decay). Utiliza una forma realmente efectiva de simular casos de cambio usando el diccionario. Usando eso podemos escribir

a=0
for i in input():a={"!":255-a,"<":a<<1&255,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)
print(a)

Gracias, Beta Decay.

Rohcana
fuente
No importa qué operación hagas, tienes que reducir el mod, 256¿verdad? Entonces, ¿por qué no hacer eso al final a={"!":255-a,"<":a*2,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)%256? Esto inmediatamente le ahorra un byte (porque lo hará en a*2lugar de a<<1) ... pero la respuesta de @ daniero también muestra que si lo hace de esta manera, (a%16)<<4puede acortarse a solo a<<4, ya que cualquier bit 16 o mayor se eliminará una vez que multiplique en 16 y reducirlo mod 256. ¡Genial! Además, ahora puede reemplazar 255-apor -1-a... o mejor, simplemente ~a. En total, estas sugerencias deberían ahorrarle 9 bytes.
mathmandan
3

Haskell, 89 bytes

a#'!'=255-a
a#'>'=div a 2
a#'<'=mod(a*2)256
a#'@'=mod(a*16)256+div a 16
a#_=a
f=foldl(#)0

Ejemplo de uso: f "!>>"->63

nimi
fuente
3

Óxido, 111 bytes

Más comentarios sobre la respuesta de @ Doorknob, pero no tengo ningún representante para los comentarios, ya que acabo de crear una cuenta.

Uno puede eliminar 10 bytes de su solución Rust con lo siguiente:

fn r(s:&str)->u8{let mut n=0u8;for t in s.chars(){n=match t{'!'=>!n,'>'=>n>>1,'<'=>n<<1,'@'=>n>>4|n<<4,_=>n}}n}
usuario4867444
fuente
Pensé que podríamos acortarnos aún más usando fold ( doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold ) pero sorprendentemente lo hace un poco más largo.
user4867444
3

Python 3, 127 bytes

Editar: cortocircuito, gracias @Jakube

Edit2: arreglo, gracias @Anachor

a=0
for i in input():a=(a^255if i=="!"else a>>1if i==">"else a<<1if i=="<"else(a&15)<<4|(a&240)>>4if i=="@"else a)&255
print(a)
uno20001
fuente
Quizás esto se deba a la nueva línea de Windows. Eso es más dos bytes. Usaré ese contador de bytes la próxima vez. :-) Gracias.
uno20001
Tenga en cuenta que esto no descarta el bit más a la izquierda cuando se desplaza a la izquierda, por lo que !<da 510mientras debería ser254
Rohcana
Espero que ahora sí. Perdón por mis errores, este es mi primer desafío de "golf".
uno20001
3

Ceilán, 297 290

shared void y(){value t=process.readLine()else"";variable Byte a=0.byte;for(c in t){switch(c)case('!'){a=a.not;}case('>'){a=a.rightLogicalShift(1);}case('<'){a=a.leftLogicalShift(1);}case('@'){a=a.and(#f0.byte).rightLogicalShift(4).xor(a.and(#f.byte).leftLogicalShift(4));}else{}}print(a);}

Formateado:

shared void y() {
    value t = process.readLine() else "";
    variable Byte a = 0.byte;
    for (c in t) { switch (c)
        case ('!') { a = a.not; }
        case ('>') { a = a.rightLogicalShift(1); }
        case ('<') { a = a.leftLogicalShift(1); }
        case ('@') { a = a.and(#f0.byte).rightLogicalShift(4).xor(a.and(#f.byte).leftLogicalShift(4)); }
        else {} }
    print(a);
}

#fy #f0son números hexadecimales para los nibbles, .byteconvierte un número entero en un byte. Tengo suerte de que el .stringatributo Byte ya use la representación sin signo de un byte. Ceilán también presenta una declaración de cambio sin caída, y una cadena es una lista de caracteres, que se puede iterar.

También traté de reducir los nombres de los métodos de desplazamiento largo utilizando una importación de alias, pero en realidad esto se vuelve 7 bytes más largo:

import ceylon.language{Byte{r=rightLogicalShift,l=leftLogicalShift}}shared void x(){value t=process.readLine()else"";variable Byte a=0.byte;for(c in t){switch(c)case('!'){a=a.not;}case('>'){a=a.r(1);}case('<'){a=a.l(1);}case('@'){a=a.and(#f0.byte).r(4).xor(a.and(#f.byte).l(4));}else{}}print(a);}

Formateado:

import ceylon.language {
    Byte {
        r=rightLogicalShift,
        l=leftLogicalShift
    }
}
shared void x() {
    value t = process.readLine() else "";
    variable Byte a = 0.byte;
    for (c in t) {
        switch (c)
        case ('!') { a = a.not; }
        case ('>') { a = a.r(1); }
        case ('<') { a = a.l(1); }
        case ('@') { a = a.and(#f0.byte).r(4).xor(a.and(#f.byte).l(4)); }
        else {}
    }
    print(a);
}

Esto podría ser útil si necesitamos esos métodos un poco más a menudo.

Paŭlo Ebermann
fuente
3

Rubí, 81 73 bytes

Mucho más simple: ¡no evalúe! Para cada carácter válido en la entrada, evalúa cada instrucción y encuentra la instrucción apropiada a través del índice de $&(el carácter actual en la entrada).

a=0
gets.scan(/[!><@]/){a=[~a,a/2,a*2,a*16+a/16]["!><@".index$&]&255}
p a
daniero
fuente
1
Eso es genial. Mucho más corto que cualquier otra forma. ¡2 votos a favor de mí!
edc65
¿Cómo puedes duplicar tu voto ...?
HyperNeutrino
@JamesSmith Probablemente se esté refiriendo a esto y a mi respuesta de Python :)
daniero
@danerio ya veo.
HyperNeutrino
2

STATA, 197 bytes

di _r(a)
gl b=0
forv x=1/`=length("$a")'{
gl c=substr("$a",`x',1)
if"$c"=="!" gl b=255-$b
if"$c"==">" gl b=int($b/2)
if"$c"=="<" gl b=mod($b*2,256)
if"$c"=="@" gl b=mod($b,16)*16+int($b/16)
}
di $b

Sin golf

display _request(a) //get the input via prompt and put in var a
global b=0 //initialise A to be 0
forv x=1/`=length("$a")'{ //for loop from 1 to last char in a
global c=substr("$a",`x',1) //get the char at index x in a
if "$c"=="!" global b=255-$b //invert is the same as 255-A
if "$c"==">" global b=int($b/2) //right shift is the same as A/2 (with integer division)
if "$c"=="<" global b=mod($b*2,256) //left shift is the same as A*2%256
if "$c"=="@" global b=mod($b,16)*16+int($b/16) //nibble swap is the same as A%16*16+A/16
}
display $b //display the result of A

No funciona con el intérprete en línea y requiere el intérprete predeterminado no libre. Esto sería algo más fácil con las operaciones bit a bit reales, pero no creo que sean demasiado útiles para la mayoría de los usos comunes de STATA.

comentarios
fuente
¿Por qué no funciona el intérprete en línea?
CalculatorFeline
2

JavaScript, 104

[].reduce.call(prompt(),function(a,i){return(i=='!'?~a:i=='>'?a/2:i=='<'?a*2:i=='@'?a>>4|a<<4:a)&255},0)

Los operadores ternarios anidados se asignan a las instrucciones.

BITWISE AND se usa para restringir nuestro tipo de Número a un solo byte.

Andrew Vermie
fuente
2

Julia, 117 94 86 73 bytes

p->(a=0x0;[a=c==33?~a:c==60?a<<1:c==62?a>>1:c!=64?a:a<<4|a>>4for c=p];1a)

Esta es una función anónima que acepta una cadena y devuelve un entero. Para llamarlo, asígnelo a una variable.

Sin golf:

function f(p)
    # Initialize the accumulator to 0 as an 8-bit unsigned integer
    a = 0x0

    # Loop over the characters in the input
    for c in p
        a = c == 33 ? ~ a :        # '!'
            c == 60 ? a << 1 :     # '<'
            c == 62 ? a >> 1 :     # '>'
            c != 64 ? a :          # no-op
            a << 4 | a >> 4        # '@'
    end

    # Convert the accumulator to a regular integer and return
    return Int(a)
end

¡Ahorré 8 bytes gracias a Sp3000 y 13 gracias a Dennis!

Alex A.
fuente
2

JavaScript (ES6), 76 81

Como una función sin nombre que devuelve el valor del acumulador

Este es un portafolio de las respuestas súper inteligentes de @daniero (que tienen muy pocos votos a favor)

Bonificación: puede pasar un valor inicial del acumulador. Si no se pasa, el valor inicial es 0 como específico.

(p,a)=>(p.replace(/[!<>@]/g,i=>a=(i<'<'?~a:i<'>'?a*2:i<'@'?a/2:a*257/16)&255),a)

Pruebe a ejecutar el fragmento a continuación en cualquier navegador EcmaScript 6 (lo probé en Firefox)

f=(p,a)=>[...p].map(c=>a=255&[a,~a,a*2,a/2,a*257/16][1+'!<>@'.indexOf(c)])|a

// TEST
out=x=>O.innerHTML+=x+'\n'

function go(x) { out(x+' -> '+f(x)) }

go('!'),go('!>>'),go('!<@'),go('!nop!&6*!')

// LESS GOLFED
F=(p,a)=>// a as a parameter, if not passed its value starts as undefined, then becomes NaN, but the operators '&' and '~' treat it as 0
  [...p].map(c => // execute following function for each character p
    a = 255 & // any intermediate result is converted to numeric and truncate to a byte          
   // evaluate all possible results (then choose one bases on the current character)
   [a,   // NOP, if unexpected char 'a' remains the same
    ~a,  // tilde == binary not (will give a result wider than a byte)
    a*2, // < shift left is *2 (can give a result wider than a byte) 
    a/2, // > shift right is /2 (can give a non integer result)
    a *257 / 16  // move nibbles around (will give a result wider than a byte)
   ] // array of all results
   [1+'!<>@'.indexOf(c)] // find index to get the correct result
  ) // end map, returns an array in any case
    // eventually a single element array containg a
  | a // return accumulator
Test program:<input id=I><button onclick='go(I.value)'>go</button>
<pre id=O></pre>

edc65
fuente
1

Cristal, 139 bytes

def f x
b=0_u8
x.chars.each do|c|
b=case c
when'!'
~b
when'>'
b>>1
when'<'
b<<1
when'@'
b<<4|b>>4
else raise ""
end
end
puts b
end
kirbyfan64sos
fuente
1

C # 193

void Main(){byte a=0;foreach(var c in Console.ReadLine()){if(c=='!')a=(byte)~a;if(c=='>')a=(byte)(a>>1);if(c=='<')a=(byte)(a<<1);if(c=='@')a=(byte)(((a&240)>>4)|((a&15)<<4));}Console.Write(a);}
Stephan Schinkel
fuente
2
¿No necesitas using System;o algo así para acceder Console.ReadLiney Console.Writesin el System.prefijo?
Alex A.
Además, me parece que no debería tener que elegir bytepara cada operación, pero podría estar equivocado.
Alex A.
1

Lua, 344 char

a=string.rep("0",8)
t=io.read()
f={["!"]=function()local s="";for j=1,8 do s=s..(a:sub(j,j)=="0"and"1"or"0") end;return s end,[">"]=function() return "0"..a:sub(1,7) end,["<"]=function()return a:sub(2,8).."0"end,["@"]=function()return a:sub(5,8)..a:sub(1,4)end}
for i=1,#t do a=(f[t:sub(i,i)]or function()return a end)()end
print(tonumber(a,2))

Inspirado por el uso de @Beta Decay de un acumulador de cadenas, ya que lua no tiene ningún tipo de byte. Probablemente podría jugar más golf usando menos funciones.

Delya Erricson
fuente
1

R, 194 bytes

b<-readline();A<-rep(0,8);s<-strsplit(b,"")[[1]];for(r in s){if(r=="!")A<-(A+1)%%2;if(r==">")A<-c(0,A)[1:length(A)];if(r=="<")A<-c(A,0)[-1];if(r=="@")A<-c(A[5:8],A[1:4])};print(sum(A*(2^(7:0))))

sin golf

b <- readline()
A <- rep(0, 8) 
s <- strsplit(b, "")[[1]]
for (r in s) {
    if (r == "!")
        A <- (A + 1) %% 2
    if (r == ">")
        A <- c(0, A)[1:length(A)]
    if (r == "<")
        A <- c(A, 0)[-1]
    if (r == "@")
        A <- c(A[5:8], A[1:4])
}
print(sum(A*(2^(7:0))))
mawir
fuente
Todo el <-puede ser sustituido por =aquí, lo que reduce el código de 7 bytes. Además, es posible que pueda reemplazar la serie de ifdeclaraciones por una llamada a switch(como en A=switch(r,"!"=(A+1)%%2, ...))
plannapus
El resultado b=readline();A=rep(0,8);s=strsplit(b,"")[[1]];for(r in s)A=switch(r,"!"=(A+1)%%2,">"=c(0,A)[1:length(A)],"<"=c(A,0)[-1],"@"=c(A[5:8],A[1:4]),A);print(sum(A*(2^(7:0))))es 167 bytes.
plannapus
1

RPL, 170,5 bytes

La entrada debe ingresarse como una cadena en el nivel 1.

\<< DEC 8 STWS \-> S 
    \<< #0d 1 S SIZE 
        FOR I "!><@" S I DUP SUB POS 1 + { \<< \>> NOT SR SL \<< DUP #16d / SWAP #16d * + \>> } SWAP GET EVAL NEXT \>> 
\>>
Jason
fuente
1

K, 57 bytes

Es un comienzo:

0{y+2*x}/(8#0){((~:;{-1_0,x};{1_ x,0};4!;{x})"!><@"?y)x}/

probado usando Kona:

  f:0{y+2*x}/(8#0){((~:;{-1_0,x};{1_ x,0};4!;{x})"!><@"?y)x}/
...
  f'("!";"!>>";"!<@";"!nop!&6*!")
255 63 239 255

Es posible que pueda hacerlo mejor en k5, pero es una serie compleja de compensaciones, por ejemplo, convertir binario a decimal es tan fácil como 2/, pero el comportamiento de ?hace que sea más difícil manejar un caso predeterminado para la búsqueda de instrucciones.

JohnE
fuente
1

PHP, 189 bytes

<? $c='00000000';foreach(str_split($argv[1])as$a){$a=='!'&&$c=strtr($c,'01','10');$a=='<'&&$c=substr($c.'0',1);$a=='>'&&$c=substr('0'.$c,0,8);$a=='@'&&$c=substr($c.$c,4,8);}echo bindec($c);

No es que supere muchas respuestas, es solo para practicar

Einacio
fuente
1

HPPPL , 302 294 bytes

#pragma mode(separator(.,;)integer(d8))EXPORT b()BEGIN print();local p,j,a;a:=#0d;INPUT({{p,[2]}});for j from 1 to dim(p)do c:=p(j);case if c==33 then a:=BITNOT(a)end if c==62 then a:=BITSR(a,1)end if c==60 then a:=BITSL(a,1)end if c==64 then a:=BITSL(a,4)+BITSR(a,4)end end;end;print(a*1);END;

Sin golf:

// make sure integers are unsigned 8 bit decimal numbers
#pragma mode( separator(.,;) integer(d8) ) 
EXPORT b()
BEGIN
  print();
  local p,j,a;
  a:=#0d;                         // set a to integer value 0
  INPUT({{p,[2]}});               // open input dialog treating input as string ( type [2])
  for j from 1 to dim(p) do
    c:=p(j);
    case
      if c==33 then a:=BITNOT(a) end             // !
      if c==62 then a:=BITSR(a,1) end            // >
      if c==60 then a:=BITSL(a,1) end            // <
      if c==64 then a:=BITSL(a,4)+BITSR(a,4) end // @
    end;
  end;
  print(a*1); // converts to proper output by promoting to non integer format
              // print(a) would result in
              // #239:8d for 239 if the default bit size is not set to 8 bits decimal
              // indicating an 8 bit unsigned decimal integer, or
              // #239d if the default bit size is already set to 8 bits decimal

END;

Comando de entrada HPPPL

Salida HPPPL a terminal

Esta respuesta asegura que el HP Prime utilice enteros de 8 bits sin signo, incluso si el modo está configurado en, por ejemplo, 64 bits por el usuario. Si la calculadora se configura manualmente para usar enteros decimales de 8 bits sin signo, entonces pragmase puede omitir el comando. Si la salida no necesita seguir estrictamente el formato, entonces a*1simplemente puede ser al final a. Multiplicar el resultado por 1 solo garantiza que la salida no siga la salida interna para valores enteros. El printcomando en la línea 4 también se puede omitir si no es necesario borrar el terminal antes de imprimir el resultado. Si se permite pasar el programa como un argumento de cadena, entonces elINPUT se puede omitir comando.

Esta es la versión más corta con entrada y salida adecuada, sin el argumento pragma (si la calculadora está configurada en Uint8 por defecto:

243 bytes:

EXPORT b()BEGIN local p,j,a;a:=#0d;INPUT({{p,[2]}});for j from 1 to dim(p)do c:=p(j);case if c=33 then a:=BITNOT(a)end if c=62 then a:=BITSR(a,1)end if c=60 then a:=BITSL(a,1)end if c=64 then a:=BITSL(a,4)+BITSR(a,4)end end;end;print(a*1);END;
ML
fuente
1

Perl 6, 96 89 bytes

{my $a=0;$a=(+^*,*+<1,*+>1,{$_+<4+$_+>4},{$_})["!<>@".index($_)//4]($a)%256 for .comb;$a}

Vieja solución:

{my $a=0;$a=(255-*,*+<1+&255,*+>1,{$_+&15+<4+$_+>4},{$_})["!<>@".index($_)//4]($a)for .comb;$a}
bb94
fuente
1

C #, 119 bytes

i=>{var a=0;foreach(var c in i){if(c=='!')a=~a;if(c=='>')a>>=1;if(c=='<')a<<=1;if(c=='@')a=a<<4|a>>4;a&=255;}return a;}

Intenté otras versiones, pero necesito más bytes:

Func<string,int>C=i=>{var a=0;foreach(var c in i){switch(c){case'!':a=~a;break;case'<':a<<=1;break;case'>':a>>=1;break;case'@':a=a<<4|a>>4;break;}a&=255;}return a;};

// This is, despite having the worst score, my personal favourite :D
Func<string,int>D=i=>{var f=new Dictionary<char,Func<int,int>>{{'!',q=>~q},{'<',q=>q<<1},{'>',q=>q>>1},{'@',q=>q<<4|q>>4}};var a=0;foreach(var c in i)if(f.ContainsKey(c))a=f[c](a)&255;return a;};
Stefan
fuente
1

Python 2.7.3, 104 bytes

Tener código en cadenas para evaluar se ve bastante sucio, pero funciona: D

a=0
for c in raw_input():a=eval({'!':'~a','<':'a<<1','>':'a>>1','@':'a<<4|a>>4'}.get(c,'a'))&255
print a

Aquí está la salida (y la entrada en realidad ..)

Y sí, realmente se está ejecutando en un RaspberryPi :)

Salida de ejemplo

Stefan
fuente