最終更新 1741326285

修正履歴 c4717bc50fefb5b14ae3e8e4bcbd9e66db4b3230

string-rewriter.lua Raw Playground
1local read, write = 1, 1
2local active_buffer, back_buffer, rule_book = {}, {}, {}
3local function parse(str)
4 local symbols = {}
5 for symbol in str:gmatch("%S+") do
6 table.insert(symbols, symbol)
7 end
8 return symbols
9end
10
11local function queue_up(string)
12 for _, symbol in ipairs(parse(string)) do
13 table.insert(active_buffer, symbol)
14 end
15end
16local function add_rule(wants)
17 return function(gives)
18 table.insert(rule_book, {parse(wants), parse(gives)})
19 end
20end
21
22local function match(wants)
23 for i = 1, #wants do
24 if wants[i] ~= active_buffer[i + read - 1] then return false end
25 end
26 return true
27end
28
29local function consume(n)
30 read = read + n
31end
32
33local function produce(gives)
34 for _, symbol in ipairs(gives) do
35 back_buffer[write] = symbol
36 write = write + 1
37 end
38end
39
40local function advance()
41 back_buffer[write], active_buffer[read] = active_buffer[read], nil
42 write, read = write + 1, read + 1
43end
44
45local function run_cycle()
46 local rule_matched = false
47 repeat
48 local rule_fired = false
49 for _, rule in ipairs(rule_book) do
50 local wants, gives = rule[1], rule[2]
51 if match(wants) then
52 consume(#wants)
53 produce(gives)
54 rule_fired, rule_matched = true, true
55 break
56 end
57 end
58 if not rule_fired then advance() end
59 until not active_buffer[read]
60 return rule_matched
61end
62
63
64local function exchange_buffers()
65 active_buffer, back_buffer = back_buffer, {}
66 read, write = 1, 1
67end
68
69local cycles, MAX_CYCLES = 0, 10000
70local function run()
71 while run_cycle() and cycles < MAX_CYCLES do
72 print(table.concat(back_buffer, " "))
73 exchange_buffers()
74 cycles = cycles + 1
75 end
76end
77
78add_rule "D D" "M"
79add_rule "C C C C C" "D"
80add_rule "L L" "C"
81add_rule "X X X X X" "L"
82add_rule "V V" "X"
83add_rule "I I I I I" "V"
84
85add_rule "I I I I" "I V"
86add_rule "V I V" "I X"
87add_rule "X X X X" "X L"
88add_rule "L X L" "X C"
89add_rule "C C C C" "C D"
90add_rule "D C D" "C M"
91
92queue_up(("I"):rep(1950, " "))
93
94run()