Snippets

Matej Nanut Advent of Code 2023 - Day 19

Created by Matej Nanut
:- use_module(library(assoc)).
:- use_module(library(between)).
:- use_module(library(charsio)).
:- use_module(library(clpz)).
:- use_module(library(dcgs)).
:- use_module(library(debug)).
:- use_module(library(dif)).
:- use_module(library(iso_ext)).
:- use_module(library(lists)).
:- use_module(library(pairs)).
:- use_module(library(pio)).
:- use_module(library(reif)).
:- use_module(library(time)).
:- use_module('../helpers').

part_one(File, Solution) :-
    once(phrase_from_file(input(Ws, Parts), File)),
    list_to_assoc(Ws, Workflows),
    parts_accepted(Workflows, Parts, Accepted),
    maplist(part_score, Accepted, Scores),
    sum_list(Scores, Solution).

% 377025 correct answer.

part_two(File, Solution) :-
    once(phrase_from_file(input(Ws, _), File)),
    list_to_assoc(Ws, Workflows),
    findall(S, gen_solution(Workflows, S), Ss),
    sum_list(Ss, Solution).

% 135506683246673 correct answer.

gen_solution(Workflows, Combinations) :-
    [X,M,A,S] ins 1..4000,
    part_accepted(Workflows, part(X,M,A,S), true),
    maplist(fd_size, [X,M,A,S], Sizes),
    foldl(foldl_mul, Sizes, 1, Combinations).

foldl_mul(X, M0, M) :- M is X * M0. 

parts_accepted(Workflows, Parts, Accepted) :-
    tfilter(part_accepted(Workflows), Parts, Accepted).

part_accepted(Workflows, Part, T) :-
    get_assoc("in", Workflows, Rs),
    part_workflow_result(Workflows, Part, Rs, T).

part_workflow_result(_, _, [accept|_], true).
part_workflow_result(_, _, [reject|_], false).
part_workflow_result(Workflows, Part, [send(W)|_], T) :-
    get_assoc(W, Workflows, Rs1),
    part_workflow_result(Workflows, Part, Rs1, T).
part_workflow_result(Workflows, Part, [condition(C, R, N, A)|Rs], T) :-
    part_rating(R, Part, X),
    if_(condition_t(C, X, N),
        part_workflow_result(Workflows, Part, [A], T),
        part_workflow_result(Workflows, Part, Rs, T)).

condition_t(<, X, N, T) :- #X #< #N #<==> #B, bit_t(B, T).
condition_t(>, X, N, T) :- #X #> #N #<==> #B, bit_t(B, T).

bit_t(0, false).
bit_t(1, true).

part_rating(x, part(X,_,_,_), X).
part_rating(m, part(_,M,_,_), M).
part_rating(a, part(_,_,A,_), A).
part_rating(s, part(_,_,_,S), S).

part_score(part(X,M,A,S), R) :-
    R is X + M + A + S.

input(Ws, Ps) --> workflows(Ws), newline, newline, parts(Ps), whites.

workflows([W|Ws]) --> workflow(W), workflows_r(Ws).
workflows_r(Ws)   --> newline, workflows(Ws).
workflows_r([])   --> [].

workflow(As-Rs) --> letters(As), "{", rules(Rs), "}".

rules([R|Rs]) --> rule(R), rules_r(Rs).
rules_r(Rs)   --> ",", rules(Rs).
rules_r([])   --> [].

rule(A)                     --> action(A).
rule(condition(<, R, N, A)) --> category(R), "<", integer(N), ":", action(A).
rule(condition(>, R, N, A)) --> category(R), ">", integer(N), ":", action(A).

action(send(As)) --> chars(As, lower).
action(accept)   --> "A".
action(reject)   --> "R".

parts([P|Ps]) --> part(P), parts_r(Ps).
parts_r(Ps)   --> newline, parts(Ps).
parts_r([])   --> [].

part(part(X,M,A,S)) --> "{x=", integer(X), ",m=", integer(M), ",a=", integer(A), ",s=", integer(S), "}".

category(x) --> "x".
category(m) --> "m".
category(a) --> "a".
category(s) --> "s".

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.