-
Notifications
You must be signed in to change notification settings - Fork 0
/
05.pl
46 lines (39 loc) · 1.54 KB
/
05.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
:- use_module(library(clpfd)), use_module(library(prolog_stack)).
get_numbers(L, Ns) :- re_foldl([re_match{0:S}, [S|T], T]>>true, "\\d+", L, Ns, [], [capture_type(term)]).
main :-
read_string(user_input, _, S), re_split("\n\n", S, [SeedsS | Blocks]),
get_numbers(SeedsS, Seeds),
convlist([Block, Map]>>(
split_string(Block, "\n", "\n", [_ | Lines]), Lines \= [],
maplist([L, [SourceStart, SourceEnd, Shift]]>>(
get_numbers(L, [DestStart, SourceStart, Length]),
SourceEnd is SourceStart + Length,
Shift is DestStart - SourceStart
), Lines, Map)
), Blocks, Maps),
!,
solve(Maps, Seeds, Part1),
format("Part 1: ~d\n", [Part1]),
range_pairs(Seeds, SeedRanges),
solve(Maps, SeedRanges, Part2),
format("Part 2: ~d\n", [Part2]).
constrain(Ranges, In, Out) :-
foldl({In, Out}/[[SourceStart, SourceEnd, Shift], AIn, AOut]>>(
End is SourceEnd-1,
(In in SourceStart..End) #<==> B,
AOut #= (AIn * (1 - B)),
B #==> (Out #= In + Shift)
), Ranges, 1, AllFail),
AllFail #==> (Out #= In).
solve(Maps, Domains, Out) :-
domain_union(Initial, Domains),
scanl(constrain, Maps, Initial, Vars),
Vars ins 0..10000000000,
last(Vars, Out),
once(labeling([min(Out), bisect], Vars)).
domain_union(V, [D|Ds]) :-
foldl([Dom, DIn, DOut]>>(DOut = DIn \/ Dom), Ds, D, DUnion),
V in DUnion.
range_pairs([], []).
range_pairs([Seed, Length | Tail], [Seed..End | Pairs]) :-
End is Seed + Length - 1, range_pairs(Tail, Pairs).