local read, write = 1, 1 local active_buffer, back_buffer, rule_book = {}, {}, {} local function parse(str) local symbols = {} for symbol in str:gmatch("%S+") do table.insert(symbols, symbol) end return symbols end local function queue_up(string) for _, symbol in ipairs(parse(string)) do table.insert(active_buffer, symbol) end end local function add_rule(wants) return function(gives) table.insert(rule_book, {parse(wants), parse(gives)}) end end local function match(wants) for i = 1, #wants do if wants[i] ~= active_buffer[i + read - 1] then return false end end return true end local function consume(n) read = read + n end local function produce(gives) for _, symbol in ipairs(gives) do back_buffer[write] = symbol write = write + 1 end end local function advance() back_buffer[write], active_buffer[read] = active_buffer[read], nil write, read = write + 1, read + 1 end local function run_cycle() local rule_matched = false repeat local rule_fired = false for _, rule in ipairs(rule_book) do local wants, gives = rule[1], rule[2] if match(wants) then consume(#wants) produce(gives) rule_fired, rule_matched = true, true break end end if not rule_fired then advance() end until not active_buffer[read] return rule_matched end local function exchange_buffers() active_buffer, back_buffer = back_buffer, {} read, write = 1, 1 end local cycles, MAX_CYCLES = 0, 10000 local function run() while run_cycle() and cycles < MAX_CYCLES do print(table.concat(back_buffer, " ")) exchange_buffers() cycles = cycles + 1 end end add_rule "D D" "M" add_rule "C C C C C" "D" add_rule "L L" "C" add_rule "X X X X X" "L" add_rule "V V" "X" add_rule "I I I I I" "V" add_rule "I I I I" "I V" add_rule "V I V" "I X" add_rule "X X X X" "X L" add_rule "L X L" "X C" add_rule "C C C C" "C D" add_rule "D C D" "C M" queue_up(("I"):rep(1950, " ")) run()