Programando com bits e bytes

40

Neste desafio, você escreverá um intérprete para um idioma simples que eu inventei. O idioma é baseado em um único acumulador A, com exatamente um byte de comprimento. No início de um programa, A = 0. Estas são as instruções de idiomas:

!: Inversão

Esta instrução simplesmente inverte todos os bits do acumulador. Todo zero se torna um e cada um se torna um zero. Simples!

>: Deslocar para a direita

Esta instrução muda todos os bits em um lugar para a direita. O bit mais à esquerda se torna zero e o bit mais à direita é descartado.

<: Shift para a esquerda

Esta instrução muda cada bit em um lugar para a esquerda. O bit mais à direita se torna zero e o bit mais à esquerda é descartado.

@: Trocar Nybbles

Esta instrução troca os quatro bits superiores de A pelos quatro bits inferiores. Por exemplo, se A é 01101010e você executa @, A será 10100110:

 ____________________
 |                  |
0110 1010    1010 0110
      |_______|

Essas são todas as instruções! Simples, certo?

Regras

  • Seu programa deve aceitar entrada uma vez no início. Esta será uma linha de código. Este não é um intérprete interativo! Você só pode aceitar entrada uma vez e não precisa voltar ao início depois que a linha for executada.
  • Seu programa deve avaliar a entrada mencionada. Todo personagem que não é mencionado acima é ignorado.
  • Seu programa deve imprimir o valor final do acumulador, em decimal.
  • Aplicam-se regras usuais para linguagens de programação válidas.
  • As brechas padrão não são permitidas.
  • Isso é , a menor contagem de bytes ganha.

Aqui estão alguns pequenos programas para testar seus envios. Antes da seta estar o código, depois do resultado esperado:

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

Apreciar!

bitsnbites
fonte
Estou presumindo ! -> 255que vamos usar 8 bits por byte aqui? A pergunta não é explícita.
amigos estão
3
@TobySpeight Um byte, por definição, é de 8 bits.
HyperNeutrino 15/02

Respostas:

15

Pitão, 36 35 bytes

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

Equipamento de teste

A representação interna do acumulador é um número inteiro. Esse número inteiro é modificado por 256 em cada iteração, conforme desejado. As operações executadas são -G-1, G/2, G*2e Gconvertido para a base 16, invertida e volta convertido para a base 10, onde Gé o acumulador.

Perdi a linha sobre ignorar todo o resto. Isso foi remediado. Obrigado, @Dennis.

isaacg
fonte
Então -G-1é mais curto que ~Gem Pyth? Duvido um pouco disso.
CalculadoraFeline
O código em questão é t_G, na verdade , onde _está a negação e testá -1. Em Pyth, ~significa algo totalmente diferente.
Isaacg
Eu quis dizer Python ~(bitwise NOT)
CalculatorFeline
@CalculatorFeline Meu argumento foi que não existe uma função de 1 caractere com esse efeito no Pyth; portanto, o código acima (pelo menos para essa operação) é o melhor possível.
Isaacg
13

C, 96

Supondo entrada ASCII (ou compatível):

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);}

Mais arrumado:

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);
}

Basicamente, é apenas uma coleção de expressões ternárias aninhadas. Estou incrementando o valor obtido getchar()para que um EOF (-1) resulte em um valor zero e o programa saia.

(link ideone)

ossifrage melindroso
fonte
11
Eu mesmo tentei o desafio e escrevi quase exatamente o mesmo código. Btw. seu programa não diminui um pouco ao mudar para cima (entrada: !<>deve resultar em 127e não 255). Defina seu acomo charou use a linha a&=255(e use %u) para obter o efeito correto. Além disso, você pode reduzir sua negação a^255para ~a. a>>4&15também é mais curto que o seu (a&240)/16.
precisa saber é o seguinte
Ah, bom argumento. Acontece que era mais eficiente mascarar os 8 bits inferiores a cada iteração.
squishish ossifrage
11
Nesse caso, você pode até usar a string de formato em %uvez de%hhu
MarcDefiant 8/15
11
Acabei de ver agora, mas você também pode usar em a/16|a*16vez de a/16|(a&15)*16. Os poucos bits no topo são removidos pelo &255.
precisa saber é o seguinte
11
Uma pequena melhoria: a*257/16é um byte menor que a/16|a*16.
perfil completo de Toby Speight
11

Python 3, 133 bytes

Usa um dicionário para compensar a falta de sintaxe de caso de opção no Python. Veja mais aqui .

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))

O acumulador é uma string que é convertida em um número base 10 no final.

Exemplo de E / S:

$ python3 bitsnbytes.py
!
255
$ python3 bitsnbytes.py
!>>
63
$ python3 bitsnbytes.py
!<@
239
$ python3 bitsnbytes.py
!nop!&6*!
255
Beta Decay
fonte
Se fosse um verdadeiro intérprete, interativo, seria for i in sys.stdin::)
Zizouz212
4
@ Zizouz212 Eu acredito que você quer dizer se foi interativo; parece um verdadeiro intérprete para mim. ;)
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)

Praticamente o mais curto possível. Define uma função anônima que recebe o programa como entrada.

  • Para !, leva x XOR 255, como JSs ~consideraria xum número de 32 bits.
  • Para <, multiplica xpor 2 e pega o resultado mod 256.
  • Pois >, realmente muda os bits de x1 bit para a direita.
  • Para @, pisos x/16e adiciona-o a x%16*16.

Agradecemos a @vihan por sugerir o uso de reducepara salvar um byte.

ETHproductions
fonte
Você pode usar <para salvar cerca de 4 bytes. Usando reduzir pode também poupar alguns bytes
Downgoat
11
@vihan Você quer dizer <no lugar de ==? Nesse caso, isso não funcionaria, pois os caracteres não-op executariam incorretamente uma operação. Eu usei isso na minha solução anterior de 80 bytes.
ETHproductions
Não é o padrão de flecha de gordura ES6 no PPCG que você precisa defini-lo?
MayorMonty
@SpeedyNinja Eu não conheço esse padrão, mas se você puder me indicar um post sobre um, modificarei minha resposta.
ETHproductions
8

CJam, 37 bytes

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

Experimente online no intérprete CJam .

Como 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
fonte
8

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

Uau, isso foi muito jogado! Obrigado a todos que me deram sugestões! Eu aprecio muito!

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);}}

Golpeou 31 (!) Bytes otimizando a troca de mordidelas com operações bit a bit, em oposição a Integer.???métodos longos .

Jogou 72 caracteres (!!!!) com a remoção da sequência desnecessária criada para trocar petiscos. Muito melhor do que antes !?

Jogou 45 (!!) caracteres removendo o uso java.util.Scannere lendo System.indiretamente. Observe que agora que a expressão lambda se foi, o Java 8 não é mais necessário! Apenas o Java 1 faria!

Jogou 7 chars ao criar classe (default)( publicpalavra-chave removida ), graças a @bmarks

Jogou 120 chars (!!!!!!!) chars girando todas aquelas Integeroperações demoradas de classe no bit para 255 - a. Agora isso é muito mais curto!

Jogou 15 chars (!) Convertendo turnos em multiplicação e divisão, removendo os chaves da instrução while e tornando alocal dentro do mainmétodo.

Ungolfed 9 = (caracteres por causa de um problema com o deslocamento à esquerda que não descarta o byte mais à esquerda. Portanto, agora o faço mod (256). O deslocamento à direita tornará o número resultante um pouco mais curto do que antes, portanto, não há necessidade de usar modo deslocamento à direita. Minha coisa de troca de petiscos trocará os últimos 4 bits e o segundo último petisco, e and (&)truncará todos os outros bits.O meu programa de inversão não causa problemas se o número original for menor que 256.

Jogou 31 35 chars graças ao @Geobits, convertendo switchdeclaração para várias declarações ternárias e também convertendo chars para ints, diminuindo os literais.

Jogou 7 chars ao remover desnecessários &240na troca de petiscos ( (a&240)>>4para a>>4e convertendo (a&15)<<4em a<<4&240. A última alteração apenas jogou um caractere no entanto.

Golfed um caractere removendo desnecessário =em a /= 2, porque a = a /= 2é equivalente a a = a / 2.

Golfed 2 chars, virando println- se para print.

Golfou 2 caracteres removendo acidentalmente a=em a=255-a( a=a=255-aé equivalente a a=255-a)

Golfed 1 char, transformando a<<4&240em a%16<<4.

Jogou 1 char adicionando colchetes à parte externa da declaração ternária e fazendo %256. Dessa forma, %16é desnecessário na parte do turno à esquerda da troca de petiscos. Os colchetes adicionam 2 caracteres e os %16salvos 3 caracteres.

Golfed 3 caracteres, alterando classa interfacee removendo publicusando o recurso de método de interface estática de Java 8. Obrigado a @TheNumberOne (sem comentários, mas encontre sua resposta em "Dicas para jogar golfe em Java"

HyperNeutrino
fonte
Não acho que a turma precise ser pública. Além disso, eu acho que se você fizer um um inteiro em vez de um int, você poderia fazer a.parseInt, a.toString, etc., em vez de Integer.parseInt, Integer.toString, etc.
bmarks
Obrigado pela primeira sugestão; Vou remover todos Integeros métodos de classe.
HyperNeutrino
Talvez você possa fazer enquanto ((i = System.in.read ())> 10) em vez de! = 10 para salvar um byte?
marcas
Boa ideia, mas qualquer coisa abaixo de 10 fará com que o programa seja encerrado, e eu devo ignorar outros caracteres, para não tornar o fim do mundo (ou pelo menos o meu programa :)); talvez não há caracteres ASCII válidos abaixo 10.
HyperNeutrino
4
É quase não vale a pena usar um switchgolfe enquanto. Os case/ breaksão muito longos. Você deve ser capaz de salvar um monte, tornando a coisa toda um ternário; algo comoa=i=='!'?255-a:i==62?a/2:i=='<'?a*2%256:i=='@'?(a&240)>>4|(a&15)<<4:a;
Geobits 9/09/09
7

Ferrugem, 121 115 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}

Exemplo de execução:

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

Ungolfed:

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
}

Surpreendentemente curto para Rust. Nada mais interessante além do fato de eu ter aprendido mais regras de precedência hoje - quem sabia que (a>>b)|cé a mesma coisa a>>b|c?

Raspou um byte alterando n>>=1para n/=2; no entanto, o mesmo não pode ser feito com a multiplicação, porque o estouro aritmético é um pânico (ou seja, falha) no Rust.

Maçaneta da porta
fonte
2
A coisa da precedência faz sentido quando você se convence de que >>é uma espécie de divisão semelhante e |é uma adição semelhante.
Lynn
6

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

Puramente para risadinhas, aqui está a calculadora HP 41C / CV / CX. (Requer o módulo Extended Functions ou 41CX para a função ATOX.) Infelizmente, a calculadora não informa o tamanho do programa em bytes.

Coloque seu programa no registro Alpha, o que é um pouco complicado, pois não há como entrar! ou @ diretamente do teclado (use XTOA com os códigos ASCII 33 e 64 respectivamente para anexá-los).

As etapas 08 e 10 permitem ignorar códigos de operação inválidos; remova-os para salvar 2 etapas, mas o programa falhará com entrada invá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
fonte
6

Python 2, 79 bytes

Percebi que fiz algo muito semelhante a isso em Python anteriormente. Esta é apenas uma porta da minha resposta Ruby , mas, aliás, é a resposta mais curta do Python a partir de agora: D

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

A diferença da versão Ruby é que esta não ignora instruções inválidas enquanto itera sobre a entrada. Em vez disso, aproveito o fato de que o Python tende a retornar em -1vez de nilquando não há correspondência - O valor atual de aé anexado à parte de trás da matriz de resultados, para que todas as instruções inválidas sejam mapeadas para o mesmo valor inalterado.

daniero
fonte
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)

"!" é o mesmo que subtrair de 255.
"<" é o mesmo que multiplicar por 2. Mas o registro de 8 bits significa mod 256.
">" é o mesmo que divisão inteira por 2.
"@" significa mudar os últimos 4 bits ( a%16) por 4 bits ( *16) e adicionando os quatro primeiros bits ( a/16).

EDIT (leia a cópia sem vergonha)
Vi a outra resposta em python (por decaimento Beta). Ele usa uma maneira realmente eficaz de simular casos de troca usando o dicionário. Usando isso, podemos escrever

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

Obrigado, Beta Decay.

Rohcana
fonte
Não importa qual operação você faça, você deve reduzir o mod, 256certo? Então por que não fazer isso no final: a={"!":255-a,"<":a*2,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)%256. Isso economiza imediatamente um byte (porque você fará em a*2vez de a<<1) ... mas a resposta de @ daniero também mostra que, se você fizer dessa maneira, (a%16)<<4poderá ser reduzido para apenas a<<4, porque qualquer bit 16 ou maior será eliminado quando você multiplicar por 16 e reduzi-lo mod 256. Bom! Além disso, agora você pode substituir 255-apor -1-a... ou melhor, apenas ~a. No total, essas sugestões devem economizar 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

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

nimi
fonte
3

Ferrugem, 111 bytes

Mais um comentário sobre a resposta da @ Doorknob, mas não tenho nenhum representante para comentar, pois acabei de criar uma conta.

Pode-se raspar 10 bytes de sua solução Rust com o seguinte:

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}
user4867444
fonte
Eu pensei que poderíamos ficar ainda mais curtos usando fold ( doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold ), mas surpreendentemente o torna um pouco mais longo.
user4867444
3

Python 3, 127 bytes

Edit: shorting, obrigado @Jakube

Edit2: corrigir, obrigado @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
fonte
Talvez seja por causa da nova linha do Windows. Isso é mais dois bytes. Vou usar esse contador de bytes na próxima vez. :-) Obrigado.
uno20001
Note que isso não descartar o bit mais à esquerda quando deixou mudando, por isso !<510ao mesmo tempo que deve ser254
Rohcana
Espero que sim. Desculpe pelos meus erros, este é o meu primeiro desafio "golfe".
Uno20001
3

Ceilão, 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);}

Formatado:

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);
}

#fe #f0são números hexadecimais para os nibbles, .byteconverte um número inteiro em um byte. Tenho sorte que o .stringatributo Byte já use a representação não assinada de um byte. O Ceilão também apresenta uma instrução switch sem falhas, e uma string é uma lista de caracteres que podem ser iterados.

Também tentei reduzir esses nomes de métodos de turno longo usando uma importação de alias, mas isso na verdade se torna 7 bytes mais:

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);}

Formatado:

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);
}

Isso pode ser útil se precisarmos desses métodos com mais frequência.

Paŭlo Ebermann
fonte
3

Rubi, 81 73 bytes

Muito mais simples - sem avaliação! Para cada caractere válido na entrada, ele avalia cada instrução e encontra a instrução apropriada através do índice de $&(o caractere atual na entrada).

a=0
gets.scan(/[!><@]/){a=[~a,a/2,a*2,a*16+a/16]["!><@".index$&]&255}
p a
daniero
fonte
11
Isso é genialidade. Muito mais curto que qualquer outro caminho. 2 votos por mim!
Edc65 9/09/15
Como você pode votar duas vezes ...?
HyperNeutrino
@JamesSmith Ele provavelmente referindo-se a isso e minha resposta python :)
daniero
@danerio eu vejo.
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

Ungolfed

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

Não funciona com o intérprete online e requer o intérprete padrão não livre. Isso seria um pouco mais fácil com as operações bit a bit reais, mas não acho que sejam muito úteis para a maioria dos usos comuns do STATA.

marcações
fonte
Por que o intérprete on-line não funciona?
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)

Operadores ternários aninhados mapeiam para instruções.

BITWISE AND é usado para restringir nosso tipo de número a um único byte.

Andrew Vermie
fonte
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 é uma função anônima que aceita uma string e retorna um número inteiro. Para chamá-lo, atribua-o a uma variável.

Ungolfed:

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

Economizou 8 bytes graças ao Sp3000 e 13 graças ao Dennis!

Alex A.
fonte
2

JavaScript (ES6), 76 81

Como uma função sem nome, retornando o valor do acumulador

Esta é uma descrição das respostas super inteligentes de @daniero (que têm muito poucos votos positivos)

Bônus: você pode passar um valor inicial do acumulador. Se não for passado, o valor inicial é 0, conforme específico.

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

Teste a execução do snippet abaixo em qualquer navegador EcmaScript 6 (testei no 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
fonte
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
fonte
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
fonte
2
Você não precisa using System;ou algo assim para acessar Console.ReadLinee Console.Writesem o System.prefixo?
Alex A.
Além disso, parece-me que você não deveria ter que recorrer a bytecada operação, mas eu posso estar errado.
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 pelo uso de um acumulador de string pelo @Beta Decay, visto que lua não tem tipo de byte. Provavelmente poderia jogar mais usando menos funções.

Delya Erricson
fonte
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))))

destroçado

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
fonte
Tudo isso <-pode ser substituído por =aqui, reduzindo assim o código em 7 bytes. Além disso, você pode ser capaz de substituir a série de ifdeclarações por uma chamada para switch(como em A=switch(r,"!"=(A+1)%%2, ...))
plannapus
O 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))))é 167 bytes.
plannapus
1

RPL, 170,5 bytes

A entrada deve ser inserida como uma sequência no nível 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
fonte
1

K, 57 bytes

É um começo:

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

testado 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

Talvez eu consiga fazer melhor no k5, mas é uma série complexa de trocas - por exemplo, converter binário em decimal é tão fácil quanto 2/, mas o comportamento de ?torna mais difícil lidar com um caso padrão para pesquisa de instruções.

JohnE
fonte
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);

Não é que ele supere muitas respostas, é apenas para praticar

Einacio
fonte
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;

Ungolfed:

// 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

Saída HPPPL para o terminal

Essa resposta garante que o HP Prime use números inteiros de 8 bits não assinados, mesmo que o modo esteja definido como, por exemplo, 64 bits pelo usuário. Se a calculadora estiver configurada manualmente para usar números inteiros decimais de 8 bits, o pragmacomando poderá ser omitido. Se a saída não precisar seguir rigorosamente o formato, a*1o final pode ser simplesmente a. Multiplicar o resultado por 1 apenas garante que a saída não siga a saída interna para valores inteiros. O printcomando na linha 4 também pode ser omitido se o terminal não precisar ser limpo antes de imprimir o resultado. Se passar o programa como um argumento de seqüência de caracteres for permitido, o INPUTcomando também poderá ser omitido.

Esta é a versão mais curta com entrada e saída adequada, sem o argumento pragma (se a calculadora estiver definida como Uint8 por padrão:

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
fonte
1

Perl 6, 96 89 bytes

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

Solução antiga:

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

Outras versões que tentei, mas preciso de mais 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
fonte
1

Python 2.7.3, 104 bytes

Ter código em cadeias a serem avaliadas parece bastante sujo, mas 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

Aqui está a saída (e entrada realmente ..)

E sim, ele está realmente rodando em um RaspberryPi :)

Saída de exemplo

Stefan
fonte