Operatori bit a bit in Brainfuck


13

Il tuo compito è creare un programma brainfuck per ciascuno dei seguenti operatori binari. Ogni programma dovrebbe prendere uno o due numeri a 8 bit (A e B) dall'input e calcolare l'operazione specificata:

  1. A XOR B
  2. A AND B
  3. A OR B
  4. A Shifted Left by 1 (circular shift)
  5. NOT A

Non è necessario implementare tutti i 5. Il punteggio è calcolato da:

#totalCharacters + {4000 * #problemsNotCompleted}

Quindi i punteggi validi vanno da zero (migliore) a 20.000 (nulla di completato).

Non mi interessa dove memorizzi il risultato o se preservi o meno l'input. Assumi celle a 8 bit e tutte le celle vuote di cui hai bisogno solo sulla destra.

Puoi presumere che i numeri siano già in qualunque posizione di memoria funzioni meglio per te, quindi non devi preoccuparti delle operazioni di I / O.


Possiamo anche risolvere il compito in un linguaggio minimalista simile come iot?
FUZxxl,

Non ho obiezioni su altre lingue, purché non ci siano operatori bit per bit integrati.
captncraig,

Risposte:


7

Punteggio: 275

Funziona meglio per espanderli con un contatore binario. Le parti meno intuitive hanno a che fare con la possibilità che A o B siano 0. Non ho trovato un modo redditizio per usare il controllo del flusso non distruttivo nella manipolazione effettiva dei bit dei primi tre. Per inciso, questi dovrebbero funzionare tutti bene con celle a 16 bit e lentamente a 32 bit.

XOR, 86

Presuppone che A e B siano nelle celle 1 e 2, memorizza A XOR B nella cella 2, il puntatore inizia nella cella 0 e termina nella cella 5.

-[[>>>>>>[>>>]++[-<<<]<<<-]>]>>>[<]>[[>[>-<-]>[<<<<<<+>>>>>>[-]]>]+[<[<<<++>>>-]<<]>>]

E, 78

Presuppone che A e B siano nelle celle 1 e 2, memorizza A OR B nella cella 4, il puntatore inizia nella cella 0 e termina nella cella 5.

-[[>>>>>>[>>>]++[-<<<]<<<-]>]>>>[<]>[[>[>[<<<<+>>>>-]<-]>+>]<[<[<<<++>>>-]<<]]

OPPURE, 86

Presuppone che A e B siano nelle celle 1 e 2, memorizza A OR B nella cella 2, il puntatore inizia nella cella 0 e termina nella cella 5.

-[[>>>>>>[>>>]++[-<<<]<<<-]>]>>>[<]>[[>[>+<-]>[<<<<<<+>>>>>>[-]]>]+[<[<<<++>>>-]<<]>>]

ROL, 18

Presuppone che A sia nella cella 0, memorizza A ROL 1 nella cella 1, il puntatore inizia e termina nella cella 0.

[>++[>>]<[>+>]<<-]

NON, 7

Presuppone che A sia nella cella 0, che memorizzi NOT A nella cella 1, il puntatore inizia e termina nella cella 0.

+[>-<-]

È davvero breve e piuttosto interessante. +1
copia il

Miglioramenti seriamente impressionanti.
captncraig,

8

Punteggio: 686

Tutti i frammenti presumono che i numeri siano già caricati nelle celle 0 e 1 e che il puntatore punti alla cella 0. Posso aggiungere un frammento audio in un secondo momento, se necessario per la sfida. Per ora, puoi provare il codice in questo modo:

+++++++++>    number 1
++++<         number 2


XOR, 221

Il risultato viene scritto nella cella 10, il puntatore termina nella cella 5

>>>>>++++++++[-<<<<<[->>+<<[->>->+<]>>[->>>>+<<]<<<<]>>>[-<<<+>>>]<<[->+<[->->+>
>>>>]>[->>>>>+>>]<<<<<<<<]>>[-<<+>>]>>>[->>+<<]>[>[-<->]<[->+<]]>[[-]<<<[->+>-<<
]>[-<+>]+>+++++++[-<[->>++<<]>>[-<<+>>]<]<[->>>>+<<<<]>>]<<<]

E, 209

Il risultato viene scritto nella cella 10, il puntatore termina nella cella 5

>>>>>++++++++[-<<<<<[->>+<<[->>->+<]>>[->>>>+<<]<<<<]>>>[-<<<+>>>]<<[->+<[->->+>
>>>>]>[->>>>>+>>]<<<<<<<<]>>[-<<+>>]>>>[->[->+<]<]>[-]>[-<<<[->+>-<<]>[-<+>]+>++
+++++[-<[->>++<<]>>[-<<+>>]<]<[->>>>+<<<<]>>]<<<]

O, 211

Il risultato viene scritto nella cella 10, il puntatore termina nella cella 5

>>>>>++++++++[-<<<<<[->>+<<[->>->+<]>>[->>>>+<<]<<<<]>>>[-<<<+>>>]<<[->+<[->->+>
>>>>]>[->>>>>+>>]<<<<<<<<]>>[-<<+>>]>>>[->>+<<]>[->+<]>[[-]<<<[->+>-<<]>[-<+>]+>
+++++++[-<[->>++<<]>>[-<<+>>]<]<[->>>>+<<<<]>>]<<<]

Ruota a sinistra, 38

Il risultato viene scritto nella cella 1, il puntatore termina nella cella 4

[->++>+<[>-]>[->>+<]<<<]>>>>[-<<<+>>>]

NON, 7

Il risultato viene scritto nella cella 1, il puntatore termina nella cella 0

+[+>+<]


Spiegazione:

XOR, AND e OR funzionano tutti in modo simile: calcola n / 2 per ciascun numero e ricorda n mod 2. Calcola lo XOR / AND / OR logico per i singoli bit. Se il bit risultante è impostato, aggiungere 2 ^ n al risultato. Ripeti 8 volte.

Questo è il layout di memoria che ho usato:

 0      1        2        3      4        5         6        7
n1  |  n2  |  marker  |  n/2  |  0  |  counter  |  bit1  |  bit2  |

  8        9        10
temp  |  temp  |  result

Ecco la fonte per XOR (i numeri indicano dove si trova il puntatore in quel momento):

>>>>>
++++ ++++ counter
[
    -
    <<<<<

    divide n1 by two
    [ 0 
        -
        >>+ set marker 2
        << 0
        [->>->+<] dec marker inc n/2
        >> 2 or 4
        [->>>>+<<] 
        <<<<
    ]
    >>>
    [-<<<+>>>]
    <<

    divide n2 by two
    [ 1
        -
        >+ set marker 2
        < 1
        [->->+>>>>>] dec marker inc n/2
        > 2 or 9
        [->>>>>+>>]
        <<<< <<<< 
    ]
    >>[-<<+>>] 3

    >>> 6

    [->>+<<]>[>[-<->]<[->+<]]>  one bit xor 8

    [
        [-]<<< 5
        [->+>-<<] copy counter negative
        > 6
        [-<+>]
        +> 7
        ++++ +++  cell 6 contains a one and cell 7 how many bits to shift
        [-<[->>++<<]>>[-<<+>>]<]  2^n
        < 6
        [->>>>+<<<<]
        >> 8
    ]

    <<<
]


Per la rotazione a sinistra, c'è ancora una volta un marcatore nella cella 2 per determinare se 2n è zero, poiché è possibile determinare solo se una cella è direttamente diversa da zero. In tal caso, un bit di carry viene scritto nella cella 4 e successivamente aggiunto a 2n. Questo è il layout di memoria:

0      1        2       3       4   
n  |  2n  |  marker  |  0  |  carry 

Ottimo lavoro! Intendevo che ogni programma prendesse input dalla console, ma più ci penso, la tua strada funziona bene. Non c'è bisogno di farti aggiungere ,>,<. Modifica la domanda.
captncraig,

Sarei interessato a sentire un po 'di una spiegazione su come funzionano. Sembra che i tuoi primi tre siano abbastanza simili, tranne per la parte più interna, ma non sono sicuro che tu stia facendo una sorta di espansione binaria (quindi sono necessarie 8 celle), o un confronto a poco a poco, o una combinazione delle due. Difficile da vedere entrando.
captncraig,

@CMP Aggiungerò una spiegazione in seguito
copia l'

3

Punteggio (attuale): 12038 837 / -

I programmi presuppongono che i numeri vengano caricati in qualsiasi cella specificata, da ,o simili. Presuppone inoltre che tutte le celle siano senza segno a 8 bit con wrapping, se necessario. All'inizio di ogni frammento, i numeri vengono caricati nella cella 0 (e 1 se necessario).

Operazioni bit - 799

Le operazioni con i bit seguono la stessa struttura generale.

Firstly, we define a divmod 2 (DM2) function.
CELLS:   A  B   C  D
INPUT:  *A  0   0  0
OUTPUT: *0 A/2 A%2 0
dp@A; while{
  dec A,2; inc B,1; dp@A; inc A,1
  while{ #Check if A was 1 at the start
    dec D,1; pour A,C; dp@A;
  }
  dec C,1; pour C,A; inc D,1; dp@D
  #If A was 1 at the start, D will be 1 here
  while{ 
    dec D,1; inc C,1; dec B,1; dp@D
  }
  dp@A
}
Translated into BF, we have
    [->+<[>>>-<<<[->>+<<]]>>-[<<+>>-]>+[-<+<->>]<<<]
I'm not that good at BF, so my algorithm may not be the smallest.

Next, we define the program.
In this, we assume that the numbers are loaded in $2 (cell 2) and $3.

inc $1,8; dp@1 {
  dec  $1
  pour $3,$6
  DM2  $2        # result in $3,$4
  DM2  $6        # result in $7,$8
  pour $7, $2
  pour $8,$5
  bop  $4,$5     # result in $6
  pour $1,$5
  pour $5,$4,$1
  down $4,$5     # decrease $4 till 0, decrease $5 by same amount
  inc  $5,#7
  shl  $6,$5
  pour $6,$0     # $0 is result
  dp@  1
}
#Now, the result is in $0

Translated to BF (with linebreaks for readability):
  >++++++++[
    ->>[->>>+<<<]<
    [->+<[>>>-<<<[->>+<<]]>>-[<<+>>-]>+[-<+<->>]<<<]>>>>  #DM2 $2
    [->+<[>>>-<<<[->>+<<]]>>-[<<+>>-]>+[-<+<->>]<<<]>     #DM2 $6
    [-<<<<<+>>>>>]>
    [-<<<+>>>]<<<<
    (bop)<<<
    [->>>>+<<<<]>>>>
    [<+<<<+>>>>-]<
    [->-<]>
    +++++++
    [->[-<<++>>]<<[->>+<<]>]
    [-<<<<<<+>>>>>>]
    <<<<<
  ]

Replace (bop) by the appropriate expression.

XOR works like this: (252-5+15=262)
  [->-<]>[[-]>+<]
AND works like this: (252-5+11=258)
  [>[>+<-]<-]
OR  works like this: (252-5+32=279)
  [->>>+<<<]>[->>+<<]>>[[-]<+>]<<<

So, combining these, we have a total of 262+258+279=799 D:

Ruota a sinistra A, 1-31 / -

Il numero Aviene caricato nella cella 0.

Pseudocode
    $0 := A
    $1 := $0 << 1    # this has the effect of discarding the top bit of A
    $2 := $0
    $3 := $0 << 1
    $2 -= $1 >> 1    # $2 now contains the top bit of A
    if $2 then $3++  # $3 now contains A rotated left 1
    res:= $3         # the result is in cell 3 now

Real code
    [->++>+>++<<<]>[-->-<]>[>+<[-]]
If you don't always need the pointer in the same position,
substitute [>+>] for the last loop (3 less chars).
However, the pointer will then sometimes end up in position 2, sometimes in position 4.

NON A - 7

Il numero Aviene caricato nella cella 0.

Pseudocode
    $0  := A
    $0  += 1
    $1  := 256-$0   #since ~A=255-A
    res := $1

+[->-<]
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.