|
|
@ -3,12 +3,29 @@ |
|
|
-export([solve/1]). |
|
|
-export([solve/1]). |
|
|
|
|
|
|
|
|
solve(Input) -> |
|
|
solve(Input) -> |
|
|
{part1(Input), none}. |
|
|
|
|
|
|
|
|
{part1(Input), part2(Input)}. |
|
|
|
|
|
|
|
|
part1(Input) -> |
|
|
part1(Input) -> |
|
|
Sensors = parse_sensors(Input), |
|
|
Sensors = parse_sensors(Input), |
|
|
Ranges = get_row(Sensors, 2000000), |
|
|
Ranges = get_row(Sensors, 2000000), |
|
|
sum_ranges(Ranges). |
|
|
|
|
|
|
|
|
BeaconlessRanges = remove_beacons(Sensors, 2000000, Ranges), |
|
|
|
|
|
sum_ranges(BeaconlessRanges). |
|
|
|
|
|
|
|
|
|
|
|
part2(Input) -> |
|
|
|
|
|
Sensors = parse_sensors(Input), |
|
|
|
|
|
{Sensors, [Answer]} = for(0, 4000000, fun check_row_for_gaps/2, {Sensors, []}), |
|
|
|
|
|
Answer. |
|
|
|
|
|
|
|
|
|
|
|
check_row_for_gaps(Row, {Sensors, Acc}) -> |
|
|
|
|
|
case rset_remove_after(4000001, rset_remove_before(-1, get_row(Sensors, Row))) of |
|
|
|
|
|
[{_X, _Y}] -> {Sensors, Acc}; |
|
|
|
|
|
[{0, NMinusOne}, {NPlusOne, 4000000}] when NMinusOne + 2 == NPlusOne -> {Sensors, [tuning_frequency(NMinusOne+1, Row)|Acc]} |
|
|
|
|
|
end. |
|
|
|
|
|
|
|
|
|
|
|
tuning_frequency(X, Y) -> X * 4000000 + Y. |
|
|
|
|
|
|
|
|
|
|
|
for(End, End, Fun, Acc) -> Fun(End, Acc); |
|
|
|
|
|
for(Start, End, Fun, Acc) -> for(Start+1, End, Fun, Fun(Start, Acc)). |
|
|
|
|
|
|
|
|
parse_sensors(Input) -> |
|
|
parse_sensors(Input) -> |
|
|
lists:map(fun parse_sensor/1, binary:split(Input, <<$\n>>, [global, trim_all])). |
|
|
lists:map(fun parse_sensor/1, binary:split(Input, <<$\n>>, [global, trim_all])). |
|
|
@ -17,7 +34,7 @@ parse_sensor(Line) -> |
|
|
{{SensorX, SensorY}, {BeaconX, BeaconY}}. |
|
|
{{SensorX, SensorY}, {BeaconX, BeaconY}}. |
|
|
|
|
|
|
|
|
get_row(Sensors, Row) -> |
|
|
get_row(Sensors, Row) -> |
|
|
remove_beacons(Sensors, Row, get_row(Sensors, Row, rset_new())). |
|
|
|
|
|
|
|
|
get_row(Sensors, Row, rset_new()). |
|
|
|
|
|
|
|
|
remove_beacons([], _Row, Set) -> Set; |
|
|
remove_beacons([], _Row, Set) -> Set; |
|
|
remove_beacons([{_, {BeaconX, Row}}|Rest], Row, Set) -> remove_beacons(Rest, Row, rset_remove1(BeaconX, Set)); |
|
|
remove_beacons([{_, {BeaconX, Row}}|Rest], Row, Set) -> remove_beacons(Rest, Row, rset_remove1(BeaconX, Set)); |
|
|
@ -60,3 +77,13 @@ rset_remove1(Point, [{Point, Point} | Rest]) -> Rest; |
|
|
rset_remove1(Point, [{Point, End} | Rest]) -> [{Point+1, End} | Rest]; |
|
|
rset_remove1(Point, [{Point, End} | Rest]) -> [{Point+1, End} | Rest]; |
|
|
rset_remove1(Point, [{Start, Point} | Rest]) -> [{Start, Point-1} | Rest]; |
|
|
rset_remove1(Point, [{Start, Point} | Rest]) -> [{Start, Point-1} | Rest]; |
|
|
rset_remove1(Point, [{Start, End} | Rest]) -> [{Start, Point-1}, {Point+1, End} | Rest]. |
|
|
rset_remove1(Point, [{Start, End} | Rest]) -> [{Start, Point-1}, {Point+1, End} | Rest]. |
|
|
|
|
|
|
|
|
|
|
|
rset_remove_before(_Point, []) -> []; |
|
|
|
|
|
rset_remove_before(Point, [{_, End}|Rest]) when Point >= End -> rset_remove_before(Point, Rest); |
|
|
|
|
|
rset_remove_before(Point, [{Start, _}|_] = List) when Point < Start -> List; |
|
|
|
|
|
rset_remove_before(Point, [{_, End}|Rest]) -> [{Point+1, End}|Rest]. |
|
|
|
|
|
|
|
|
|
|
|
rset_remove_after(_Point, []) -> []; |
|
|
|
|
|
rset_remove_after(Point, [{Start, _}|_]) when Point =< Start -> []; |
|
|
|
|
|
rset_remove_after(Point, [{_, End}=Node | Rest]) when Point > End -> [Node|rset_remove_after(Point, Rest)]; |
|
|
|
|
|
rset_remove_after(Point, [{Start, _End}|_]) -> [{Start, Point-1}]. |