const std = @import("std"); const mem = std.mem; const Symbol = enum(u2) { M, U, I }; pub fn main() !void { // Prints to stderr (it's a shortcut based on `std.io.getStdErr()`) std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); // stdout is for the actual output of your application, for example if you // are implementing gzip, then only the compressed bytes should be sent to // stdout, not any debugging messages. const stdout_file = std.io.getStdOut().writer(); var bw = std.io.bufferedWriter(stdout_file); const stdout = bw.writer(); var list = std.ArrayList([]Symbol).init(std.heap.page_allocator); defer list.deinit(); // try commenting this out and see if zig detects the memory leak! var initial: [2]Symbol = .{Symbol.M, Symbol.I}; try list.append(&initial); var count: u64 = 0; while(list.items.len > count){ count = list.items.len; for(list.items)|string|{ if(rule1Test(string)){ try list.append(rule1(string)); } if(rule2Test(string)){ try list.append(rule2(string)); } if(rule3Test(string)){ try list.append(rule3(string)); } if(rule4Test(string)){ try list.append(rule4(string)); } if(finish(string)){ break; //Finished! } } } try stdout.print("Run `zig build test` to run the tests.\n", .{}); try bw.flush(); // don't forget to flush! } pub fn rule1Test(input: []Symbol ) bool{ return (input[input.len] == Symbol.I); } pub fn rule1(input: []Symbol) []Symbol{ const lastEl:Symbol = input[input.len]; if(lastEl == Symbol.I){ return input ++ &Symbol.U; } } pub fn rule2Test(input: []Symbol) bool { return input[0] == Symbol.M; } pub fn rule2(input: []Symbol) []Symbol{ //M_ => M__ return input ++ input[1..]; } pub fn rule3Test(input: []Symbol) bool { for(input)|symbol, i|{ if(symbol == Symbol.I){ var streak = input[i..i+2]; if(mem.eql(u2, streak, [_]Symbol{Symbol.I ** 3}) ){ return true; } } } return false; } pub fn rule3(input: []Symbol) []Symbol{ // III => U //var i:u64 = 0; for(input)|symbol, i|{ if(symbol == Symbol.I){ var streak = input[i..i+2]; if(mem.eql(u2, streak, []Symbol{Symbol.I ** 3})){ return input[0..i] ++ Symbol.U ++ input[i+2..]; } } } } pub fn rule4Test(input: []Symbol) bool { for(input)|symbol, i|{ if(symbol == Symbol.U){ var streak = input[i..i+2]; return (mem.eql(u2, streak, []Symbol{Symbol.U ** 3})); } } return false; } pub fn rule4(input: []Symbol) []Symbol{ // UU => - for(input)|symbol, i|{ if(symbol == Symbol.U){ var streak = input[i..i+2]; if(mem.eql(u2, streak, []Symbol{Symbol.U ** 3})){ return input[0..i] ++ input[i+1..]; } } } } pub fn finish(input: []Symbol) bool{ return mem.eql(u2, input, []Symbol{Symbol.M, Symbol.U}); } test "simple test" { var list = std.ArrayList(i32).init(std.testing.allocator); defer list.deinit(); // try commenting this out and see if zig detects the memory leak! try list.append(42); try std.testing.expectEqual(@as(i32, 42), list.pop()); }