Programmazione con bit e byte


40

In questa sfida scriverai un interprete per una lingua semplice che ho inventato. La lingua si basa su un singolo accumulatore A, che è esattamente lungo un byte. All'inizio di un programma, A = 0. Queste sono le istruzioni sulle lingue:

!: Inversione

Questa istruzione inverte semplicemente ogni bit dell'accumulatore. Ogni zero diventa uno e ognuno diventa uno zero. Semplice!

>: Maiusc a destra

Questa istruzione sposta ogni bit in un posto a destra. Il bit più a sinistra diventa zero e il bit più a destra viene scartato.

<: Maiusc a sinistra

Questa istruzione si sposta ogni bit in un posto a sinistra. Il bit più a destra diventa zero e il bit più a sinistra viene scartato.

@: Scambia Nybbles

Questa istruzione scambia i primi quattro bit di A con i quattro bit inferiori. Ad esempio, se A è 01101010ed esegui @, A sarà 10100110:

 ____________________
 |                  |
0110 1010    1010 0110
      |_______|

Queste sono tutte le istruzioni! Semplice vero?

Regole

  • Il programma deve accettare input una volta all'inizio. Questa sarà una riga di codice. Questo non è un interprete interattivo! È possibile accettare l'input solo una volta e non è necessario ritornare all'inizio una volta eseguita quella riga.
  • Il tuo programma deve valutare detto input. Ogni personaggio che non è menzionato sopra viene ignorato.
  • Il programma dovrebbe quindi stampare il valore finale dell'accumulatore, in decimale.
  • Si applicano le regole usuali per linguaggi di programmazione validi.
  • Le scappatoie standard non sono ammesse.
  • Questo è , vince il conteggio dei byte più piccolo.

Ecco alcuni piccoli programmi per testare i tuoi invii. Prima che la freccia sia il codice, dopo che è il risultato previsto:

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

Godere!


Presumo da qui ! -> 255che dovremo usare 8 bit per byte? La domanda non è esplicita.
Toby Speight,

3
@TobySpeight Un byte, per definizione, è 8 bit.
HyperNeutrino,

Risposte:


15

Pyth, 36 35 byte

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

Collaudare l'imbragatura

La rappresentazione interna dell'accumulatore è un numero intero. Questo numero intero è modificato da 256 per ogni iterazione, come desiderato. Le operazioni eseguite sono -G-1, G/2, G*2e Gconvertiti in base 16, invertito, e torna convertito in base 10, dove Gè l'accumulatore.

Ho perso la linea sull'ignorare tutto il resto. Questo è stato risolto. Grazie @Dennis.


Quindi -G-1è più breve rispetto ~Ga Pyth? Ne dubito in qualche modo.
Calcolatrice

Il codice in questione è in realtà t_G, dove _è la negazione ed tè -1. In Pyth, ~significa qualcosa di totalmente diverso.
Isaacg,

Intendevo Python ~(bit a bit NOT)
CalculatorFeline il

@CalculatorFeline Il mio punto era che non esiste una funzione di 1 carattere con quell'effetto in Pyth, quindi il codice sopra (almeno per quell'operazione) è buono come sarà.
Isaacg,

13

C, 96

Supponendo l'ingresso ASCII (o compatibile):

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

più ordinato:

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

Fondamentalmente è solo una raccolta di espressioni ternarie nidificate. Sto aumentando il valore ottenuto da in getchar()modo che un EOF (-1) si traduca in un valore pari a zero e il programma termina.

(collegamento ideone)


1
Ho provato la sfida da solo e ho scritto quasi esattamente lo stesso codice. Btw. il tuo programma non lascia cadere il bit quando si sposta verso l'alto (input: !<>dovrebbe risultare in 127e non 255). Definisci il tuo aas charo usa la linea a&=255(e usa %u) per ottenere l'effetto corretto. Inoltre puoi abbreviare la tua negazione a^255a ~a. a>>4&15è anche più corto del tuo (a&240)/16.
MarcDefiant,

Ah, buon punto. Si è scoperto che era più efficiente mascherare gli 8 bit inferiori ad ogni iterazione.
ossifrage schifoso

1
In questo caso puoi anche usare la stringa di formato %uinvece di%hhu
MarcDefiant

1
L'ho appena visto ora, ma puoi anche usare al a/16|a*16posto di a/16|(a&15)*16. I pochi bit in alto vengono rimossi dal &255.
MarcDefiant,

1
Un piccolo miglioramento: a*257/16è un byte più breve di a/16|a*16.
Toby Speight,

11

Python 3, 133 byte

Utilizza un dizionario per compensare la mancanza di sintassi di caso e caso in Python. Vedi di più qui .

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'accumulatore è una stringa che viene convertita in un numero di base 10 alla fine.

Esempio I / O:

$ python3 bitsnbytes.py
!
255
$ python3 bitsnbytes.py
!>>
63
$ python3 bitsnbytes.py
!<@
239
$ python3 bitsnbytes.py
!nop!&6*!
255

Se fosse un vero interprete interattivo, lo sarebbe for i in sys.stdin::)
Zizouz212

4
@ Zizouz212 Credo che intendi se fosse interattivo; mi sembra un vero interprete. ;)
Alex A.

9

Javascript (ES6), 80 91 90 byte

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 il più corto possibile. Definisce una funzione anonima che accetta il programma come input.

  • Per !, prende x XOR 255, poiché JS ~considererebbe xun numero a 32 bit.
  • Per <, si moltiplica xper 2 e prende il risultato mod 256.
  • Per >, sposta veramente i bit di x1 bit verso destra.
  • Per @, pavimenti x/16e lo aggiunge a x%16*16.

Grazie a @vihan per aver suggerito l'uso di reduceper salvare un byte.


È possibile utilizzare <per salvare circa 4 byte. L'uso di ridurre potrebbe anche salvare alcuni byte
Downgoat

1
@vihan Intendi <al posto di ==? In tal caso, ciò non funzionerebbe, poiché i personaggi non operativi eseguivano erroneamente un'operazione. L'ho usato nella mia precedente soluzione a 80 byte.
ETHproductions

La freccia grassa ES6 standard non è su PPCG che devi definire?
MayorMonty,

@SpeedyNinja Non conosco nessuno di questi standard, ma se potessi indicarmi un post su uno, modificherò la mia risposta.
ETHproductions

8

CJam, 37 byte

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

Provalo online nell'interprete CJam .

Come funziona

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#

8

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

Wow, questo è stato golfato molto! Grazie a tutti quelli che mi hanno dato suggerimenti! Lo apprezzo molto!

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

Giocato a golf 31 (!) Byte ottimizzando lo scambio di nibble con operazioni bit a bit rispetto a Integer.???metodi lunghi .

Golfato 72 (!!!!) caratteri rimuovendo la stringa non necessaria creata per scambiare stuzzichini. Molto meglio di prima !?

Golfati 45 (!!) rimuovendo l'uso java.util.Scannere la lettura System.indirettamente. Nota che ora che l'espressione lambda è sparita, Java 8 non è più necessario! Solo Java 1 lo farebbe!

Golfato 7 caratteri facendo classe (default)( publicparola chiave rimossa ), grazie a @bmarks

Hai giocato a golf 120 (!!!!!!!) trasformando tutte quelle lunghe Integeroperazioni di classe in quel momento 255 - a. Ora è molto più breve!

Golfato 15 (!) Caratteri convertendo i turni in moltiplicazione e divisione, rimuovendo le parentesi graffe dall'istruzione while e rendendola alocale all'interno del mainmetodo.

Ungolfed 9 = (caratteri a causa di un problema con lo spostamento a sinistra che non scarta il byte più a sinistra. Pertanto, ora lo faccio mod (256). Lo spostamento a destra renderà il numero risultante un po 'più corto di prima, quindi non è necessario utilizzarlo modcon lo spostamento a destra. La mia cosa di nibble-swap cambierà gli ultimi 4 bit e il penultimo, e il and (&)troncamento di tutti gli altri bit. Il mio programma di inversione non causa alcun problema se il numero originale è inferiore a 256.

Golfed 31 35 chars grazie alla @Geobits convertendo switchdichiarazione a un sacco di dichiarazioni ternari, e anche la conversione caratteri per interi, accorciando le letterali.

Golfato 7 caratteri rimuovendo inutili &240nello scambio di stuzzichini ( (a&240)>>4in a>>4e convertendoli (a&15)<<4in a<<4&240. L'ultima modifica però ha golfato solo un personaggio.

Golfato 1 carattere rimuovendo non necessario =in a /= 2, perché a = a /= 2equivale a a = a / 2.

Golfato 2 caratteri girando printlnsu print.

Golfed 2 caratteri rimuovendo accidentale a=in a=255-a( a=a=255-aequivale a a=255-a)

Golfato 1 carattere trasformandolo a<<4&240in a%16<<4.

Golfato 1 carattere aggiungendo parentesi all'esterno dell'istruzione ternaria e facendo %256. In questo modo, %16non è necessario nella parte di spostamento a sinistra dello scambio di stuzzichini. Le parentesi aggiungono 2 caratteri e il %16salvataggio 3 caratteri.

Golfed 3 caratteri, cambiando classper interfacee rimozione publicutilizzando la funzione di metodo di interfaccia statica di Java 8. Grazie a @TheNumberOne (nessun commento, ma trova la sua risposta su "Suggerimenti per giocare a golf in Java"


Non penso che la classe debba essere pubblica. Inoltre, penso che se fai un numero intero anziché un int, potresti fare a.parseInt, a.toString, ecc. Invece di Integer.parseInt, Integer.toString, ecc.
contrassegna l'

Grazie per il primo suggerimento; Ho intenzione di rimuovere tutti Integeri metodi di classe però.
HyperNeutrino,

Forse puoi fare while ((i = System.in.read ())> 10) invece di! = 10 per salvare un byte?
segna il

Buona idea, ma qualsiasi cosa al di sotto di 10 farà terminare il programma, e dovrei ignorare altri personaggi, non fare poi la fine del mondo (o almeno il mio programma :)) Lo considererò comunque; forse non ci sono caratteri ASCII validi sotto 10.
HyperNeutrino,

4
Non vale quasi mai la pena di usare un switchpo 'di golf. I case/ breaksono troppo lunghi. Dovresti essere in grado di salvare un mucchio rendendo il tutto un ternario; qualcosa del generea=i=='!'?255-a:i==62?a/2:i=='<'?a*2%256:i=='@'?(a&240)>>4|(a&15)<<4:a;
Geobits,

7

Ruggine, 121 115 byte

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}

Esecuzione di esempio:

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
}

Sorprendentemente abbreviazione di Rust. Nient'altro di veramente interessante oltre al fatto che oggi ho imparato più regole di precedenza: chi sapeva che (a>>b)|cè lo stesso a>>b|c?

Rimozione di un byte cambiando n>>=1in n/=2; tuttavia, lo stesso non può essere fatto con la moltiplicazione, perché l'overflow aritmetico è un panico (cioè un crash) in Rust.


2
La cosa della precedenza ha senso quando ti convinci che >>è una specie di divisione simile ed |è una sorta di aggiunta simile.
Lynn,

6

HP 41C / CV / CX (? Byte, 42 passaggi)

Solo per risatine, eccolo per il calcolatore HP 41C / CV / CX. (Richiede il modulo Funzioni estese o un 41CX per la funzione ATOX. Sfortunatamente la calcolatrice non riporta le dimensioni del programma in byte.

Metti il ​​tuo programma nel registro Alpha, il che è un po 'complicato, poiché non c'è modo di entrare! o @ direttamente dalla tastiera (utilizzare XTOA con i codici ASCII 33 e 64 rispettivamente per aggiungerli).

I passaggi 08 e 10 consentono di ignorare i codici operativi non validi; rimuoverli per salvare 2 passaggi, ma il programma si arresterà in modo anomalo in caso di input non valido.

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

6

Python 2, 79 byte

Mi sono reso conto di aver fatto qualcosa di molto simile a questo in Python in precedenza. Questa è solo una porta della mia risposta di Ruby , ma per inciso è la risposta Python più corta al momento: 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 differenza dalla versione di Ruby è che questa non ignora le istruzioni non valide durante l'iterazione dell'input. Invece approfitto del fatto che Python tende a tornare -1invece che nilquando non c'è corrispondenza: il valore corrente di aviene aggiunto al retro dell'array dei risultati, in modo che tutte le istruzioni non valide vengano mappate allo stesso valore invariato.


4

Python 3, 124 94 93 byte

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)

"!"
equivale a sottrarre 255. "<" equivale a moltiplicare per 2. Ma il registro a 8 bit significa mod 256.
">" è uguale alla divisione intera per 2.
"@" significa spostare gli ultimi 4 bit ( a%16) di 4 bit ( *16) e aggiungendo i primi quattro bit ( a/16).

EDIT (leggi copia spudorata)
Ho visto l'altra risposta in pitone (con decadimento beta). Utilizza un modo davvero efficace per simulare casi di switch usando il dizionario. Usando questo possiamo scrivere

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

Grazie, Decadimento Beta.


Non importa quale operazione fai, devi ridurre la mod, 256giusto? Allora perché non farlo alla fine: a={"!":255-a,"<":a*2,">":a//2,"@":(a%16)<<4+a>>4}.get(i,a)%256. Questo ti fa immediatamente risparmiare un byte (perché lo farai a*2invece di a<<1) ... ma la risposta di @ daniero mostra anche che se lo fai in questo modo, (a%16)<<4puoi accorciarlo a giusto a<<4, perché ogni bit 16 o più grande verrà eliminato una volta moltiplicato di 16 e ridurlo mod 256. Bello! Inoltre, ora puoi sostituire 255-acon -1-a... o meglio, con solo ~a. Complessivamente, questi suggerimenti dovrebbero farti risparmiare 9 byte.
Mathmandan,

3

Haskell, 89 byte

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

Esempio di utilizzo: f "!>>"->63


3

Ruggine, 111 byte

Più di un commento sulla risposta di @ Doorknob, ma non ho alcun rappresentante per i commenti poiché ho appena creato un account.

Uno può radere 10 byte dalla sua soluzione Rust con il seguente:

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}

Pensavo che potremmo essere ancora più brevi usando fold ( doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold ) ma sorprendentemente lo allunga un po 'di più.
user4867444

3

Python 3, 127 byte

Modifica: corto circuito, grazie @Jakube

Edit2: correzione, grazie @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)

Forse è perché la nuova linea di Windows. Questo è più due byte. Userò quel contatore di byte la prossima volta. :-) Grazie.
Uno20001,

Nota che questo non scarta il bit più a sinistra quando si sposta a sinistra, quindi !<510mentre dovrebbe essere254
Rohcana

Spero ora. Scusate i miei errori, questa è la mia prima sfida "golf".
Uno20001,

3

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

formattato:

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 #f0sono numeri esadecimali per i nibble, .byteconverte un numero intero in un byte. Sono fortunato che l' .stringattributo Byte utilizza già la rappresentazione senza segno di un byte. Ceylon presenta anche un'istruzione switch senza fall-through e una stringa è un elenco di caratteri, che può essere ripetuto.

Ho anche cercato di abbattere quei nomi di metodi a turni lunghi usando un'importazione di aliasing, ma questo in realtà diventa 7 byte più a lungo:

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

formattato:

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

Questo potrebbe essere utile se abbiamo bisogno di questi metodi un po 'più spesso.


3

Rubino, 81 73 byte

Molto più semplice: niente valutazione! Per ogni carattere valido nell'input, valuta ogni istruzione e trova l'istruzione appropriata attraverso l'indice di $&(il carattere corrente nell'input).

a=0
gets.scan(/[!><@]/){a=[~a,a/2,a*2,a*16+a/16]["!><@".index$&]&255}
p a

1
È geniale. Molto più breve che in qualsiasi altro modo. 2 voti da parte mia!
edc65,

Come puoi raddoppiare il tuo voto ...?
HyperNeutrino,

@JamesSmith Probabilmente si riferisce a questa e alla mia risposta di Python :)
daniero,

@danerio vedo.
HyperNeutrino,

2

STATA, 197 byte

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

Non funziona con l'interprete online e richiede l'interprete predefinito non libero. Ciò sarebbe in qualche modo più semplice con le operazioni bit a bit effettive, ma non penso che siano troppo utili per la maggior parte degli usi comuni di STATA.


Perché l'interprete online non funziona?
Calcolatrice

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)

Gli operatori ternari nidificati eseguono il mapping alle istruzioni.

BITWISE AND viene utilizzato per vincolare il nostro tipo Numero a un singolo byte.


2

Julia, 117 94 86 73 byte

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)

Questa è una funzione anonima che accetta una stringa e restituisce un numero intero. Per chiamarlo, assegnarlo a una variabile.

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

Risparmiato 8 byte grazie a Sp3000 e 13 grazie a Dennis!


2

JavaScript (ES6), 76 81

Come una funzione senza nome che restituisce il valore dell'accumulatore

Questo è il porting delle risposte super intelligenti di @daniero (che hanno troppi voti troppo bassi)

Bonus: puoi passare un valore iniziale dell'accumulatore. Se non passato, il valore iniziale è 0 come da specifico.

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

Prova a eseguire lo snippet di seguito in qualsiasi browser EcmaScript 6 (ho testato in 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>


1

Cristallo, 139 byte

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

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

2
Non ti serve using System;o qualcosa del genere per accedere Console.ReadLinee Console.Writesenza il System.prefisso?
Alex A.

Inoltre mi sembra che non dovresti fare il cast byteper ogni operazione, ma potrei sbagliarmi.
Alex A.

1

Lua, 344 caratteri

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

Ispirato dall'uso di @Beta Decay di un accumulatore di stringhe, visto che lua non ha un tipo di byte. Probabilmente si potrebbe giocare più a golf usando meno funzioni.


1

R, 194 byte

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

ungolfed

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

Tutto <-può essere sostituito da =qui, riducendo così il codice di 7 byte. Inoltre potresti essere in grado di sostituire la serie di ifdichiarazioni con una chiamata a switch(come in A=switch(r,"!"=(A+1)%%2, ...))
plannapus,

Il risultato 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 byte.
plannapus,

1

RPL, 170,5 byte

L'ingresso deve essere inserito come stringa al livello 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 \>> 
\>>

1

K, 57 byte

È un inizio:

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

testato con 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

Potrei essere in grado di fare meglio in k5, ma è una serie complessa di compromessi - per esempio, convertire il binario in decimale è facile come 2/, ma il comportamento di ?rende più difficile gestire un caso predefinito per la ricerca delle istruzioni.


1

PHP, 189 byte

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

Non è che batterà molte risposte, è solo per esercitarsi


1

HPPPL , 302 294 byte

#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 di input HPPPL

Uscita HPPPL al terminale

Questa risposta garantisce che HP Prime utilizzi numeri interi a 8 bit senza segno anche se la modalità è impostata, ad esempio, a 64 bit dall'utente. Se la calcolatrice è impostata manualmente per utilizzare numeri decimali a 8 bit senza segno, è pragmapossibile omettere il comando. Se l'output non ha bisogno di seguire rigorosamente il formato, allora a*1alla fine può essere semplicemente a. Moltiplicare il risultato per 1 garantisce che l'output non segua l'output interno per i valori interi. Il printcomando nella riga 4 può anche essere omesso se non è necessario cancellare il terminale prima di stampare il risultato. Se è consentito passare il programma come argomento stringa, è INPUTpossibile omettere anche il comando.

Questa è la versione più breve con input e output appropriati, senza l'argomento pragma (se la calcolatrice è impostata su Uint8 per impostazione predefinita:

243 byte:

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;

1

Perl 6, 96 89 byte

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

Vecchia soluzione:

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

1

C #, 119 byte

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

Altre versioni che ho provato, ma ho bisogno di più byte:

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

1

Python 2.7.3, 104 byte

Avere il codice nelle stringhe da valutare sembra piuttosto sporco, ma funziona: 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

Ecco l'output (e l'input in realtà ..)

E sì, è davvero in esecuzione su un RaspberryPi :)

Esempio di output

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.