This topic is about Day 8 of the Advent of Code 2022 .
Link to our leaderboard:
https://adventofcode.com/2022/leaderboard/private/view/370884
The entry code is:
370884-a6a71927
Good luck!
This topic is about Day 8 of the Advent of Code 2022 .
Link to our leaderboard:
https://adventofcode.com/2022/leaderboard/private/view/370884
The entry code is:
370884-a6a71927
Good luck!
Re-used some of the code from previous year to parse numerical grid into a map:
main(File) ->
{ok, RawData} = file:read_file(File),
Data = [ [ X - $0 || X <- binary_to_list(Line) ]
|| Line <- binary:split(RawData, <<"\n">>, [global, trim]) ],
Map = load(Data),
io:format("part 1: ~p~n", [solve1(Map)]),
io:format("part 2: ~p~n", [solve2(Map)]).
load(Data) ->
maps:from_list([ {{X, Y}, N} || {Y, Line} <- enum(Data),
{X, N} <- enum(Line) ]).
enum(List) ->
lists:zip(lists:seq(1, length(List)), List).
solve1(Data) ->
MaxC = {MaxX, MaxY} = lists:max(maps:keys(Data)),
Edges = 2 * MaxX + 2 * MaxY - 4,
length([ true || X <- lists:seq(2, MaxX - 1),
Y <- lists:seq(2, MaxY - 1),
is_visible({X, Y}, MaxC, Data) ])
+ Edges.
is_visible(Coord, MaxC, Map) ->
Height = maps:get(Coord, Map),
lists:any(fun (D) -> all_shorter(Height, Map, enum_direction(D, Coord, MaxC)) end,
[left, right, up, down]).
all_shorter(Height, Map, Coords) ->
lists:all(fun (C) -> maps:get(C, Map) < Height end, Coords).
enum_direction(left, {X0, Y0}, _ ) -> [ {X, Y0} || X <- lists:seq(X0 - 1, 1, -1) ];
enum_direction(right, {X0, Y0}, {MaxX, _}) -> [ {X, Y0} || X <- lists:seq(X0 + 1, MaxX) ];
enum_direction(up, {X0, Y0}, _ ) -> [ {X0, Y } || Y <- lists:seq(Y0 - 1, 1, -1) ];
enum_direction(down, {X0, Y0}, {_, MaxY}) -> [ {X0, Y } || Y <- lists:seq(Y0 + 1, MaxY) ].
solve2(Data) ->
MaxC = {MaxX, MaxY} = lists:max(maps:keys(Data)),
lists:max([ scenic_score({X, Y}, MaxC, Data) || X <- lists:seq(2, MaxX - 1),
Y <- lists:seq(2, MaxY - 1) ]).
scenic_score(Coord, MaxC, Map) ->
Height = maps:get(Coord, Map),
lists:foldl(fun (D, Acc) -> Acc * view_distance(Height, Map, enum_direction(D, Coord, MaxC)) end,
1,
[left, right, up, down]).
view_distance(Height, Map, [C|Rest]) ->
case maps:get(C, Map) >= Height of
true -> 1;
false -> 1 + view_distance(Height, Map, Rest)
end;
view_distance(_, _, []) ->
0.
I didn’t know what I was doing last night but I solved it using Clojure. Nastiest Clojure I wrote, having transposed and reverted and reverted transposed matrices and comparing with original… arghhh.
I attempted to do the same for Erlang, after having enough hammock time. I am proud of the code (Although I took ample inspiration from your code at Part 2 especially, thank you). Especially I liked the way I regained my [Head | Tail]
fluency (the list -> map
function).
Did this at 5AM, took ~40 minutes (like I said, reading your code helped).
-module(day_8).
-export([solve/0]).
input() ->
{ok, RawHeights} = file:read_file("data/8.txt"),
RawHeights.
parse(RawHeights) ->
TreeList =
[[X - $0 || X <- binary_to_list(Line)]
|| Line <- binary:split(RawHeights, <<"\n">>, [global, trim])],
Length = length(TreeList),
Breadth = length(hd(TreeList)),
Edges = 2 * Length + 2 * Breadth - 4,
TreeMap = tree_list_to_tree_map(TreeList),
{TreeMap, Edges, Length, Breadth}.
solve() ->
RawHeights = input(),
{TreeMap, Edges, Length, Breadth} = parse(RawHeights),
Solve1 = solve1(TreeMap, Edges, Length, Breadth),
Solve2 = solve2(TreeMap, Length, Breadth),
{Solve1, Solve2}.
solve1(TreeMap, Edges, Length, Breadth) ->
Interior =
length([true
|| X <- lists:seq(2, Length - 1),
Y <- lists:seq(2, Breadth - 1),
is_visible({X, Y}, {Length, Breadth}, TreeMap)]),
Edges + Interior.
solve2(TreeMap, Length, Breadth) ->
lists:max([scenic_score({X, Y}, {Length, Breadth}, TreeMap)
|| X <- lists:seq(2, Length - 1), Y <- lists:seq(2, Breadth - 1)]).
tree_list_to_tree_map(TreeList) ->
tree_list_to_tree_map(TreeList, 1, 1, []).
tree_list_to_tree_map([], _, _, TreeList) ->
maps:from_list(TreeList);
tree_list_to_tree_map([[] | Lengths], X, _, TreeList) ->
tree_list_to_tree_map(Lengths, X + 1, 1, TreeList);
tree_list_to_tree_map([[Height | Breadths] | Lengths], X, Y, TreeList) ->
tree_list_to_tree_map([Breadths | Lengths], X, Y + 1, [{{X, Y}, Height} | TreeList]).
seen_from(top, {XX, YY}, _) ->
[{X, YY} || X <- lists:seq(XX - 1, 1, -1)];
seen_from(bottom, {XX, YY}, {Length, _}) ->
[{X, YY} || X <- lists:seq(XX + 1, Length)];
seen_from(left, {XX, YY}, _) ->
[{XX, Y} || Y <- lists:seq(YY - 1, 1, -1)];
seen_from(right, {XX, YY}, {_, Breadth}) ->
[{XX, Y} || Y <- lists:seq(YY + 1, Breadth)].
is_visible(Coord, Dims, Map) ->
lists:any(fun(Dir) -> is_tallest(maps:get(Coord, Map), Map, seen_from(Dir, Coord, Dims))
end,
[top, bottom, left, right]).
is_tallest(Height, Map, Coords) ->
lists:all(fun(C) -> maps:get(C, Map) < Height end, Coords).
scenic_score(Coord, Dims, Map) ->
Height = maps:get(Coord, Map),
Reducer =
fun(Dir, Acc) -> Acc * view_distance(Height, Map, seen_from(Dir, Coord, Dims)) end,
lists:foldl(Reducer, 1, [top, bottom, left, right]).
view_distance(Height, TreeMap, [C | Rest]) ->
case maps:get(C, TreeMap) >= Height of
true ->
1;
false ->
1 + view_distance(Height, TreeMap, Rest)
end;
view_distance(_, _, []) ->
0.
Hah! That TreeMap
and TreeList
naming was intentional… a tribute to Java if you will.