Programmation avec des bits et des octets

40

Dans ce défi, vous allez écrire un interprète pour un langage simple que j'ai composé. La langue est basée sur un seul accumulateur A, qui a exactement une longueur d'un octet. Au début d'un programme, A = 0. Voici les instructions relatives aux langues:

!: Inversion

Cette instruction inverse simplement chaque bit de l'accumulateur. Chaque zéro devient un et chaque devient un zéro. Simple!

>: Décaler à droite

Cette instruction déplace chaque bit dans A un endroit vers la droite. Le bit le plus à gauche devient un zéro et le bit le plus à droite est supprimé.

<: Décalage à gauche

Cette instruction décale chaque bit dans A un endroit à gauche. Le bit le plus à droite devient un zéro et le bit le plus à gauche est supprimé.

@: Echangez des Nybbles

Cette instruction permute les quatre bits supérieurs de A avec les quatre bits inférieurs. Par exemple, si A est 01101010et que vous exécutez @, A sera 10100110:

 ____________________
 |                  |
0110 1010    1010 0110
      |_______|

C'est toutes les instructions! Simple, non?

Règles

  • Votre programme doit accepter une entrée au début. Ce sera une ligne de code. Ce n'est pas un interprète interactif! Vous ne pouvez accepter qu'une entrée et vous n'avez pas besoin de revenir au début une fois que cette ligne a été exécutée.
  • Votre programme doit évaluer ladite entrée. Tout caractère non mentionné ci-dessus est ignoré.
  • Votre programme devrait alors imprimer la valeur finale de l'accumulateur, en décimal.
  • Les règles habituelles pour les langages de programmation valides s'appliquent.
  • Les failles standard sont interdites.
  • C'est le , le plus petit nombre d'octets gagne.

Voici quelques petits programmes pour tester vos soumissions. Avant la flèche est le code, après c'est le résultat attendu:

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

Prendre plaisir!

bitsnbites
la source
Je suppose ! -> 255qu'à partir de cela, nous devrions utiliser 8 bits par octet ici? La question n'est pas explicite.
Toby Speight le
3
@TobySpeight Un octet, par définition, est de 8 bits.
HyperNeutrino

Réponses:

15

Pyth, 36 35 octets

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

Harnais de test

La représentation interne de l'accumulateur est un entier. Ce nombre entier est modifié par 256 à chaque itération, comme vous le souhaitez. Les opérations effectuées sont -G-1, G/2, G*2et Gconverties en base 16, inversée, et à l' arrière converti en base 10, où Gest l'accumulateur.

J'ai raté la ligne à propos d'ignorer tout le reste. Ceci a été corrigé. Merci, Dennis.

isaacg
la source
Donc, -G-1est plus court qu'en ~GPyth? J'en doute un peu.
CalculatriceFeline
Le code en question est en fait t_G, où _est la négation et test -1. En Pyth, ~signifie quelque chose de totalement différent.
isaacg
Je voulais dire Python ~(bitwise PAS)
CalculatorFeline
@CalculatorFeline Mon point était qu'il n'y avait pas de fonction à 1 caractère avec cet effet en Pyth, donc le code ci-dessus (du moins pour cette opération) est aussi bon qu'il va l'être.
isaacg
13

C, 96

En supposant que l’entrée ASCII (ou 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);
}

Fondamentalement, il s'agit simplement d'une collection d'expressions ternaires imbriquées. J'incrémente la valeur obtenue à partir de getchar()sorte qu'un EOF (-1) donne une valeur de zéro et que le programme se termine.

(lien ideone)

ossifrage délirant
la source
1
J'ai essayé le défi moi-même et j'ai écrit presque exactement le même code. Btw. votre programme ne lâche pas le bit lorsqu’on passe à la vitesse supérieure (entrée: !<>devrait entraîner 127et non 255). Définissez votre en atant que char, ou utilisez la ligne a&=255(et utilisez %u) pour obtenir le bon effet. Aussi, vous pouvez raccourcir votre négation a^255à ~a. a>>4&15est également plus courte que votre (a&240)/16.
MarcDefiant
Ah, bon point. Il s'avère qu'il était plus efficace de masquer les 8 bits inférieurs à chaque itération.
ossifrage
1
Dans ce cas, vous pouvez même utiliser la chaîne de format %uau lieu de%hhu
MarcDefiant
1
Je viens de le voir maintenant, mais vous pouvez également utiliser à la a/16|a*16place de a/16|(a&15)*16. Les quelques bits en haut sont enlevés par le &255.
MarcDefiant
1
Une amélioration minime: a*257/16est un octet plus court que a/16|a*16.
Toby Speight le
11

Python 3, 133 octets

Utilise un dictionnaire pour compenser un manque de syntaxe de casse en Python. Voir plus ici .

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

L'accumulateur est une chaîne qui est convertie en un nombre de base 10 à la fin.

Exemple I / O:

$ python3 bitsnbytes.py
!
255
$ python3 bitsnbytes.py
!>>
63
$ python3 bitsnbytes.py
!<@
239
$ python3 bitsnbytes.py
!nop!&6*!
255
Beta Decay
la source
Si c'était un vrai interprète interactif, ce serait for i in sys.stdin::)
Zizouz212
4
@ Zizouz212 Je pense que vous voulez dire si c'était interactif; cela ressemble à un véritable interprète pour moi. ;)
Alex A.
9

Javascript (ES6), 80 91 90 octets

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

À peu près aussi court que possible. Définit une fonction anonyme qui prend le programme en entrée.

  • Pour !, prend x XOR 255, comme JS ~envisagerait xun nombre 32 bits.
  • Pour <, multiplie xpar 2 et prend le résultat mod 256.
  • Car >, décale vraiment les bits de x1 bit vers la droite.
  • Pour @, les sols x/16et les ajoute x%16*16.

Merci à @vihan pour avoir suggéré d'utiliser reducepour sauvegarder un octet.

ETHproductions
la source
Vous pouvez utiliser <pour économiser environ 4 octets. Réduire peut également économiser des octets
Downgoat
1
@ vihan Voulez-vous dire <à la place de ==? Si tel est le cas, cela ne fonctionnerait pas, car les caractères non-op ne procéderaient pas correctement à une opération. Je l'ai utilisé dans ma précédente solution de 80 octets.
ETHproductions
N'est-ce pas le standard ES6 Fat Arrow standard sur PPCG que vous devez définir?
MayorMonty
@SpeedyNinja Je ne connais aucun standard de ce type, mais si vous pouviez m'indiquer un message à propos d'un post, je modifierais ma réponse.
ETHproductions
8

CJam, 37 octets

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

Essayez-le en ligne dans l' interprète CJam .

Comment ça marche

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
la source
8

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

Wow, cela a été beaucoup joué au golf! Merci à tous ceux qui m'ont fait des suggestions! Je l'apprécie énormément!

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 (!) Octets en optimisant l'échange de nibble avec des opérations au niveau des bits, par opposition à des Integer.???méthodes longues .

Golfé 72 caractères (!!!!) en supprimant la chaîne inutile créée pour permuter les petits bouts. Beaucoup mieux qu'avant !?

Golfé 45 (!!) caractères en supprimant l'utilisation java.util.Scanneret la lecture de System.indirectement. Notez que maintenant que l'expression lambda a disparu, Java 8 n'est plus requis! Tout simplement Java 1 ferait!

Golfé 7 caractères en faisant classe (default)( publicmot-clé supprimé ), grâce à @bmarks

Golfé 120 (!!!!!!!) personnages en tournant toutes ces Integeropérations de classe longues dans le bit basculant vers 255 - a. Maintenant c'est beaucoup plus court!

Golfé 15 (!) Caractères en convertissant les décalages en multiplication et division, en supprimant les accolades de la déclaration while et en rendant alocal la mainméthode.

Ungolfed 9 = (caractères à cause d'un problème avec le décalage gauche ne supprimant pas l'octet le plus à gauche. Par conséquent, je le fais maintenant mod (256). Le décalage droit réduira le bit numéro un plus court qu'avant, il n'est donc pas nécessaire d'utiliser modle décalage droit. Mon truc interchangeable échangera les 4 derniers bits et l'avant-dernier nibble, et and (&)tronquera tous les autres bits. Mon programme d'inversion ne pose aucun problème si le nombre d'origine est inférieur à 256.

Golfé 31 35 caractères grâce à @Geobits en convertissant une switchdéclaration en plusieurs déclarations ternaires et en convertissant des caractères en entiers, raccourcissant les littéraux.

Golfé 7 caractères en supprimant inutile &240dans le swap de swap ( (a&240)>>4à a>>4et convertir (a&15)<<4en a<<4&240. Le dernier changement a joué au golf cependant un personnage.

Golfé 1 caractère en supprimant inutile =dans a /= 2, car a = a /= 2est équivalent à a = a / 2.

Golfé 2 personnages en se tournant printlnvers print.

Golfé 2 caractères en supprimant accidentelle a=dans a=255-a( a=a=255-aest équivalent à a=255-a)

Golfé 1 caractère en se transformant a<<4&240en a%16<<4.

Golfé 1 caractère en ajoutant des parenthèses à l'extérieur de la déclaration ternaire et en faisant %256. De cette façon, le %16n'est pas nécessaire dans la partie gauche du swap. Les crochets ajoutent 2 caractères et les %16enregistre 3 caractères.

3 caractères golfed en changeant classde interfaceet la suppression en publicutilisant la fonction de la méthode d'interface statique Java 8. Merci à @TheNumberOne (pas de commentaire, mais trouvez sa réponse sur "Astuces pour jouer au golf en Java"

HyperNeutrino
la source
Je ne pense pas que la classe doit être publique. Aussi, je pense que si vous faites un Integer au lieu d'un int, vous pouvez faire a.parseInt, a.toString, etc. au lieu d'Integer.parseInt, Integer.toString, etc.
bmarks
Merci pour la première suggestion. Je vais cependant supprimer toutes Integerles méthodes de classe.
HyperNeutrino
Peut-être que vous pouvez faire tout en ((i = System.in.read ())> 10) au lieu de! = 10 pour sauvegarder un octet?
bmarks
Bonne idée, mais tout ce qui est en dessous de 10 entraînera la fin du programme, et je suis censé ignorer les autres personnages, ne pas faire alors la fin du monde (ou du moins mon programme :)) Je vais y réfléchir cependant; Peut-être n'y a-t-il pas de caractères ascii valides en dessous de 10.
HyperNeutrino
4
Cela ne vaut presque jamais la peine de switchjouer au golf. Les case/ breaksont trop long. Vous devriez être capable de sauver beaucoup de monde en faisant de l’ensemble un ternaire; quelque chose commea=i=='!'?255-a:i==62?a/2:i=='<'?a*2%256:i=='@'?(a&240)>>4|(a&15)<<4:a;
Geobits
7

Rouille, 121 à 115 octets

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}

Échantillon échantillon:

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
}

Étonnamment court pour Rust. Rien d’autre vraiment intéressant à part le fait que j’ai appris plus de règles de préséance aujourd’hui - qui savait (a>>b)|cc’est la même chose a>>b|c?

Rasé un octet en changeant n>>=1à n/=2; Cependant, on ne peut pas faire la même chose avec la multiplication, car un dépassement arithmétique est une panique (un crash) dans Rust.

Poignée de porte
la source
2
La chose la priorité est logique lorsque vous vous convaincre que >>est sorte de comme la division et |est sorte de comme l' addition.
Lynn
6

HP 41C / CV / CX (? Octets, 42 étapes)

Purement pour rire, le voici pour la calculatrice HP 41C / CV / CX. (Nécessite le module Extended Functions ou un module 41CX pour la fonction ATOX.) Malheureusement, la calculatrice ne signale pas la taille des programmes en octets.

Mettez votre programme dans le registre Alpha, ce qui est un peu délicat, car il n'y a aucun moyen d'entrer! ou @ directement à partir du clavier (utilisez XTOA avec les codes ASCII 33 et 64, respectivement, pour les ajouter).

Les étapes 08 et 10 permettent d’ignorer les codes non valides; supprimez-les pour enregistrer 2 étapes, mais le programme se bloquera sur une entrée non valide.

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
la source
6

Python 2, 79 octets

J'ai réalisé que j'avais déjà fait quelque chose de très similaire à cela en Python. Ceci n’est qu’un portage de ma réponse Ruby , mais c’est d'ailleurs la réponse la plus courte en Python: 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 différence avec la version de Ruby est que celle-ci n'ignore pas les instructions non valides lors d'une itération sur l'entrée. Au lieu de cela, je profite du fait que Python a tendance à renvoyer -1au lieu de nilquand il n'y a pas de correspondance - La valeur actuelle de aest ajoutée à l'arrière du tableau de résultats, de sorte que toutes les instructions non valides correspondent à la même valeur inchangée.

Daniero
la source
4

Python 3, 124 94 93 octets

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)

"!" est identique à soustraire de 255.
"<" équivaut à multiplier par 2. Mais le registre à 8 bits signifie mod 256.
">" est identique à la division entière par 2.
"@" signifie décaler les 4 derniers bits ( a%16) de 4 bits (*16 ) et en ajoutant les quatre premiers bits ( a/16).

EDIT (lire copie sans vergogne)
Vu l'autre réponse en python (par Beta decay). Il utilise un moyen très efficace pour simuler des cas de commutation en utilisant un dictionnaire. En utilisant ça on peut écrire

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

Merci, Beta Decay.

Rohcana
la source
Quelle que soit l'opération que vous faites, vous devez réduire le mod 256non? Alors pourquoi ne pas le faire à la fin: a={"!":255-a,"<":a*2,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)%256. Cela vous évite immédiatement un octet (parce que vous le ferez a*2au lieu de a<<1) ... mais la réponse de @daniero montre également que si vous le faites de cette façon, il (a%16)<<4est possible de le raccourcir a<<4, car tout bit de 16 ou plus sera éliminé une fois multiplié. par 16 et le réduire mod 256. Nice! En outre, vous pouvez maintenant remplacer 255-apar -1-a... ou mieux, simplement ~a. Au total, ces suggestions devraient vous faire économiser 9 octets.
mathmandan
3

Haskell, 89 octets

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

Exemple d'utilisation: f "!>>"->63

nimi
la source
3

Rouille, 111 octets

Plus d'un commentaire sur la réponse de @ Doorknob, mais je n'ai aucun représentant pour les commentaires, car je viens de créer un compte.

On peut raser 10 octets de sa solution Rust avec ce qui suit:

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}
utilisateur4867444
la source
Je pensais que nous pouvions être encore plus courts en utilisant fold ( doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold ) mais, étonnamment, le rend un peu plus long.
user4867444
3

Python 3, 127 octets

Edit: court-circuit, merci @ Jakube

Edit2: corrige, merci @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
la source
C'est peut-être parce que la nouvelle ligne de Windows. C'est plus deux octets. J'utiliserai ce compteur d'octets la prochaine fois. :-) Merci.
uno20001
Notez que cela n'élimine pas le bit le plus à gauche lorsque vous !<510254
déplacez à
J'espère que maintenant c'est le cas. Désolé pour mes erreurs, ceci est mon premier défi "golf".
uno20001
3

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

Formaté:

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

#fet #f0sont des nombres hexadécimaux pour les quartets, .byteconvertit un entier en octet. J'ai de la chance que Byte.string attribut utilise déjà la représentation non signée d'un octet. Ceylan comporte également une instruction switch sans basculement, et une chaîne de caractères est une liste de caractères pouvant être itérés.

J'ai également essayé de réduire ces noms de méthode de décalage long en utilisant une importation de repliement de spectre, mais cela devient en réalité 7 octets plus longs:

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

Formaté:

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

Cela pourrait être utile si nous avons besoin de ces méthodes un peu plus souvent.

Paŭlo Ebermann
la source
3

Rubis, 81 73 octets

Tellement plus simple - pas d'eval! Pour chaque caractère valide de l'entrée, il évalue chaque instruction et recherche l'instruction appropriée à l'aide de l'index de $&(le caractère actuel de l'entrée).

a=0
gets.scan(/[!><@]/){a=[~a,a/2,a*2,a*16+a/16]["!><@".index$&]&255}
p a
Daniero
la source
1
C'est du génie. Beaucoup plus court que tout autre moyen. 2 votes positifs par moi!
Edc65
Comment pouvez-vous doubler votre vote ...?
HyperNeutrino
@ JamesSmith Il fait probablement allusion à cela et à ma réponse en python :)
daniero
@ danerio je vois.
HyperNeutrino
2

STATA, 197 octets

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

Ne fonctionne pas avec l'interpréteur en ligne et requiert l'interpréteur par défaut non libre. Ce serait un peu plus facile avec les opérations au niveau des bits, mais je ne pense pas qu'elles soient trop utiles pour la plupart des utilisations courantes de STATA.

bmarks
la source
Pourquoi l'interprète en ligne ne fonctionne-t-il pas?
CalculatriceFeline
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)

Les opérateurs ternaires imbriqués mappent les instructions.

BITWISE AND est utilisé pour contraindre notre type Number à un seul octet.

Andrew Vermie
la source
2

Julia, 117 94 86 73 octets

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)

C'est une fonction anonyme qui accepte une chaîne et renvoie un entier. Pour l'appeler, assignez-le à une variable.

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

Sauvegardé 8 octets grâce à Sp3000 et 13 grâce à Dennis!

Alex A.
la source
2

JavaScript (ES6), 76 81

En tant que fonction non nommée renvoyant la valeur de l'accumulateur

Ceci est un portage des réponses super intelligentes de @daniero (qui ont trop peu de votes positifs)

Bonus: vous pouvez passer une valeur initiale de l'accumulateur. Si non passé, la valeur de départ est 0 comme spécifique.

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

Testez l'exécution de l'extrait ci-dessous dans n'importe quel navigateur EcmaScript 6 (j'ai testé dans 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
la source
1

Crystal, 139 octets

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
la source
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
la source
2
N'avez-vous pas besoin using System;ou quelque chose comme ça pour accéder Console.ReadLineet Console.Writesans le System.préfixe?
Alex A.
De plus, il me semble que vous ne devriez pas avoir à faire de casting bytepour chaque opération, mais je peux me tromper.
Alex A.
1

Lua, 344 car.

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

Inspiré par l'utilisation par @Beta Decay d'un accumulateur de chaîne, vu que lua n'a aucun type d'octet. Pourrait probablement être joué davantage en utilisant moins de fonctions.

Delya Erricson
la source
1

R, 194 octets

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

non-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
la source
Tout <-peut être remplacé par =ici, réduisant ainsi le code de 7 octets. De plus, vous pourrez peut-être remplacer la série de ifdéclarations par un appel à switch(comme dans A=switch(r,"!"=(A+1)%%2, ...))
plannapus le
Le résultat 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))))est 167 octets.
Plannapus
1

RPL, 170,5 octets

L'entrée doit être entrée sous forme de chaîne au niveau 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
la source
1

K, 57 octets

C'est un début:

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

testé avec 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

Je pourrais peut-être faire mieux en k5, mais c'est une série complexe de compromis - par exemple, convertir du binaire en décimal est aussi facile que 2/, mais le comportement de ?rend plus difficile la gestion d'un cas par défaut pour la recherche d'instruction.

JohnE
la source
1

PHP, 189 octets

<? $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);

Ce n'est pas que ça va battre beaucoup de réponses, c'est seulement pour la pratique

Einacio
la source
1

HPPPL , 302 294 octets

#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;

Commande d'entrée HPPPL

Sortie HPPPL vers le terminal

Cette réponse garantit que le HP Prime utilise des entiers 8 bits non signés, même si le mode est défini sur 64 bits par exemple par l'utilisateur. Si la calculatrice est configurée manuellement pour utiliser des entiers décimaux à 8 bits non signés, la pragmacommande peut être omise. Si la sortie n'a pas à suivre strictement le format, a*1la fin peut simplement l'être a. En multipliant le résultat par 1, on s'assure simplement que la sortie ne suit pas la sortie interne pour les valeurs entières. La printcommande de la ligne 4 peut également être omise si le terminal n'a pas besoin d'être effacé avant l'impression du résultat. Si le passage du programme en tant qu’argument de chaîne est autorisé, alors leINPUT commande peut également être omise.

C'est la version la plus courte avec entrée et sortie correcte, sans l'argument pragma (si la calculatrice est définie sur Uint8 par défaut:

243 octets:

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
la source
1

Perl 6, 96 89 octets

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

Ancienne solution:

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

C #, 119 octets

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

Les autres versions que j'ai essayées, mais qui nécessitent plus d'octets:

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
la source
1

Python 2.7.3, 104 octets

Avoir du code dans les chaînes à évaluer est plutôt sale, mais ça marche: 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

Voici la sortie (et l'entrée en fait ..)

Et oui, ça marche vraiment sur un RaspberryPi :)

Exemple de sortie

Stefan
la source