Битовые операторы в Brainfuck

13

Ваша задача состоит в том, чтобы создать одну программу brainfuck для каждого из следующих бинарных операторов. Каждая программа должна взять одно или два 8-битных числа (A и B) из ввода и вычислить указанную операцию:

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

Вам не нужно реализовывать все 5. Оценка рассчитывается по формуле:

#totalCharacters + {4000 * #problemsNotCompleted}

Таким образом, действительные оценки от нуля (лучший) до 20 000 (ничего не завершено).

Мне все равно, где вы храните результат или сохраняете ли вы ввод. Предположим, 8-битные ячейки и столько пустых ячеек, сколько нужно только справа.

Вы можете предположить, что числа уже находятся в любом месте памяти, которое лучше всего подходит для вас, поэтому вам не нужно беспокоиться об операциях ввода-вывода.

captncraig
источник
Можем ли мы также решить задачу на подобном минималистском языке, таком как iot?
FUZxxl
У меня нет никаких возражений против любых других языков, если нет встроенных побитовых операторов.
Captncraig

Ответы:

7

Оценка: 275

Лучше расширить их с помощью двоичного счетчика. Менее интуитивно понятные части имеют дело с возможностью того, что A или B равны 0. Я не нашел выгодного способа использовать неразрушающее управление потоком в реальных битовых манипуляциях первых трех. Между прочим, все это должно нормально работать с 16-разрядными ячейками и медленно с 32-разрядными.

XOR, 86

Предполагается, что A и B находятся в ячейках 1 и 2, хранит A XOR B в ячейке 2, указатель начинается в ячейке 0 и заканчивается в ячейке 5.

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

И, 78

Предполагается, что A и B находятся в ячейках 1 и 2, хранит A OR B в ячейке 4, указатель начинается в ячейке 0 и заканчивается в ячейке 5.

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

ИЛИ 86

Предполагается, что A и B находятся в ячейках 1 и 2, хранит A OR B в ячейке 2, указатель начинается в ячейке 0 и заканчивается в ячейке 5.

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

РОЛ, 18

Предполагается, что A находится в ячейке 0, хранит A ROL 1 в ячейке 1, указатель начинается и заканчивается в ячейке 0.

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

НЕ, 7

Предполагается, что A находится в ячейке 0, хранит NOT A в ячейке 1, указатель начинается и заканчивается в ячейке 0.

+[>-<-]
Даниэль Кристофани
источник
Это действительно коротко и довольно круто. +1
копия
Серьезные впечатляющие улучшения.
Captncraig
8

Оценка: 686

Все фрагменты предполагают, что числа уже загружены в ячейки 0 и 1 и что указатель указывает на ячейку 0. Я могу добавить фрагмент atoi позже, если это потребуется для вызова. На данный момент вы можете попробовать код следующим образом:

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


XOR, 221

Результат записывается в ячейку 10, указатель заканчивается в ячейке 5

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

И, 209

Результат записывается в ячейку 10, указатель заканчивается в ячейке 5

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

ИЛИ 211

Результат записывается в ячейку 10, указатель заканчивается в ячейке 5

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

Поверните налево, 38

Результат записывается в ячейку 1, указатель заканчивается в ячейке 4

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

НЕ, 7

Результат записывается в ячейку 1, указатель заканчивается в ячейке 0

+[+>+<]


Объяснение:

XOR, AND и OR работают одинаково: вычислите n / 2 для каждого числа и запомните n mod 2. Рассчитайте логическое XOR / AND / OR для отдельных битов. Если результирующий бит установлен, добавьте 2 ^ n к результату. Повторите это 8 раз.

Это макет памяти, который я использовал:

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

  8        9        10
temp  |  temp  |  result

Вот источник для XOR (числа указывают, где находится указатель в то время):

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

    <<<
]


Для левого поворота снова есть маркер в ячейке 2, чтобы определить, равен ли 2n нулю, поскольку вы можете только определить, является ли ячейка ненулевой напрямую. Если это так, бит переноса записывается в ячейку 4, а затем добавляется к 2n. Это макет памяти:

0      1        2       3       4   
n  |  2n  |  marker  |  0  |  carry 
копия
источник
Отличная работа! Я намеревался, чтобы каждая программа принимала данные с консоли, но чем больше я об этом думаю, тем лучше все работает. Не нужно заставлять вас добавлять ,>,<. Я отредактирую вопрос.
Captncraig
Мне было бы интересно услышать немного объяснения того, как они работают. Похоже, что ваши первые три очень похожи, за исключением самой внутренней части, но я не уверен, что вы делаете какое-то двоичное расширение (следовательно, требуется 8 ячеек), или поэлементное сравнение, или некоторую комбинацию двух. Трудно увидеть, шагая через.
Captncraig
@CMP Я добавлю объяснение позже
скопируйте
3

Счет (текущий): 12038 837 / -

Программы предполагают, что числа загружаются в любую ячейку, указанную ,или аналогичную. Также предполагается, что все ячейки 8-битные без знака с переносом по мере необходимости. В начале каждого фрагмента числа загружаются в ячейку 0 (и 1, если необходимо).

Битовые операции - 799

Битовые операции следуют той же общей структуре.

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:

Поверните влево A, 1 - 31 / -

Номер Aзагружается в ячейку 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.

НЕ А - 7

Номер Aзагружается в ячейку 0.

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

+[->-<]
о_О
источник