88 lines
2.4 KiB
Prolog
88 lines
2.4 KiB
Prolog
:- use_module(library(dcg/basics)).
|
|
|
|
many(_, []) --> [].
|
|
many(P, [X|Xs]) --> call(P, X), many(P, Xs).
|
|
|
|
seed_list(Seeds) --> "seeds:", blanks, numbers(Seeds).
|
|
|
|
blank_sep(_, []) --> [].
|
|
blank_sep(P, [X|Xs]) --> call(P, X), blanks, blank_sep(P, Xs).
|
|
|
|
numbers(Ns) --> blank_sep(number, Ns).
|
|
|
|
name(X) --> many(alpha_to_lower, Cs), {atom_codes(X, Cs)}.
|
|
|
|
header(From, To) --> name(From), "-to-", name(To), blanks, "map:".
|
|
|
|
map_line(m(Src, Dest, Len)) --> numbers([Dest, Src, Len]).
|
|
|
|
part(p(From, To, Elems)) -->
|
|
header(From, To), blanks, blank_sep(map_line, Elems), blanks.
|
|
|
|
|
|
file1(Seeds, Parts) --> seed_list(Seeds), blanks, many(part, Parts).
|
|
|
|
parse1(Seeds, Parts, File) :- once(phrase_from_file(file1(Seeds, Parts), File)).
|
|
|
|
:- dynamic seed/1, entry/5, next_step/2.
|
|
setup1(Seeds, Parts) :-
|
|
transaction((retractall(seed(_)),
|
|
retractall(entry(_, _, _, _, _)),
|
|
retractall(next_step(_, _)),
|
|
setup_seeds1(Seeds), setup_map(Parts))).
|
|
|
|
setup_seeds1(Seeds) :- maplist(assert_seed1, Seeds).
|
|
assert_seed1(S) :- assertz(seed(S)).
|
|
|
|
setup_map(Parts) :- maplist(setup_part, Parts).
|
|
setup_part(p(From, To, Elems)) :-
|
|
assertz(next_step(From, To)),
|
|
maplist(assert_entry(From, To), Elems).
|
|
assert_entry(From, To, m(Src, Dest, Len)) :-
|
|
assert(entry(From, To, Src, Dest, Len)).
|
|
|
|
parse_setup1(File) :- parse1(Seeds, Parts, File), setup1(Seeds, Parts).
|
|
|
|
|
|
map1(From, To, Src, Dest) :-
|
|
entry(From, To, Src0, Dest0, Len),
|
|
Src1 is Src0 + Len,
|
|
Src >= Src0, Src < Src1, !,
|
|
Index is Src - Src0,
|
|
Dest is Dest0 + Index.
|
|
map1(From, To, Src, Src) :-
|
|
next_step(From, To).
|
|
|
|
map1N(From, From, Src, Src) :- !.
|
|
map1N(From, To, Src, Dest) :-
|
|
map1(From, Mid, Src, MidN),
|
|
map1N(Mid, To, MidN, Dest).
|
|
|
|
part1(File) :-
|
|
parse_setup1(File),
|
|
setof(L, S^(seed(S), map1N(seed, location, S, L)), [L|_]),
|
|
writeln(L).
|
|
|
|
|
|
seed_ranges(Seeds) --> "seeds:", blanks, blank_sep(seed_range, Seeds).
|
|
seed_range(s(Lo, Len)) --> numbers([Lo, Len]).
|
|
|
|
file2(Seeds, Parts) --> seed_ranges(Seeds), blanks, many(part, Parts).
|
|
|
|
parse2(Seeds, Parts, File) :- once(phrase_from_file(file2(Seeds, Parts), File)).
|
|
|
|
|
|
min_range(To, Lo, Hi) :-
|
|
setof(r(Dest, Len),
|
|
From^Src^entry(From, To, Src, Dest, Len),
|
|
[r(Lo0, Len)|_]),
|
|
Hi0 is Lo0 + Len,
|
|
Hi1 is Lo0 - 1,
|
|
(Lo = Lo0, Hi = Hi0 ; Lo = 0, Hi = Hi1).
|
|
|
|
range_size(s(_, Len), Len).
|
|
seed_count(Seeds, N) :-
|
|
maplist(range_size, Seeds, Sizes),
|
|
foldl(plus, Sizes, 0, N).
|
|
|
|
% vim: set ft=prolog :
|