Побітні оператори в Brainfuck


13

Ваше завдання полягає в створенні однієї програми для кожного з наступних бінарних операторів. Кожна програма повинна взяти одне або два 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-бітні комірки та стільки порожніх комірок, скільки вам потрібно лише праворуч.

Ви можете припустити, що цифри вже є в тому місці, де розташування пам'яті найкраще підходить для вас, тому вам не потрібно турбуватися про операції вводу-виводу.


Чи можемо ми також вирішити задачу подібною мінімалістичною мовою, такою як iot?
FUZxxl

Я не заперечую проти будь-яких інших мов, доки немає вбудованих побітових операторів.
captncraig

Відповіді:


7

Оцінка: 275

Працює краще розширити їх двійковим лічильником. Менш інтуїтивно зрозумілі частини стосуються можливості того, що А або В дорівнює 0. Я не знайшов вигідного способу використання неруйнівного управління потоком при фактичній маніпуляції бітом перших трьох. Між іншим, вони повинні добре працювати з 16-бітовими елементами і повільно з 32-бітовими.

XOR, 86

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

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

І, 78

Припустимо, що A і B знаходяться в клітинках 1 і 2, зберігають A АБО B у клітині 4, вказівник починається в комірці 0 і закінчується в комірці 5.

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

АБО, 86

Припускаємо, що A і B знаходяться в клітинах 1 і 2, зберігають A АБО B у комірці 2, вказівник починається в комірці 0 і закінчується в комірці 5.

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

РОЛ, 18

Припускаємо, що A знаходиться у комірці 0, зберігає A ROL 1 у комірці 1, покажчик починається та закінчується у комірці 0.

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

НЕ, 7

Припускаємо, що A знаходиться у комірці 0, зберігається НЕ у комірці 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 і АБО всі працюють аналогічно: Обчисліть 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

+[->-<]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.