Brainfuckの繰り返し処理に少し感動した
Brainfuckというプログラミング言語をPythonで動かしてみて、理解を深めようとしました。
コードはClaudeに書いてもらいました。
PythonでBrainfuckを動かす
import sys
# '>' はポインタをインクリメントする。
# '<' はポインタをデクリメントする。
# '+' ポインタの値をインクリメントする。
# '-' ポインタの値をデクリメントする.
# '.' ポインタの値をutf-8文字で出力する.
# ',' 1バイトの入力を受け付け, その値をポインタのmemに格納する.
# '[' ポインタのバイトが0なら、一致する']'にジャンプする。
# ']' ポインタのバイトが0でない場合、一致する'['にジャンプする。
mem_size = 300
mem = [0 for i in range(mem_size)]
ptr = 0
if __name__ == "__main__":
args = sys.argv
path = args[1]
with open(path) as f:
code = f.read()
code_list = list(code)
head = 0
while head < len(code_list):
if code_list[head] == '+':
mem[ptr] += 1
elif code_list[head] == '-':
mem[ptr] -= 1
elif code_list[head] == '[':
if mem[ptr] == 0:
count = 1
while count != 0:
head += 1
if head == len(code_list):
print("']' is missing")
sys.exit(1)
if code_list[head] == '[':
count += 1
elif code_list[head] == ']':
count -= 1
elif code_list[head] == ']':
if mem[ptr] != 0:
count = 1
while count != 0:
head -= 1
if head < 0:
print("'[' is missing")
if code_list[head] == ']':
count += 1
elif code_list[head] == '[':
count -= 1
elif code_list[head] == '.':
#chr: char -> code point
print(chr(mem[ptr]),end = "") #no line break
elif code_list[head] == ',':
#ord: code point -> char
mem[ptr] = ord(sys.stdin.buffer.read(1))
elif code_list[head] == '>':
ptr += 1
if ptr > mem_size:
print("overflow!")
sys.exit(1)
elif code_list[head] == "<":
if ptr == 0:
print("Can't decrement anymore")
ptr -= 1
else:
pass #ignore other symbol
head += 1
'[', ']'の意味がいまいち分からん
検証コード
'[', ']'の機能を知らべるために、'['・ ']'の箇所を抽出してコードを実行しました。
mem_size = 30000
mem = [0 for i in range(mem_size)]
ptr = 0
code_list = ">+++++++++[<++++++++>-]<."
count = 0
head = 0 #(tape reading) head
print("ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr])")
while head < len(code_list):
if code_list[head] == '+':
mem[ptr] += 1
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]))
elif code_list[head] == '-':
mem[ptr] -= 1
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]))
elif code_list[head] == '[':
if mem[ptr] == 0:
count = 1
while count != 0:
head += 1
if head == len(code_list):
print("']' is missing")
sys.exit(1)
if code_list[head] == '[':
count += 1
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]), "[ while")
elif code_list[head] == ']':
count -= 1
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]), "[ while")
else:
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]), "[ while else")
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]), "[ end")
elif code_list[head] == ']':
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]))
if mem[ptr] != 0:
count = 1
while count != 0:
head -= 1
if head < 0:
print("'[' is missing")
if code_list[head] == ']':
count += 1
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]), "[ while")
elif code_list[head] == '[':
count -= 1
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]), "[ while")
else:
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]), "[ while else")
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]), "[ end")
elif code_list[head] == '.':
#chr: char -> code point
print(chr(mem[ptr]),end = "") #no line break
elif code_list[head] == ',':
#ord: code point -> char
mem[ptr] = ord(sys.stdin.buffer.read(1))
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]))
elif code_list[head] == '>':
ptr += 1
if ptr > mem_size:
print("overflow!")
sys.exit(1)
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]))
elif code_list[head] == "<":
if ptr == 0:
print("Can't decrement anymore")
ptr -= 1
print(ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr]))
else:
pass #ignore other symbol
head += 1
出力結果
ptr, mem[ptr], code_list[head], head, count, chr(mem[ptr])
1 0 > 0 0
1 1 + 1 0
1 2 + 2 0
1 3 + 3 0
1 4 + 4 0
1 5 + 5 0
1 6 + 6 0
1 7 + 7 0
1 8 + 8 0
1 9 + 9 0
1 9 [ 10 0 [ end
0 0 < 11 0
0 1 + 12 0
0 2 + 13 0
0 3 + 14 0
0 4 + 15 0
0 5 + 16 0
0 6 + 17 0
0 7 + 18 0
0 8 + 19 0
1 9 > 20 0
1 8 - 21 0
1 8 ] 22 0
1 8 - 21 1 [ while else
1 8 > 20 1 [ while else
1 8 + 19 1 [ while else
1 8 + 18 1 [ while else
1 8 + 17 1 [ while else
1 8 + 16 1 [ while else
1 8 + 15 1 [ while else
1 8 + 14 1 [ while else
1 8 + 13 1 [ while else
1 8 + 12 1 [ while else
1 8 < 11 1 [ while else
1 8 [ 10 0 [ while
1 8 [ 10 0 [ end
0 8 < 11 0
0 9 + 12 0
0 10 + 13 0
0 11 + 14 0
0 12 + 15 0
0 13 + 16 0
0 14 + 17 0
0 15 + 18 0
0 16 + 19 0
1 8 > 20 0
1 7 - 21 0
1 7 ] 22 0
1 7 - 21 1 [ while else
1 7 > 20 1 [ while else
1 7 + 19 1 [ while else
1 7 + 18 1 [ while else
1 7 + 17 1 [ while else
1 7 + 16 1 [ while else
1 7 + 15 1 [ while else
1 7 + 14 1 [ while else
1 7 + 13 1 [ while else
1 7 + 12 1 [ while else
1 7 < 11 1 [ while else
1 7 [ 10 0 [ while
1 7 [ 10 0 [ end
0 16 < 11 0
0 17 + 12 0
0 18 + 13 0
0 19 + 14 0
0 20 + 15 0
0 21 + 16 0
0 22 + 17 0
0 23 + 18 0
0 24 + 19 0
1 7 > 20 0
1 6 - 21 0
1 6 ] 22 0
1 6 - 21 1 [ while else
1 6 > 20 1 [ while else
1 6 + 19 1 [ while else
1 6 + 18 1 [ while else
1 6 + 17 1 [ while else
1 6 + 16 1 [ while else
1 6 + 15 1 [ while else
1 6 + 14 1 [ while else
1 6 + 13 1 [ while else
1 6 + 12 1 [ while else
1 6 < 11 1 [ while else
1 6 [ 10 0 [ while
1 6 [ 10 0 [ end
0 24 < 11 0
0 25 + 12 0
0 26 + 13 0
0 27 + 14 0
0 28 + 15 0
0 29 + 16 0
0 30 + 17 0
0 31 + 18 0
0 32 + 19 0
1 6 > 20 0
1 5 - 21 0
1 5 ] 22 0
1 5 - 21 1 [ while else
1 5 > 20 1 [ while else
1 5 + 19 1 [ while else
1 5 + 18 1 [ while else
1 5 + 17 1 [ while else
1 5 + 16 1 [ while else
1 5 + 15 1 [ while else
1 5 + 14 1 [ while else
1 5 + 13 1 [ while else
1 5 + 12 1 [ while else
1 5 < 11 1 [ while else
1 5 [ 10 0 [ while
1 5 [ 10 0 [ end
0 32 < 11 0
0 33 + 12 0 !
0 34 + 13 0 "
0 35 + 14 0 #
0 36 + 15 0 $
0 37 + 16 0 %
0 38 + 17 0 &
0 39 + 18 0 '
0 40 + 19 0 (
1 5 > 20 0
1 4 - 21 0
1 4 ] 22 0
1 4 - 21 1 [ while else
1 4 > 20 1 [ while else
1 4 + 19 1 [ while else
1 4 + 18 1 [ while else
1 4 + 17 1 [ while else
1 4 + 16 1 [ while else
1 4 + 15 1 [ while else
1 4 + 14 1 [ while else
1 4 + 13 1 [ while else
1 4 + 12 1 [ while else
1 4 < 11 1 [ while else
1 4 [ 10 0 [ while
1 4 [ 10 0 [ end
0 40 < 11 0 (
0 41 + 12 0 )
0 42 + 13 0 *
0 43 + 14 0 +
0 44 + 15 0 ,
0 45 + 16 0 -
0 46 + 17 0 .
0 47 + 18 0 /
0 48 + 19 0 0
1 4 > 20 0
1 3 - 21 0
1 3 ] 22 0
1 3 - 21 1 [ while else
1 3 > 20 1 [ while else
1 3 + 19 1 [ while else
1 3 + 18 1 [ while else
1 3 + 17 1 [ while else
1 3 + 16 1 [ while else
1 3 + 15 1 [ while else
1 3 + 14 1 [ while else
1 3 + 13 1 [ while else
1 3 + 12 1 [ while else
1 3 < 11 1 [ while else
1 3 [ 10 0 [ while
1 3 [ 10 0 [ end
0 48 < 11 0 0
0 49 + 12 0 1
0 50 + 13 0 2
0 51 + 14 0 3
0 52 + 15 0 4
0 53 + 16 0 5
0 54 + 17 0 6
0 55 + 18 0 7
0 56 + 19 0 8
1 3 > 20 0
1 2 - 21 0
1 2 ] 22 0
1 2 - 21 1 [ while else
1 2 > 20 1 [ while else
1 2 + 19 1 [ while else
1 2 + 18 1 [ while else
1 2 + 17 1 [ while else
1 2 + 16 1 [ while else
1 2 + 15 1 [ while else
1 2 + 14 1 [ while else
1 2 + 13 1 [ while else
1 2 + 12 1 [ while else
1 2 < 11 1 [ while else
1 2 [ 10 0 [ while
1 2 [ 10 0 [ end
0 56 < 11 0 8
0 57 + 12 0 9
0 58 + 13 0 :
0 59 + 14 0 ;
0 60 + 15 0 <
0 61 + 16 0 =
0 62 + 17 0 >
0 63 + 18 0 ?
0 64 + 19 0 @
1 2 > 20 0
1 1 - 21 0
1 1 ] 22 0
1 1 - 21 1 [ while else
1 1 > 20 1 [ while else
1 1 + 19 1 [ while else
1 1 + 18 1 [ while else
1 1 + 17 1 [ while else
1 1 + 16 1 [ while else
1 1 + 15 1 [ while else
1 1 + 14 1 [ while else
1 1 + 13 1 [ while else
1 1 + 12 1 [ while else
1 1 < 11 1 [ while else
1 1 [ 10 0 [ while
1 1 [ 10 0 [ end
0 64 < 11 0 @
0 65 + 12 0 A
0 66 + 13 0 B
0 67 + 14 0 C
0 68 + 15 0 D
0 69 + 16 0 E
0 70 + 17 0 F
0 71 + 18 0 G
0 72 + 19 0 H
1 1 > 20 0
1 0 - 21 0
1 0 ] 22 0
1 0 ] 22 0 [ end
0 72 < 23 0 H
'[', ']'の意味
どうやら、繰り返し処理を実行してるらしい。
入力:+++++++++[<++++++++>-]<.
">"で2番目のメモリに移動し、"+++++++++"で9を入力(ここでは繰り返す回数を指定してる)
"["から繰り返し処理を開始する
"<"で1番目ののメモリに移動し、"++++++++"でメモリの値を足していく(ここでは8)
">"で2番目のメモリに移動し、"-"でメモリの値を減らす(9-1=8, 1回繰り返した)
"]"でコードの読み取り箇所を"["のところまで戻る
"["からもう一回繰り返し処理をする
"<"で1番目のメモリに移動し、"++++++++"でメモリの値を入力(ここでは82=16)
">"で2番目のメモリに移動し、"-"でメモリの値を減らす(8-1=7, 2回繰り返した)
これらを2番目のメモリの値が0になるまで繰り返す
"<"で1番目のメモリに移動すると、1番目のメモリの値が89=72になる
"."で出力
少し感動
次のメモリに繰り返し回数を指定するのは、よく考えたなぁ。
この記事が気に入ったらサポートをしてみませんか?