Search results for "aoc"

Advent of Code 2023 - Day 1 solutions

Readme
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
// #folder:aoc2023
// @aoc2023
// @title Day 1 solutions
import getAocData from "https://esm.town/v/nbbaier/getAocData";
const data = await getAocData(1);
const input = (await data.text()).split("\n").slice(0, -1);
const numberMap: Map<string, number> = new Map<string, number>([
["one", 1],
["two", 2],
["three", 3],
["four", 4],
["five", 5],
["six", 6],
["seven", 7],
["eight", 8],
["nine", 9],
]);
function findDigits(line: string) {
const foundDigits = Array.from(numberMap.entries()).map((number) => ({
matches: Array.from(
line.matchAll(new RegExp(`${number[0]}|${number[1]}`, "g")),
),
}));
return foundDigits;
}
export const solution = (() => {
const partOne = input
.map(line => Array.from(line).filter(char => /\d/.test(char)))
.map(line => line.length > 1 ? line[0] + line[line.length - 1] : line[0] + line[0])
.map(num => parseInt(num)).reduce((total, num) => total + num, 0);
const partTwo = input.map(line =>
findDigits(line)
.flatMap(el => el.matches.map((match) => ({ digit: match[0], index: match.index })))
.sort((a, b) => a.index - b.index)
.map((element) => /\d/.test(element.digit) ? Number(element.digit) : numberMap.get(element.digit))
)
.map(line => line.length > 1 ? `${line[0]}${line[line.length - 1]}` : `${line[0]}${line[0]}`)
.map(num => parseInt(num))
.reduce((total, num) => total + num, 0);
return { partOne, partTwo };
})();
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
// #folder:aoc2023
// @aoc2023
// @title Day 3 solutions
import getAocData from "https://esm.town/v/nbbaier/getAocData";
const data = await (await getAocData(3)).text();
const input = data.split("\n");
const symbolRegex: RegExp = new RegExp(
Array.from(new Set(data.split("\n").map(line => line.split("")).flat())).filter(char => !/[.\d]/.test(char)).map(
escapeRegex,
).join(
"|",
),
"g",
);
const numberRegex: RegExp = /\d+/g;
interface NumMetadata {
line: number;
idx: number;
number: string;
length: number;
adjacentPoints?: number[][];
}
interface SymbolMetadata {
point: number[];
symbol: string;
}
function getAdjacentCoordinates(point: number[]) {
const xPoint = point[0];
const yPoint = point[1];
const offsets = [-1, 0, 1];
const adjacentCoordinates = [];
for (const x of offsets) {
for (const y of offsets) {
if (x !== 0 || y !== 0) {
if (xPoint + x >= 0 && yPoint + y >= 0 && xPoint + x < input[yPoint].length && yPoint < input.length) {
adjacentCoordinates.push([xPoint + x, yPoint + y]);
}
}
}
}
return adjacentCoordinates;
}
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
import * as base64 from "https://deno.land/std/encoding/base64.ts";
const bytes = base64.decodeBase64(
// base64 encoded wasm module
"AGFzbQEAAAABiwEUYAJ/fwF/YAJ/fwBgA39/fwF/YAF/AX9gA39/fwBgAX8AYAR/f39/AGAAAX9gBX9/f39/AGAEf39/fwF/YAZ/f39/f38Bf2AHf39/f39/fwF/YAZ+f39/f38BfmADfn9/AX9gB39/f39/f38AYAJ+fwBgA39+fgBgBH9+fn8AYAV/f39/fwF/YAAAAjcBGF9fd2JpbmRnZW5fcGxhY2Vob2xkZXJfXxpfX3diZ19sb2dfM
);
let imports: any = {};
imports["__wbindgen_placeholder__"] = imports;
let wasm;
const { TextDecoder, TextEncoder } = globalThis;
let cachedTextDecoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true });
cachedTextDecoder.decode();
let cachedUint8Memory0 = null;
function getUint8Memory0() {
if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachedUint8Memory0;
}
function getStringFromWasm0(ptr, len) {
ptr = ptr >>> 0;
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
let WASM_VECTOR_LEN = 0;
let cachedTextEncoder = new TextEncoder("utf-8");
const encodeString = typeof cachedTextEncoder.encodeInto === "function"
? function(arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
}
: function(arg, view) {
const buf = cachedTextEncoder.encode(arg);
view.set(buf);
return {
read: arg.length,
written: buf.length,
};
};
function passStringToWasm0(arg, malloc, realloc) {
if (realloc === undefined) {
const buf = cachedTextEncoder.encode(arg);
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
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) => {
const label = line.split('-')[0].split('=')[0];
return {
label,
length: label.length,
ascii: label.split('').map((ch) => ch.charCodeAt(0)),
focal: line[label.length] === '-' ? null : parseInt(line.slice(label.length + 1)),
};
});
const dusa = new Dusa(`
# AOC Day 15, Part 2
#builtin INT_PLUS plus
#builtin INT_TIMES times
#builtin INT_MINUS minus
#builtin NAT_SUCC s
numBoxes is 256.
entries is N :- field _ "entries" is N.
labelLength Label is Len :-
field Ref "length" is Len,
field Ref "label" is Label.
ascii Label N is Ch :-
field _ Entry is Ref,
field Ref "label" is Label,
field Ref "ascii" is Str,
field Str N is Ch.
label Entry is Label :-
field _ Entry is Ref,
field Ref "label" is Label.
instruction Entry is del :-
field _ Entry is Ref,
field Ref "focal" is ().
instruction Entry is add N :-
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
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
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
O....#....
O.OO#....#
.....##...
OO.#O....O
.O.....O#.
O.#..O.#.#
..O..#O..O
.......O..
#....###..
#OO..#....
`
.trim()
.split("\n")
.map((line) => line.split(""));
const PROGRAM = `
# AOC Day 14, Part 2 - Take 1
#builtin INT_MINUS minus
#builtin NAT_SUCC s
#builtin INT_PLUS plus
input X Y is Ch :-
field Root "data" is Data,
field Data Y is Row,
field Row X is Ch.
height is N :- field Root "height" is N.
width is N :- field Root "width" is N.
# PART 1: RANGE CALCULATION
# We're going to calculate all the horizontal ranges
# (hRange (pair X Y) is Width) is Height) and vertical
# ranges (vRange (pair X Y), identifying them with
# their leftmost/topmost point. We'll also create
# a lookup table for every non-blocked point:
# (hRangeFor (pair X Y) is (pair XStart Y)) and
# (vRangeFor (pair X Y) is (pair X YStart)).
# A range (horizontal or vertical) starts on any open
# space (non-#) that is at the left/top boundary or
# to the immediate right/bottom of a # symbol
growHRange (pair 0 Y) 0 :-
input 0 Y is Ch, Ch != "#".
growHRange (pair X Y) X :-
input X Y is Ch, Ch != "#",
XPrev == minus X 1,
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
O....#....
O.OO#....#
.....##...
OO.#O....O
.O.....O#.
O.#..O.#.#
..O..#O..O
.......O..
#....###..
#OO..#....
`
.trim()
.split("\n")
.map((line) => line.split(""));
const dusa = new Dusa(`
# AOC Day 14, Part 2 - Take 1
#builtin INT_MINUS minus
#builtin NAT_SUCC s
#builtin INT_PLUS plus
input X Y is Ch :-
field Root "data" is Data,
field Data Y is Row,
field Row X is Ch.
height is N :- field Root "height" is N.
width is N :- field Root "width" is N.
# PART 1: RANGE CALCULATION
# We're going to calculate all the horizontal ranges
# (hRange (pair X Y) is Width) is Height) and vertical
# ranges (vRange (pair X Y), identifying them with
# their leftmost/topmost point. We'll also create
# a lookup table for every non-blocked point:
# (hRangeFor (pair X Y) is (pair XStart Y)) and
# (vRangeFor (pair X Y) is (pair X YStart)).
# A range (horizontal or vertical) starts on any open
# space (non-#) that is at the left/top boundary or
# to the immediate right/bottom of a # symbol
growHRange (pair 0 Y) 0 :-
input 0 Y is Ch, Ch != "#".
growHRange (pair X Y) X :-
input X Y is Ch, Ch != "#",
XPrev == minus X 1,
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
???.### 1,1,3
.??..??...?##. 1,1,3
?#?#?#?#?#?#?#? 1,3,1,6
????.#...#... 4,1,1
????.######..#####. 1,6,5
?###???????? 3,2,1
`
.trim()
.split("\n");
const PROGRAM = `
#builtin NAT_SUCC s
#builtin STRING_CONCAT concat
value N is "#" :- char N is "#".
value N is "." :- char N is ".".
value N is { "#", "." } :- char N is "?".
startRun 0 is true :- value 0 is "#".
startRun (s N) is true :-
value N is ".",
value (s N) is "#".
startRun N is false :- value N is ".".
startRun (s N) is false :- value N is "#", value (s N) is "#".
startRun N is { false? } :- char N is _.
scan 0 is Lens :- runs is Lens.
scan (s N) is Lens :-
startRun N is false,
scan N is Lens.
scan (s N) is Lens :-
startRun N is true,
scan N is (cons Len Lens).
runAt N is Len :-
startRun N is true,
scan N is (cons Len Lens).
value N is "#" :-
runAt N is (s Len).
runAt (s N) is Len :-
runAt N is (s Len).
value N is "." :-
runAt N is 0.
#forbid startRun N is true, scan N is nil.
#forbid scan length is cons _ _.
#forbid length is Len, runAt Len is (s _).
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
#.##..##.
..#.##.#.
##......#
##......#
..#.##.#.
..##..##.
#.#.##.#.
#...##..#
#....#..#
..##..###
#####.##.
#####.##.
..##..###
#....#..#
`
.trim()
.split("\n\n")
.map((grid) => grid.split("\n").map((line) => line.split("")));
const PROGRAM = `
# AOC Day 13 Solution
#builtin NAT_SUCC s
#builtin INT_MINUS minus
#builtin INT_PLUS plus
#builtin INT_TIMES times
input (s X) (s Y) is Ch :-
field Root Y is Row,
field Row X is Ch.
# Characters for Part 1 are exactly the inputs
char part1 X Y is Ch :- input X Y is Ch.
# Characters for Part 2 are the inputs with
# one smudge - a "#" turned to a "." (could
# symmetrically be a "." turned to a "#")
smudge is { pair X Y? } :-
input X Y is "#",
finishedPart1.
char part2 X Y is Ch :-
smudge is (pair SX SY),
input X Y is Ch,
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
???.### 1,1,3
.??..??...?##. 1,1,3
?#?#?#?#?#?#?#? 1,3,1,6
????.#...#... 4,1,1
????.######..#####. 1,6,5
?###???????? 3,2,1
`
.trim()
.split("\n");
const PROGRAM = `
#builtin NAT_SUCC s
#builtin INT_PLUS plus
getWays 0 noRun RunList :- runs is RunList.
# When we're NOT in a run
numWays N noRun nil is 0 :-
getWays N noRun nil,
char N is "#".
numWays N noRun RunList is NWays :-
getWays N noRun RunList,
RunList == (cons (s Len) SubList),
char N is "#",
numWays (s N) (run Len) SubList is NWays.
getWays (s N) (run Len) SubList :-
getWays N noRun RunList,
RunList == (cons (s Len) SubList),
char N is Ch, Ch != ".".
numWays N noRun RunList is NWays :-
getWays N noRun RunList,
char N is ".",
numWays (s N) noRun RunList is NWays.
getWays (s N) noRun RunList :-
getWays N noRun RunList,
char N is Ch, Ch != "#".
numWays N noRun nil is NWaysDot :-
getWays N noRun nil,
char N is "?",
numWays (s N) noRun nil is NWaysDot.
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
...#......
.......#..
#.........
..........
......#...
.#........
.........#
..........
.......#..
#...#.....
`
.trim()
.split("\n")
.map((line) => line.trim().split(""));
const PROGRAM = `
# AOC Day 11
#builtin NAT_SUCC s
#builtin INT_TIMES times
#builtin INT_PLUS plus
#builtin INT_MINUS minus
# Process input to get X, Y coordinates
charAt X Y is Ch :-
field _ "map" is List,
field List Y is Cols,
field Cols X is Ch.
width is W :- field _ "width" is W.
expansionFactor is F :- field _ "expansionFactor" is F.
# Use default reasoning to find out which rows/cols have stars
hasStar y Y is { false? } :- charAt _ Y is _.
hasStar y Y is true :- charAt _ Y is "#".
hasStar x X is { false? } :- charAt X _ is _.
hasStar x X is true :- charAt X _ is "#".
needsRemap x 0 0.
needsRemap y 0 0.
remap Axis Old is (minus (plus New expansionFactor) 1) :-
needsRemap Axis Old New,
hasStar Axis Old is false.
remap Axis Old is New :-
needsRemap Axis Old New,
hasStar Axis Old is true.
needsRemap Axis (s Old) (s New) :-
remap Axis Old is New.
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
...#......
.......#..
#.........
..........
......#...
.#........
.........#
..........
.......#..
#...#.....
`
.trim()
.split("\n")
.map((line) => line.trim().split(""));
const PROGRAM = `
# AOC Day 11
#builtin NAT_SUCC s
#builtin INT_TIMES times
#builtin INT_PLUS plus
#builtin INT_MINUS minus
# Process input to get X, Y coordinates
charAt X Y is Ch :-
field _ "map" is List,
field List Y is Cols,
field Cols X is Ch.
width is W :- field _ "width" is W.
expansionFactor is F :- field _ "expansionFactor" is F.
# Use default reasoning to find out which rows/cols have stars
hasStar y Y is { false? } :- charAt _ Y is _.
hasStar y Y is true :- charAt _ Y is "#".
hasStar x X is { false? } :- charAt X _ is _.
hasStar x X is true :- charAt X _ is "#".
needsRemap x 0 0.
needsRemap y 0 0.
remap Axis Old is (minus (plus New expansionFactor) 1) :-
needsRemap Axis Old New,
hasStar Axis Old is false.
remap Axis Old is New :-
needsRemap Axis Old New,
hasStar Axis Old is true.
needsRemap Axis (s Old) (s New) :-
remap Axis Old is New.
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
.F----7F7F7F7F-7....
.|F--7||||||||FJ....
.||.FJ||||||||L7....
FJL7L7LJLJ||LJ.L-7..
L--J.L7...LJS7F-7L7.
....F-J..F7FJ|L7L7L7
....L7.F7||L7|.L7L7|
.....|FJLJ|FJ|F7|.LJ
....FJL-7.||.||||...
....L---J.LJ.LJLJ...
`
.trim()
.split("\n")
.map((line) => line.trim().split(""));
const dusa = new Dusa(`
# AOC Day 10, Part 2
#builtin INT_PLUS plus
#builtin INT_MINUS minus
# Process input to get X, Y coordinates
charAt (pair X Y) is Ch :-
field _ "map" is List,
field List Y is Cols,
field Cols X is Ch.
# Which connections does a character imply?
connectX "L" 1. connectY "L" -1.
connectX "J" -1. connectY "J" -1.
connectX "F" 1. connectY "F" 1.
connectX "7" -1. connectY "7" 1.
connectY "|" -1. connectY "|" 1.
connectX "-" -1. connectX "-" 1.
# Edges require agreement between the source and destination
# about there being a connection
# Horizontal edges (only X changes)
edge A B :-
charAt A is Ch, A == pair X1 Y,
connectX Ch Delta, X2 == plus X1 Delta,
B == pair X2 Y, charAt B is Ch2,
connectX Ch2 (minus 0 Delta).
# Vertical edges (only Y changes)
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
7-F7-
.FJ|7
SJLL7
|F--J
LJ.LJ
`
.trim()
.split("\n")
.map((line) => line.trim().split(""));
const dusa = new Dusa(`
# AOC Day 10, Part 1
#builtin INT_PLUS plus
#builtin INT_MINUS minus
# Process input to get X, Y coordinates
charAt (pair X Y) is Ch :-
field _ "map" is List,
field List Y is Cols,
field Cols X is Ch.
# Which connections does a character imply?
connectX "L" 1. connectY "L" -1.
connectX "J" -1. connectY "J" -1.
connectX "F" 1. connectY "F" 1.
connectX "7" -1. connectY "7" 1.
connectY "|" -1. connectY "|" 1.
connectX "-" -1. connectX "-" 1.
# Edges require agreement between the source and destination
# about there being a connection
# Horizontal edges (only X changes)
edge A B :-
charAt A is Ch, A == pair X1 Y,
connectX Ch Delta, X2 == plus X1 Delta,
B == pair X2 Y, charAt B is Ch2,
connectX Ch2 (minus 0 Delta).
# Vertical edges (only Y changes)
edge A B :-
charAt A is Ch, A == pair X Y1,
connectY Ch Delta, Y2 == plus Y1 Delta,
B == pair X Y2, charAt B is Ch2,
connectY Ch2 (minus 0 Delta).
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
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
0 3 6 9 12 15
1 3 6 10 15 21
10 13 16 21 30 45
`
.trim()
.split("\n")
.map((line) => {
const values = line
.trim()
.split(" ")
.map((n) => parseInt(n));
return {
length: values.length,
values,
};
});
const dusa = new Dusa(`
# AOC Day 9
#builtin INT_MINUS minus
#builtin INT_PLUS plus
#builtin NAT_SUCC s
# We can compute diffs from sequences...
seq Seq (plus D 1) N is (minus V2 V1) :-
needDiffs Seq D,
seq Seq D N is V1,
seq Seq D (plus N 1) is V2.
# ...and we can also compute sequences from diffs!
seq Seq D (plus N 1) is (plus V1 Delta) :-
seq Seq D N is V1,
seq Seq (plus D 1) N is Delta.
# ...in both directions!
seq Seq D N is (minus V2 Delta) :-
seq Seq D (plus N 1) is V2,
seq Seq (plus D 1) N is Delta.
# We need diffs whenever there's a non-zero value in a sequence
needDiffs Seq D :-
seq Seq D N is V,
V != 0.
# And the length of the subsequent sequence will be one shorter
len Seq (plus D 1) is Len :-
needDiffs Seq D,