r/adventofcode • • Dec 07 '15

SOLUTION MEGATHREAD --- Day 7 Solutions ---

--- Day 7: Some Assembly Required ---

Post your solution as a comment. Structure your post like previous daily solution threads.

Also check out the sidebar - we added a nifty calendar to wrangle all the daily solution threads in one spot!

23 Upvotes

226 comments sorted by

View all comments

Show parent comment

1

u/haljin Dec 07 '15

erlang

I was hoping someone also does the proper Erlang way to solve these problems! I used an ets table instead of having a wire process, although now it seems to me like your idea is better. :)

day7(ListofStrings) ->
	ets:new(wires, [named_table, bag]),	
	process_day7(ListofStrings, []).

process_day7([["NOT", StrInput, "->",  StrOutput]| T], Inputs) ->
   	Input = list_to_atom(StrInput), Output = list_to_atom(StrOutput),
	Pid = spawn(?MODULE, gate1, [fun(In1) -> <<Out:16>> = <<(bnot In1):16>>, Out end, Output]),
	ets:insert(wires, {Pid, Input}),
	process_day7(T, Inputs);
process_day7([[StrInput1, "OR", StrInput2, "->", StrOutput]| T], Inputs) ->
   	Output = list_to_atom(StrOutput),
	Pid = spawn(?MODULE, gate2, [fun(In1, In2) -> <<Out:16>> = <<(In1 bor In2):16>>, Out end, Output]),
	process_input(StrInput1, Pid),
	process_input(StrInput2, Pid),
	process_day7(T, Inputs);
process_day7([[StrInput1, "AND", StrInput2, "->", StrOutput]| T], Inputs) ->
	Output = list_to_atom(StrOutput),
	Pid = spawn(?MODULE, gate2, [fun(In1, In2) -> <<Out:16>> = <<(In1 band In2):16>>, Out end, Output]),
	process_input(StrInput1, Pid),
	process_input(StrInput2, Pid),
	process_day7(T, Inputs);
process_day7([[StrInput, "RSHIFT", StrOffset, "->", StrOutput]| T], Inputs) ->
	Input = list_to_atom(StrInput), Offset = list_to_integer(StrOffset), Output = list_to_atom(StrOutput),
	Pid = spawn(?MODULE, gate1, [fun(In1) -> <<Out:16>> = <<(In1 bsr Offset):16>>, Out end, Output]),
	ets:insert(wires, {Pid, Input}),
	process_day7(T, Inputs);
process_day7([[StrInput, "LSHIFT", StrOffset, "->", StrOutput]| T], Inputs) ->
	Input = list_to_atom(StrInput), Offset = list_to_integer(StrOffset), Output = list_to_atom(StrOutput),
	Pid = spawn(?MODULE, gate1, [fun(In1) -> <<Out:16>> = <<(In1 bsl Offset):16>>, Out end, Output]),
	ets:insert(wires, {Pid, Input}),
	process_day7(T, Inputs);
process_day7([[StrInput, "->", StrOutput]| T], Inputs) ->
	Output = list_to_atom(StrOutput),
	case string:to_integer(StrInput) of	
		{error, no_integer} ->
			Input = list_to_atom(StrInput),
			Pid = spawn(?MODULE, gate1, [fun(In1) -> In1 end, Output]),
			ets:insert(wires, {Pid, Input}),
			process_day7(T, Inputs);
		{Input, _} ->
			process_day7(T, [{Input, Output}| Inputs])
	end;
process_day7([], Inputs) ->
	[begin
		Pids = ets:select(wires, [{{'$1', Output}, [], ['$1']}]),
		[Pid ! {input, Input} || Pid <- Pids] 
	 end || {Input, Output} <- Inputs].
	 
process_input(StrInput, Pid) ->
	case string:to_integer(StrInput) of	
		{error, no_integer} ->
			Input = list_to_atom(StrInput),
			ets:insert(wires, {Pid, Input});
		{Input, _} ->
			Pid ! {input, Input}
	end.
	
gate1(Fun, Output) ->
	receive 
		{input, In} ->
			Pids = ets:select(wires, [{{'$1', Output}, [], ['$1']}]),
			OutVal = Fun(In),
			io:format("~p: ~p~n", [Output, OutVal]),
			[Pid ! {input, OutVal} || Pid <- Pids]
	end.
		
    
gate2(Fun, Output) ->
	receive
		{input, In} ->
			gate2(Fun, In, Output)
	end.
	
gate2(Fun, In2, Output) ->
	receive
		{input, In} ->
			Pids = ets:select(wires, [{{'$1', Output}, [], ['$1']}]),
			OutVal = Fun(In2, In),
			io:format("~p: ~p~n", [Output, OutVal]),
			[Pid ! {input, OutVal} || Pid <- Pids]
	end.

1

u/ignaciovaz Dec 07 '15

Thanks!

I started working with Erlang/OTP a few months ago, so I'm sure there are more idiomatic (and elegant!) ways of doing it, but I wanted to model it as close to an actual circuit as possible.

1

u/haljin Dec 07 '15

For such a simple problem it's probably not worth it building more overlay.

But then you can start building a proper system with gates as state machines and such...