# Advent of code 2023

**URL:** <https://swi-prolog.discourse.group/t/advent-of-code-2023/7025>\
**Category:** General\
**Created:** [December 2, 2023, 9:21pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025 "2023-12-02T21:21:24Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![meditans](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/meditans/32/1768_2.png) [@meditans](https://swi-prolog.discourse.group/u/meditans)\
**Post date:** [December 4, 2023, 1:08pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/22 "2023-12-04T13:08:18Z")

</div>

Here’s my solution for today [aoc2023/04/main.pl at 859f5e91a41db8cc3c2e42eaac9603ee26ea58a1 · meditans/aoc2023 · GitHub](https://github.com/meditans/aoc2023/blob/859f5e91a41db8cc3c2e42eaac9603ee26ea58a1/04/main.pl).  
I had written the second part in a more verbose way, but your solution @emiruz inspired me to simplify it!

> [@emiruz](#):
>
> If possible in vanilla Prolog (i.e. just standard libraries)?

Where’s the fun in that 😄? Jokes aside, I’m using my own collection of dcg parsing utils [(pack `dcg_tools`)](https://github.com/meditans/dcg_tools/blob/0588fc22e812f9a17941b144bde1d2f559613080/prolog/dcg_tools.pl), and my personal utilities [(pack `medikit`)](https://github.com/meditans/medikit/blob/6df2654471fd252d2a2496afe0c40fe5f697ec2a/prolog/medikit.pl). You can install them, or just read the source and copy what you need, and feel free to ask questions.

For parsing in particular, you could start using `library(dcg/basics)` and `library(dcg/high_order)` as @jan suggested!

---

<div class="post-metadata">

**Author:** ![emiruz](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emiruz/32/4495_2.png) [@emiruz](https://swi-prolog.discourse.group/u/emiruz)\
**Post date:** [December 4, 2023, 2:52pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/23 "2023-12-04T14:52:49Z")

</div>

Very nice… just 21 LOC! I have to start learning CHR, AoC seems like a good time to practice it. Is there any material you’d specifically recommend? I found a [YouTube video](https://www.youtube.com/watch?v=ObNqhtxnHGg) and [this PPT tutorial](https://dtai.cs.kuleuven.be/CHR/files/tutorial_iclp2008.pdf) – and that’s about it …

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 4, 2023, 3:24pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/24 "2023-12-04T15:24:55Z")

</div>

> [@meditans](#):
>
> Here’s my solution for today

Neat. Just, there is no need to use ``String`` in SWI-Prolog’s DCGs. Just using `"String"` does the job. The DCG compiler finds the terminal and acts on its type dynamically. Using double quotes keeps the code portable.

---

<div class="post-metadata">

**Author:** ![meditans](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/meditans/32/1768_2.png) [@meditans](https://swi-prolog.discourse.group/u/meditans)\
**Post date:** [December 4, 2023, 3:31pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/25 "2023-12-04T15:31:10Z")

</div>

> [@emiruz](#):
>
> Is there any material you’d specifically recommend?

There is also a tutorial hosted at [GitHub - Anniepoo/swiplchrtut: Tutorial for the CHR system](https://github.com/Anniepoo/swiplchrtut), and a couple of books written by the creator of the CHR language, although with a more academic bent. I would suggest just trying to use it for AoC and developing a taste for when it’s useful as a tool. Ask in this forum, I myself have quite a lot of questions on the precise procedural semantics of CHR that I will have to get out in the next days.

---

<div class="post-metadata">

**Author:** ![meditans](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/meditans/32/1768_2.png) [@meditans](https://swi-prolog.discourse.group/u/meditans)\
**Post date:** [December 4, 2023, 3:31pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/26 "2023-12-04T15:31:47Z")

</div>

> [@jan](#):
>
> there is no need to use `String` in SWI-Prolog’s DCGs. Just using `"String"` does the job. The DCG compiler finds the terminal and acts on its type dynamically. Using double quotes keeps the code portable.

Great tip, thank you!

---

<div class="post-metadata">

**Author:** ![jgriego](https://avatars.discourse-cdn.com/v4/letter/j/f17d59/32.png) [@jgriego](https://swi-prolog.discourse.group/u/jgriego)\
**Post date:** [December 4, 2023, 8:30pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/27 "2023-12-04T20:30:29Z")

</div>

I also used `lazy_list_location//1` for day 3 and ran into problems with it; it seems to misbehave under some circumstances; wasn’t able to figure out exactly what is wrong with it, yet, though.

I had been parsing the input with:

```prolog
schematic(Loci) --> `.`, !, schematic(Loci).
schematic(Loci) --> `\n`, !, schematic(Loci).
schematic([symbol(Line, Col, C) | More]) -->
    lazy_list_location(file(_, Line, Col, _)),
    [C], { \+ code_type(C, digit), C \== 0'. }, !,
    schematic(More).
schematic([number(Line, Col, Width, N) | More]) -->
    lazy_list_location(file(_, Line, Col, _)),
    integer(N), !,
    lazy_list_location(file(_, _, EndCol, _)),
    { Width is EndCol - Col },
    schematic(More).
schematic([]) --> [].

```

which seemed to produce more `symbol/3` terms in the list than expected (just two “ghost” extras that weren’t in the input, out of 741!); I switched to

```prolog
schematic(Loci) --> `.`, !, schematic(Loci).
schematic(Loci) --> `\n`, !, schematic(Loci).
schematic([symbol(Line, Col, C) | More]) -->
    [C], { \+ code_type(C, digit), C \== 0'. }, !,
    lazy_list_location(file(_, Line, Col0, _)), !, % <-- delayed call to lazy_list_location//1 to after the cut
    { Col is Col0 - 1 },
    schematic(More).
schematic([number(Line, Col, Width, N) | More]) -->
    lazy_list_location(file(_, Line, Col, _)),
    integer(N), !,
    lazy_list_location(file(_, _, EndCol, _)),
    { Width is EndCol - Col },
    schematic(More).
schematic([]) --> [].

```

and that fixed everything (!)

EDIT wow posting via email does not work very well; fixed indentation

(also, full solution is [here](https://github.com/jjgriego/aoc/blob/bea83cd4890cf297e7ce8b2ca04f6fdb726ecede/2023/src/03.pl))

---

<div class="post-metadata">

**Author:** ![CapelliC](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/capellic/32/17_2.png) [@CapelliC](https://swi-prolog.discourse.group/u/CapelliC)\
**Post date:** [December 4, 2023, 8:48pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/28 "2023-12-04T20:48:04Z")

</div>

Nice ! You nailed it !

---

<div class="post-metadata">

**Author:** ![emiruz](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emiruz/32/4495_2.png) [@emiruz](https://swi-prolog.discourse.group/u/emiruz)\
**Post date:** [December 4, 2023, 10:41pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/29 "2023-12-04T22:41:33Z")

</div>

Its posted on another thread too, but here is a re-write (27 LOC) of day 3 solution, both parts. It uses DCG+CHR for a particularly concise implementation.

```prolog
:- use_module(library(chr)).
:- use_module(library(dcg/basics)).

:- set_prolog_flag(chr_toplevel_show_store, false).

ns(N,V) :- number_string(N,V).

% Parse input, designate X,Y coordinates to each character.
t(Xs) --> t(1,1,Xs).
t(_,_,[]) --> [].
t(X0,_,Xs) --> "\n",{X is X0+1},!,t(X,1,Xs).
t(X0,Y0,[p(X0,Y0,Y0,[V])|Xs]) --> [V0],{char_code(V,V0)},{Y is Y0+1},!,t(X0,Y,Xs).

% Predicates for the constraint store.
:- chr_constraint p/4.
:- chr_constraint q/4.
:- chr_constraint k/3.
:- chr_constraint stage/1.

% Remove dot coordinates.
p(_,_,_,['.']) <=> true.

% Merge digits.
p(X,Y0,Y,V),p(X,Y01,Y1,V1) <=>
    Y01-Y=:=1,
    ns(_,V),ns(_,V1) | append(V,V1,V_),p(X,Y0,Y1,V_).

% Check if X1,Y1 (a symbol coordinate) is adjacent to a digit span.
adj(X1,Y1,X,Y0,Y) :- X1>=X-1,X+1>=X1,Y1>=Y0-1,Y+1>=Y1.

% iff stage(2), filter for digit spans adjacent to symbols.
stage(2),p(X1,Y1,Y1,_) \ p(X,Y0,Y,V) <=>
         ns(_,V),adj(X1,Y1,X,Y0,Y) | ns(N,V),q(X,Y0,Y,N).

% iff stage(3), group digit spans around star symbols.
stage(3),p(X1,Y1,Y1,['*']) \ q(X,Y0,Y,V) <=>
	 adj(X1,Y1,X,Y0,Y) | k(X1,Y1,[V]).
% iff stage(3), aggregate star groups.
stage(3) \ k(X,Y,V),k(X,Y,V1) <=> V\=V1 | append(V,V1,Vs),k(X,Y,Vs).

solve(File,Part1,Part2) :-
    phrase_from_file(t(Xs),File), % read file and parse with t DCG.
    maplist(call,Xs), % call all predicates to put into CHR store.
    %invoke stage(2) and sum qs.
    stage(2),aggregate_all(sum(N),find_chr_constraint(q(_,_,_,N)),Part1),
    % invoke stage(3) and sum ks with just 2 values.
    stage(3),aggregate_all(sum(N),(find_chr_constraint(k(_,_,[A,B])),N is A*B),Part2). 

```

It is an order of magnitude slower than @CapelliC solution unfortunately, but its a pretty naive implementation so its likely possible to write it in a more performant way whilst maintaining the DCG+CHR approach.

---

<div class="post-metadata">

**Author:** ![CapelliC](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/capellic/32/17_2.png) [@CapelliC](https://swi-prolog.discourse.group/u/CapelliC)\
**Post date:** [December 5, 2023, 8:05am UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/30 "2023-12-05T08:05:45Z")

</div>

Great work indeed.  
But my good vibrations for constraints (and CHR in particular) has declined during the time, since I cannot see the benefits but just the additional problems in merging its semantic with the already overly complex (and sometime bizarre) semantic of Prolog (+attvars).  
But I must thanks @ridgeworks for his work on clpBNR, that IMHO targets real problems in effective ways, and then keeps my attention alive…

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 5, 2023, 9:27am UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/31 "2023-12-05T09:27:01Z")

</div>

> [@jgriego](#):
>
> I also used `lazy_list_location//1` for day 3 and ran into problems with it; it seems to misbehave under some circumstances; wasn’t able to figure out exactly what is wrong with it, yet, though.

As the docs say, it has a number of different representations. It is also slow. It is meant to support syntax\_error//1, which can deal with the various representations and speed is typically not vital for reporting an error. Do not use it to keep track of positions for anything else.

---

<div class="post-metadata">

**Author:** ![emiruz](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emiruz/32/4495_2.png) [@emiruz](https://swi-prolog.discourse.group/u/emiruz)\
**Post date:** [December 5, 2023, 6:25pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/32 "2023-12-05T18:25:43Z")

</div>

Hey guys, [day 5](https://adventofcode.com/2023/day/5)! Part 2 is a bit gnarly – I wen’t down the wrong rabbit hole on it, but I think I see a simple solution now. Here is a DCG+CHR solution to part 1 in 25 LOC. I’m still working on Part 2.

```prolog
:- use_module(library(dcg/basics)).
:- use_module(library(chr)).

:- set_prolog_flag(chr_toplevel_show_store, false).

% Parse seed list.
seeds([]) --> [].
seeds([s(X)|Xs]) --> blanks,number(X),seeds(Xs).
% Parse rows.
rngs(_,_,[]) --> [].
rngs(Fr,To,[c(A-B-C,Fr,To)|Xs]) --> number(A),blanks,number(B),blanks,number(C),
				    "\n",rngs(Fr,To,Xs).
rngs(Fr,To,[c(A-B-C,Fr,To)]) --> number(A),blanks,number(B),blanks,number(C).
% Parse individual category.
cat([]) --> [].
cat(Rs) --> string(Fr),"-to-",string(To)," map:\n",rngs(Fr,To,Rs).
% Parse categories.
cats([Rs|Xs]) --> cat(Rs),"\n\n",!,cats(Xs).
cats([Rs]) --> cat(Rs).
% Parse file.
file(Seeds,Cats) --> "seeds:",seeds(Seeds),"\n\n",cats(Cats).

:- chr_constraint c/3.
:- chr_constraint s/1.
:- chr_constraint q/2.

c(D-S-L,`seed`,To) \ s(X) <=> X>=S,S+L-1>=X | N is X+D-S,q(N,To).

s(X) <=> find_chr_constraint(c(_,`seed`,To)), q(X,To).

c(D-S-L,From,To) \ q(X,From) <=> X>=S,S+L-1>=X | N is X+D-S, q(N,To).

q(X,From) <=> From \= `location` | find_chr_constraint(c(_,From,To)), q(X,To).

solve(File,Part1) :-
    phrase_from_file(file(Ss,Cs0),File),
    flatten(Cs0,Cs),maplist(call,Cs),maplist(call,Ss),
    findall(X,find_chr_constraint(q(X,_)),Xs),!,
    min_member(Part1,Xs).

```

@CapelliC I really dislike having to do things like **[0’s,0’e,0’e,0’d]** in the code. Is there some way around that so that I can use strings without explicit conversion predicates?

EDIT: implementing @CapelliC advice RE literals.

---

<div class="post-metadata">

**Author:** ![CapelliC](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/capellic/32/17_2.png) [@CapelliC](https://swi-prolog.discourse.group/u/CapelliC)\
**Post date:** [December 5, 2023, 6:45pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/33 "2023-12-05T18:45:41Z")

</div>

> [@emiruz](#):
>
> `c(D-S-L,[0's,0'e,0'e,0'd],To) \ s(X) <=> X>=S,S+L-1>=X | N is X+D-S,q(N,To).`

backticks strings should do:

```prolog
c(D-S-L,`seed`,To) \ s(X) <=> X>=S,S+L-1>=X | N is X+D-S,q(N,To).

```

---

<div class="post-metadata">

**Author:** ![emiruz](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emiruz/32/4495_2.png) [@emiruz](https://swi-prolog.discourse.group/u/emiruz)\
**Post date:** [December 5, 2023, 6:56pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/34 "2023-12-05T18:56:35Z")

</div>

I was hoping it was something simple like that, thank you!

---

<div class="post-metadata">

**Author:** ![meditans](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/meditans/32/1768_2.png) [@meditans](https://swi-prolog.discourse.group/u/meditans)\
**Post date:** [December 5, 2023, 9:46pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/35 "2023-12-05T21:46:12Z")

</div>

> [@emiruz](#):
>
> Hey guys, [day 5](https://adventofcode.com/2023/day/5)!

Awesome job, like the other CHR solution you posted yesterday! Only point, giving some better names to one-single letter constraints, or a short comment explaining what they are meant to be, would improve readability. I’m unsure where the different stages (seed → soil etc) are processed here.

Here’s my solution for both parts (comments are always welcome)

> <https://github.com/meditans/aoc2023/blob/f9edcebe73eb378b79539965ecee43aa7d7bebc7/05/main.pl>

---

<div class="post-metadata">

**Author:** ![emiruz](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emiruz/32/4495_2.png) [@emiruz](https://swi-prolog.discourse.group/u/emiruz)\
**Post date:** [December 5, 2023, 10:23pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/36 "2023-12-05T22:23:10Z")

</div>

Just finished part 2 (below). I just wrote some code to try whether a location has a corresponding seed, and then tried all the locations in order. Since seeds are in very large blocks (as are the categories), I bound the solution first by stepping in units of 10000 and then finesse the final block of 10000 once I’ve found a solution. Its only really the last 20 lines or so that are specific to part2 – the rest is the same as part 1. Both parts together are [here on Github](https://github.com/emiruz/adventofcode2023/blob/b5daac78e15e4a6964806557a6df842a84963682/day05/solution.prolog). 44 LOC – not over the moon; feels like I’m missing some kind of key insight here which would have made for a more elegant solution.

```prolog
:- use_module(library(dcg/basics)).
:- use_module(library(clpfd)).

% Parse seed list.
seeds([]) --> [].
seeds([X|Xs]) --> blanks,number(X),seeds(Xs).
% Parse rows.
rngs(_,_,[]) --> [].
rngs(Fr,To,[c(A-B-C,Fr,To)|Xs]) --> number(A),blanks,number(B),blanks,number(C),
				    "\n",rngs(Fr,To,Xs).
rngs(Fr,To,[c(A-B-C,Fr,To)]) --> number(A),blanks,number(B),blanks,number(C).
% Parse individual category.
cat([]) --> [].
cat(Rs) --> string(Fr),"-to-",string(To)," map:\n",rngs(Fr,To,Rs).
% Parse categories.
cats([Rs|Xs]) --> cat(Rs),"\n\n",!,cats(Xs).
cats([Rs]) --> cat(Rs).
% Parse file.
file(Seeds,Cats) --> "seeds:",seeds(Seeds),"\n\n",cats(Cats).

% Check if a location has a corresponding seed.
best(Ss,_,Try,`seed`) :-
    member(S-L,Ss),
    Try >= S, S+L-1 >= Try,!.
best(Ss,Cs,Try0,Name) :-
    member(c(D-S-L,Fr,Name),Cs),
    Try0 >= D, D+L-1 >= Try0,
    Try is Try0+S-D,!,
    best(Ss,Cs,Try,Fr).
best(Ss,Cs,Try,Name) :-
    memberchk(c(_,Fr,Name),Cs),
    best(Ss,Cs,Try,Fr).

pairs([],Acc,Acc) :- !.
pairs([A,B|T],Acc,Result) :- pairs(T,[A-B|Acc],Result).

until(Ss,Cs,_,X,X) :- best(Ss,Cs,X,`location`),!.
until(Ss,Cs,Inc,X0,Y) :- X is X0+Inc, until(Ss,Cs,Inc,X,Y).

solve(File,X) :-
    phrase_from_file(file(Ss,Cs0),File),
    pairs(Ss,[],Seeds),
    flatten(Cs0,Cs),
    until(Seeds,Cs,10000,0,X0),
    Start is X0-10000, until(Seeds,Cs,1,Start,X).

```

---

<div class="post-metadata">

**Author:** ![emiruz](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emiruz/32/4495_2.png) [@emiruz](https://swi-prolog.discourse.group/u/emiruz)\
**Post date:** [December 5, 2023, 10:27pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/37 "2023-12-05T22:27:48Z")

</div>

> [@meditans](#):
>
> I’m unsure where the different stages (seed → soil etc) are processed here.

🙂 Good old single letter variable names. I learned a language called J once – oh dead, you should see what that looks like… single letter everything! But I totally agree, CHRs are specially difficult to “execute mentally”, needs lots of comments.

Something I don’t love about CHR is that the order of constraints is not just important – it is crucial. If the order made no difference, it would lose capabilities, but the significance of the order is quite difficult to interpret on static code review.

---

<div class="post-metadata">

**Author:** ![emiruz](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emiruz/32/4495_2.png) [@emiruz](https://swi-prolog.discourse.group/u/emiruz)\
**Post date:** [December 5, 2023, 10:39pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/38 "2023-12-05T22:39:59Z")

</div>

> [@meditans](#):
>
> Here’s my solution for both parts (comments are always welcome)

Its a beautiful solution but it contains a lot of Prolog features I never knew existed 🙂

I don’t know what “dynamic” predicates are. So far as I can tell it uses clpfd implicitly to create an optimisation of sorts? Does it run fairly quickly?

Have you seen the [stats for day 5](https://adventofcode.com/2023/stats)? At the time of writing a 40% drop-off on completion of any part compared to day 4. Of those who did complete some part of the puzzle, 40%+ did not complete part 2.

This was pretty difficult for day 5!

---

<div class="post-metadata">

**Author:** ![meditans](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/meditans/32/1768_2.png) [@meditans](https://swi-prolog.discourse.group/u/meditans)\
**Post date:** [December 5, 2023, 10:59pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/39 "2023-12-05T22:59:56Z")

</div>

> [@emiruz](#):
>
> feels like I’m missing some kind of key insight here which would have made for a more elegant solution.

Probably the fact that since the transformation is linear, you can process intervals instead of single numbers.

> [@emiruz](#):
>
> Something I don’t love about CHR is that the order of constraints is not just important – it is crucial. If the order made no difference, it would lose capabilities, but the significance of the order is quite difficult to interpret on static code review.

Yes, I agree, and it’s why I tend to avoid computations with more than 3/5 rules in CHR. It starts to become magical when I read it again.

> [@emiruz](#):
>
> I don’t know what “dynamic” predicates are. So far as I can tell it uses clpfd implicitly to create an optimisation of sorts? Does it run fairly quickly?

Dynamic predicates are predicates you can assert clauses of at runtime (check for `assertz` as a starting point). While I usually find this kind of behavior too side-effecty for my tastes I’m trying to de-empathize the role of ad-hoc datastructures, using just clauses instead. So the parsing creates a datastructure, but then, in `set_knowledge`, I extract all the subterms that look like information I want to have around, and assert those (and some cleanup).

The fact that I used clpfd is orthogonal to that, but it’s the key in having the solution run instantaneously - I mean the key is processing intervals instead of points, but clpfd makes it very pleasant to write. It’s probably one of my favorite libraries in prolog, to be fair.

---

<div class="post-metadata">

**Author:** ![emiruz](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emiruz/32/4495_2.png) [@emiruz](https://swi-prolog.discourse.group/u/emiruz)\
**Post date:** [December 5, 2023, 11:15pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/40 "2023-12-05T23:15:00Z")

</div>

> [@meditans](#):
>
> Probably the fact that since the transformation is linear, you can process intervals instead of single numbers.

What I had found tricky was that the range of the intervals at any given category isn’t exhaustive. So they can’t just be mapped to each other; fancier footwork is needed. I tried splitting and mapping intervals in various ways but it was too fiddly, I figured there must be some shortcut. Trying the numbers backwards (i.e. checking if a location has a corresponding seed) still takes \<1s to find a solution.

I’ve read through a many of the solutions on /r/adventofcode/ – very few solutions, are as clean and systematic as yours.

---

<div class="post-metadata">

**Author:** ![emiruz](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emiruz/32/4495_2.png) [@emiruz](https://swi-prolog.discourse.group/u/emiruz)\
**Post date:** [December 5, 2023, 11:16pm UTC](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025/41 "2023-12-05T23:16:22Z")

</div>

Found on Reddit. This year is a bit different 🙂

 ![image](https://global.discourse-cdn.com/free1/uploads/swiprolog/original/2X/1/1652cddba9044bd35c10bf3bfc1fda825454572a.png)

[Previous page](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025.md?page=1)

[Next page](https://swi-prolog.discourse.group/t/advent-of-code-2023/7025.md?page=3)
