From a31b1a41422684c07630402124b7dcf02ac4dd9d Mon Sep 17 00:00:00 2001 From: Andrew Coleman Date: Mon, 25 Dec 2017 16:18:49 -0500 Subject: [PATCH] day23 solution, helped by reddit --- day23/Makefile | 8 ++++ day23/day23.erl | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ day23/problem | 32 +++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 day23/Makefile create mode 100644 day23/day23.erl create mode 100644 day23/problem diff --git a/day23/Makefile b/day23/Makefile new file mode 100644 index 0000000..1ff1604 --- /dev/null +++ b/day23/Makefile @@ -0,0 +1,8 @@ +all: day23.beam + erl -noshell -s day23 start -s init stop + +day23.beam: + erlc day23.erl + +clean: + rm -f day23.beam diff --git a/day23/day23.erl b/day23/day23.erl new file mode 100644 index 0000000..599f6cf --- /dev/null +++ b/day23/day23.erl @@ -0,0 +1,105 @@ +-module(day23). +-export([start/0]). + +value_or_register(X, Registers) + when X >= <<"a">>, X =< <<"z">> -> maps:get(X, Registers, 0); +value_or_register(X, _Registers) + -> { NewValue, _ } = string:to_integer(X), + NewValue. + +format_input(Input) + -> lists:map(fun(X) -> [A|Args] = re:split(X, " "), { A, Args } end, re:split(Input, "\n")). + +assemble(Input) + -> Instructions = format_input(Input), + assemble(Instructions, length(Instructions), 1, 0, maps:new()). + +debug_assemble(Input) + -> Instructions = format_input(Input), + assemble(Instructions, length(Instructions), 1, 0, maps:put(<<"a">>, 1, maps:new())). + +assemble(_Instructions, MaxInstructions, Ip, LastFrequency, Registers) + when Ip < 1; Ip > MaxInstructions -> { LastFrequency, Registers }; +assemble(Instructions, MaxInstructions, Ip, LastFrequency, Registers) + -> { Op, Args } = lists:nth(Ip, Instructions), + %io:fwrite("ip ~p op ~p args ~p~n~p~n", [Ip, Op, Args, Registers]), + case Op of + <<"add">> -> + [Src,Dest|_] = Args, + ExistingValue = maps:get(Src, Registers, 0), + NewValue = value_or_register(Dest, Registers), + assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, maps:put(Src, ExistingValue + NewValue, Registers)); + <<"sub">> -> + [Src,Dest|_] = Args, + ExistingValue = maps:get(Src, Registers, 0), + NewValue = value_or_register(Dest, Registers), + assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, maps:put(Src, ExistingValue - NewValue, Registers)); + <<"jnz">> -> + [Src,Dest|_] = Args, + SrcValue = value_or_register(Src, Registers), + NewValue = value_or_register(Dest, Registers), + if SrcValue /= 0 -> assemble(Instructions, MaxInstructions, Ip + NewValue, LastFrequency, Registers); + true -> assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, Registers) + end; + <<"jgz">> -> + [Src,Dest|_] = Args, + SrcValue = value_or_register(Src, Registers), + NewValue = value_or_register(Dest, Registers), + if SrcValue > 0 -> assemble(Instructions, MaxInstructions, Ip + NewValue, LastFrequency, Registers); + true -> assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, Registers) + end; + <<"mod">> -> + [Src,Dest|_] = Args, + ExistingValue = maps:get(Src, Registers, 0), + NewValue = value_or_register(Dest, Registers), + assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, maps:put(Src, ExistingValue rem NewValue, Registers)); + <<"mul">> -> + [Src,Dest|_] = Args, + ExistingValue = maps:get(Src, Registers, 0), + NewValue = value_or_register(Dest, Registers), + Registers2 = maps:put("mul_count", maps:get("mul_count", Registers, 0) + 1, Registers), + assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, maps:put(Src, ExistingValue * NewValue, Registers2)); + <<"rcv">> -> + [Dest|_] = Args, + NewValue = value_or_register(Dest, Registers), + if NewValue /= 0 -> LastFrequency; + true -> assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, Registers) + end; + <<"set">> -> + [Src,Dest|_] = Args, + NewValue = value_or_register(Dest, Registers), + assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, maps:put(Src, NewValue, Registers)); + <<"snd">> -> + [Dest|_] = Args, + NewValue = value_or_register(Dest, Registers), + assemble(Instructions, MaxInstructions, Ip + 1, NewValue, Registers); + <<>> -> + io:fwrite("invalid instruction: ~p~n", [{ Op, Args }]), + assemble(Instructions, MaxInstructions, Ip + 1, LastFrequency, Registers) + end. + +is_prime(Check) + -> is_prime(Check, 2, math:sqrt(Check)). +is_prime(Check, Min, _Max) + when Check rem Min == 0 -> false; +is_prime(Check, Min, Max) + when Min > Max -> Check /= 1; +is_prime(Check, Min, Max) + -> is_prime(Check, Min + 1, Max). + +get_num_nonprimes(Start, End) + -> get_num_nonprimes(Start, End, 1, is_prime(Start)). +get_num_nonprimes(Start, End, Count, _IsPrime) + when Start == End -> Count; +get_num_nonprimes(Start, End, Count, IsPrime) + when IsPrime -> NewStart = Start + 17, + get_num_nonprimes(NewStart, End, Count, is_prime(NewStart)); +get_num_nonprimes(Start, End, Count, IsPrime) + when not IsPrime -> NewStart = Start + 17, + get_num_nonprimes(NewStart, End, Count + 1, is_prime(NewStart)). + +start() + -> { ok, File } = file:read_file("problem"), + io:fwrite("~p~n", [ assemble(File) ]), + %io:fwrite("~p~n", [ debug_assemble(File) ]). + io:fwrite("~p~n", [ get_num_nonprimes(109900, 126900) ]). diff --git a/day23/problem b/day23/problem new file mode 100644 index 0000000..9d29443 --- /dev/null +++ b/day23/problem @@ -0,0 +1,32 @@ +set b 99 +set c b +jnz a 2 +jnz 1 5 +mul b 100 +sub b -100000 +set c b +sub c -17000 +set f 1 +set d 2 +set e 2 +set g d +mul g e +sub g b +jnz g 2 +set f 0 +sub e -1 +set g e +sub g b +jnz g -8 +sub d -1 +set g d +sub g b +jnz g -13 +jnz f 2 +sub h -1 +set g b +sub g c +jnz g 2 +jnz 1 3 +sub b -17 +jnz 1 -23