d5p1 and d5p2
This commit is contained in:
108
05/part2.pl
Normal file
108
05/part2.pl
Normal file
@@ -0,0 +1,108 @@
|
||||
answer(Answer) :-
|
||||
combine([seed_to_soil, soil_to_fertilizer, fertilizer_to_water,
|
||||
water_to_light, light_to_temperature, temperature_to_humidity,
|
||||
humidity_to_location], Map),
|
||||
seed_map(Seeds),
|
||||
fold_down(Seeds, Map, MappedSeeds),
|
||||
sort(MappedSeeds, [[Answer, _, _] | _]).
|
||||
|
||||
% combine all map predicates into one map
|
||||
combine([MapPredicate], Map) :-
|
||||
G =.. [MapPredicate, Map], G.
|
||||
combine([Map1Predicate, Map2Predicate| RestOfMaps], CombinedMap) :-
|
||||
G =.. [Map1Predicate, Map1], G,
|
||||
H =.. [Map2Predicate, Map2], H,
|
||||
process_map(Map1, ProcessedMap1),
|
||||
process_map(Map2, ProcessedMap2),
|
||||
fold_down(ProcessedMap1, ProcessedMap2, Map12),
|
||||
retractall(map12pred(_)), assertz(map12pred(Map12)),
|
||||
combine([map12pred | RestOfMaps], CombinedMap).
|
||||
|
||||
% combine 2 maps into one
|
||||
fold_down([], _, []).
|
||||
fold_down([Pair1 | RestOfMap1], Map2, FoldedMap) :-
|
||||
split_pair(Pair1, Map2, NewPair1s),
|
||||
fold_down(RestOfMap1, Map2, RestOfFoldedMap),
|
||||
append(NewPair1s, RestOfFoldedMap, FoldedMap).
|
||||
|
||||
% split_pair(InputPair, OutputMap, SplittedInputPairs)
|
||||
split_pair([Out1S, In1S, Len1], [], [[Out1S, In1S, Len1]]).
|
||||
|
||||
split_pair([Out1S, In1S, Len1],
|
||||
[[Out2S, In2S, Len2] | _],
|
||||
[[OutSNew, In1S, Len1]]) :-
|
||||
% range1 completely inside
|
||||
Out1S >= In2S, Out1S + Len1 =< In2S + Len2,
|
||||
OutSNew is Out2S + (Out1S - In2S).
|
||||
|
||||
split_pair([Out1S, In1S, Len1],
|
||||
[[_, In2S, Len2] | RestOf2],
|
||||
Split) :-
|
||||
% no overlap
|
||||
(Out1S >= In2S + Len2; Out1S + Len1 =< In2S),
|
||||
split_pair([Out1S, In1S, Len1], RestOf2, Split).
|
||||
|
||||
split_pair([Out1S, In1S, Len1],
|
||||
[[Out2S, In2S, Len2] | RestOf2],
|
||||
[[OutLeftS, In1S, LenLeft] | RestOfSplit]) :-
|
||||
% range1 overlaps to the right
|
||||
Out1S >= In2S, Out1S < In2S + Len2, Out1S + Len1 > In2S + Len2,
|
||||
LenLeft is In2S + Len2 - Out1S,
|
||||
OutLeftS is Out2S + (Out1S - In2S),
|
||||
OutRightS is In2S + Len2,
|
||||
InRightS is In1S + LenLeft,
|
||||
LenRight is Len1 - LenLeft,
|
||||
split_pair([OutRightS, InRightS, LenRight], RestOf2, RestOfSplit).
|
||||
|
||||
split_pair([Out1S, In1S, Len1],
|
||||
[[Out2S, In2S, Len2] | RestOf2],
|
||||
[[Out2S, InRightS, LenRight] | RestOfSplit]) :-
|
||||
% range1 overlaps to the left
|
||||
Out1S < In2S, Out1S + Len1 > In2S, Out1S + Len1 =< In2S + Len2,
|
||||
LenLeft is In2S - Out1S,
|
||||
InRightS is In1S + LenLeft,
|
||||
LenRight is Len1 - LenLeft,
|
||||
split_pair([Out1S, In1S, LenLeft], RestOf2, RestOfSplit).
|
||||
|
||||
split_pair([Out1S, In1S, Len1],
|
||||
[[Out2S, In2S, Len2] | RestOf2],
|
||||
[[Out2S, InMiddleS, Len2] | RestOfSplit]) :-
|
||||
% range1 completely covers range2
|
||||
Out1S < In2S, Out1S + Len1 > In2S + Len2,
|
||||
LenLeft is In2S - Out1S,
|
||||
InMiddleS is In1S + LenLeft,
|
||||
split_pair([Out1S, In1S, LenLeft], RestOf2, SplitLeft),
|
||||
OutRightS is In2S + Len2,
|
||||
InRightS is In1S + LenLeft + Len2,
|
||||
LenRight is Len1 - LenLeft - Len2,
|
||||
split_pair([OutRightS, InRightS, LenRight], RestOf2, SplitRight),
|
||||
append(SplitLeft, SplitRight, RestOfSplit).
|
||||
|
||||
% converts given ranges to sorted closed intervals starting at 0
|
||||
process_map(Map, ProcessedMap) :-
|
||||
sort(2, @=<, Map, SortedMap),
|
||||
pad_start(SortedMap, Sorted0PaddedMap),
|
||||
pad_end(Sorted0PaddedMap, ProcessedMap).
|
||||
|
||||
% add 0 range at the beginning if not exist. Range must be already sorted.
|
||||
pad_start([[OutS, 0, Len] | RRanges], [[OutS, 0, Len] | RRanges]).
|
||||
pad_start([[OutS, InS, Len] | RRanges],
|
||||
[[0, 0, InS], [OutS, InS, Len] | RRanges]) :-
|
||||
InS =\= 0.
|
||||
|
||||
% add MAXINT range at end. Range must be already sorted.
|
||||
pad_end(Ranges, PaddedRanges) :-
|
||||
reverse(Ranges, [[OutS, InS, Len] | RestOfRevRanges]),
|
||||
NewInS is InS + Len,
|
||||
NewLen is 4294967295 - NewInS,
|
||||
(NewLen =:= 0 ->
|
||||
reverse([[OutS, InS, Len] | RestOfRevRanges], PaddedRanges);
|
||||
reverse([[NewInS, NewInS, NewLen], [OutS, InS, Len] | RestOfRevRanges],
|
||||
PaddedRanges)
|
||||
).
|
||||
|
||||
% convert seed ranges into a straight map
|
||||
seed_map([], []).
|
||||
seed_map([Start, Len | RestOfSeeds], [[Start, Start, Len] | RestOfMap]) :-
|
||||
seed_map(RestOfSeeds, RestOfMap).
|
||||
seed_map(Map) :- seeds(Seeds), seed_map(Seeds, Map).
|
Reference in New Issue
Block a user