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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import { Dusa } from "https://unpkg.com/dusa@0.0.11/lib/client.js";
const INPUT = `
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
`
.trim()
.split(",")
.map((line) => ({ length: line.length, ascii: line.split("").map((ch) => ch.charCodeAt(0)) }));
const dusa = new Dusa(`
# AOC Day 15, Part 1
#builtin INT_PLUS plus
#builtin INT_TIMES times
#builtin INT_MINUS minus
#builtin NAT_SUCC s
entries is N :- field _ "entries" is N.
length Entry is Len :-
field _ Entry is Ref,
field Ref "length" is Len.
ascii Entry N is Ch :-
field _ Entry is Ref,
field Ref "ascii" is Str,
field Str N is Ch.
# Hash computation
partial Entry 0 is 0 :- ascii Entry _ is _.
partial Entry (s N) is Next :-
partial Entry N is Val,
ascii Entry N is Code,
X == times 17 (plus Val Code),
mod256 X is Next.
needMod256 X X :-
partial Entry N is Val,
ascii Entry N is Code,
X == times 17 (plus Val Code).
hash Entry is Hash :-
length Entry is Len,
partial Entry Len is Hash.
# LOL, division by repeated subtraction
mod256 X is Y :-
needMod256 X Y,
Y < 256.
needMod256 X (minus Y 256) :-
needMod256 X Y,
Y >= 256.
# Goal
sum 0 is 0.
sum (s N) is (plus Accum Hash) :-
sum N is Accum,
hash N is Hash.
goal is (sum entries).
`);
dusa.load({ data: INPUT, entries: INPUT.length }, "field");
console.log(dusa.solution.get("goal"));