%% to compile: erlc day3A.erl %% to run: erl -noshell -s day3 solve %% -module(day4). -export ([solve/0, solve/1, solve/2]). -export ([read_boards/0]). solve() -> solve(['1']), solve(['2']), init:stop(). solve(A) -> solve(A, read_boards()). solve(['1'], D) -> io:format("The solution to ~p puzzle1 is: ~p~n", [?MODULE, solve(1, D)]); solve(1, D) -> solution1(D); solve(['2'], D) -> io:format("The solution to ~p puzzle2 is: ~p~n", [?MODULE, solve(2, D)]); solve(2, D) -> solution2(D). read_boards() -> {ok, IO} = file:open("boards.txt", 'read'), Data = read_boards(IO), file:close(IO), Data. read_boards(IO) -> read_boards(IO, []). read_boards('eof', Boards) -> Boards; read_boards(IO, Boards) -> case read_board(IO) of 'eof' -> Boards; Board -> read_boards(IO, Boards ++ [Board]) end. read_board(IO) -> read_line(IO, []). read_line(IO, Board) -> case file:read_line(IO) of {ok, "\n"} -> make_board(Board); 'eof' -> 'eof'; {ok, Line} -> read_line(IO, [[ list_to_integer(X) || X <- string:tokens(Line, " \n")]|Board]) end. make_board(B) -> B ++ [lists:map(fun(X) -> lists:nth(Y,X) end, B) || Y <- lists:seq(1,5)]. solution1(Boards) -> Input = get_input(), Bingo = process(Boards, 1, Input), score(Bingo). solution2(Boards) -> Input = get_input(), Bingo = process(Boards, length(Boards), Input), score(Bingo). score({'bingo', Num, Board}) -> Fun = fun(L) -> lists:foldl(fun(X, Acc) -> X + Acc end, 0, L) end, Num * (Fun([Fun(X) || X <- Board]) / 2). process(Boards, _Count, []) -> Boards; process(Boards, Count, [H|T]) -> New_boards = process_boards(Boards, H, []), case is_bingo(New_boards) of {'bingo', Board} when Count == 1 -> {'bingo', H, Board}; {'bingo', _Board} -> New_boards2 = delete_bingo_boards(New_boards), process(New_boards2, Count - length(New_boards) + length(New_boards2), T); _Else -> process(New_boards, Count, T) end. process_boards([], _Num, Acc) -> Acc; process_boards([B|T], Num, Acc) -> process_boards(T, Num, [[lists:delete(Num, X) || X <- B]|Acc]). is_bingo([]) -> 'false'; is_bingo([Board|Rest]) -> case is_line(Board) of 'true' -> {'bingo', Board}; 'false' -> is_bingo(Rest) end. is_line(Board) -> lists:any(fun(X) -> X == [] end, Board). delete_bingo_boards(Boards) -> [Board || Board <- Boards, not is_line(Board)]. get_input() -> [83,69,34,46,30,23,19,75,22,37,89,78,32,39,11,44,95,43,26,48,84,53,94,88,18,40,62,35,27,42,15,2,91,20,4,64,99,71,54,97,52,36,28,7,74,45,70,86,98,1,61,50,68,6,77,8,57,47,51,72,65,3,49,24,79,13,17,92,41,80,63,67,82,90,55,0,10,93,38,21,59,73,33,31,9,76,5,66,16,58,85,87,12,29,25,14,96,56,60,81].