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}

따라서 유효한 점수는 0 (최고)에서 20,000 (아무것도 없음)입니다.

결과 저장 위치 또는 입력 유지 여부는 상관하지 않습니다. 8 비트 셀과 오른쪽에 필요한만큼의 빈 셀을 가정하십시오.

숫자가 이미 가장 적합한 메모리 위치에 있다고 가정 할 수 있으므로 IO 작업에 대해 걱정할 필요가 없습니다.


우리는 또한 iot와 같은 유사 최소한의 언어로 과제를 해결할 수 있습니까?
FUZxxl

비트 단위 연산자가 내장되어 있지 않으면 다른 언어에 반대하지 않습니다.
captncraig

답변:


7

점수 : 275

이진 카운터를 사용하여 확장하는 것이 좋습니다. 덜 직관적 인 부분은 A 또는 B가 0 일 가능성을 처리합니다. 처음 3 개의 실제 비트 조작에서 비파괴적인 흐름 제어를 사용하는 수익성있는 방법을 찾지 못했습니다. 또한 16 비트 셀에서는 32 비트에서는 느리게 작동합니다.

XOR, 86

A와 B가 셀 1과 2에 있고 A XOR B를 셀 2에 저장하고 포인터는 셀 0에서 시작하여 셀 5에서 종료한다고 가정합니다.

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

AND, 78

A와 B가 셀 1과 2에 있고 셀 4에 A OR B를 저장하고 포인터가 셀 0에서 시작하여 셀 5에서 끝났다고 가정합니다.

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

또는 86

A와 B가 셀 1과 2에 있고 A OR B를 셀 2에 저장하고 포인터는 셀 0에서 시작하여 셀 5에서 끝났다고 가정합니다.

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

ROL, 18

A가 셀 0에 있고 A ROL 1을 셀 1에 저장하고 포인터가 셀 0에서 시작 및 종료한다고 가정합니다.

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

아닙니다, 7

A가 셀 0에 있고 NOT A를 셀 1에 저장하고 포인터가 셀 0에서 시작 및 종료한다고 가정합니다.

+[>-<-]

정말 짧고 멋지다. +1
복사

매우 인상적인 개선.
captncraig 2013

8

점수 : 686

모든 스 니펫은 숫자가 셀 0과 1에 이미로드되어 있고 포인터가 셀 0을 가리키는 것으로 가정합니다. 나중에 도전에 필요한 경우 아토이 스 니펫을 추가 할 수 있습니다. 지금은 다음과 같은 코드를 사용해 볼 수 있습니다.

+++++++++>    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에 0이 아닌지 여부를 판별하는 마커가 다시 한 번 있습니다. 셀이 0이 아닌지 여부 만 판별 할 수 있기 때문입니다. 그렇다면, 캐리 비트가 셀 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

+[->-<]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.