Skip to content

Commit a990aa8

Browse files
committed
wow today was annoying
- spent a while trying to do this with just string replacement and gave up because of the spaces & realising I'd have to check for wins with that - eventually switched to a proper string[][] and from there it was trivial - for part 2, spent way too long trying to debug why my practice answer was wrong. I tried: - maybe it wants to exit immediately in the loop (in hindsight that makes no sense - there's no 'order' to bingo) - finally figured out I'm supposed to get a selection from next turn. should have logged res and selection immediately because I'd've seen instantly that selection was wrong but res was right and saved a lot of time. - mad that my part 1 rank is not the same as it was yesterday. I saw the number and I thought "oh that's what I got yesterday" but it wasn't quite
1 parent 6af3333 commit a990aa8

File tree

7 files changed

+994
-1
lines changed

7 files changed

+994
-1
lines changed

2021/solutions/day4/day4.1.ts

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
input: string, lines: string[], dblines: string[][]
3+
copy(text: string) → clipboard
4+
error(message: string) → thrown error
5+
-5..mod(3) → @mod(-5, 3)
6+
*/
7+
8+
// Cardinals:
9+
// [[1,0],[-1,0],[0,1],[0,-1]]
10+
// +Diagonals:
11+
// [[1,0],[-1,0],[0,1],[0,-1],[-1,-1],[-1,1],[1,-1],[1,1]]
12+
13+
export {};
14+
15+
const practice = `7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
16+
17+
22 13 17 11 0
18+
8 2 23 4 24
19+
21 9 14 16 7
20+
6 10 3 18 5
21+
1 12 20 15 19
22+
23+
3 15 0 2 22
24+
9 18 13 17 5
25+
19 8 7 25 23
26+
20 11 10 24 4
27+
14 21 16 12 6
28+
29+
14 21 17 24 4
30+
10 16 15 9 19
31+
18 8 23 26 20
32+
22 11 13 6 5
33+
2 0 12 3 7`;
34+
// input = practice;
35+
36+
37+
let [selections, ...boardsraw] = input.split("\n\n");
38+
39+
let boards = boardsraw.map(b => {
40+
const v = b.trim().split("\n").map(l => l.trim().split(/ +/));
41+
return v;
42+
});
43+
boards.dwth(log);
44+
45+
function checkWin(board: string[][]): boolean {
46+
let win = false;
47+
range(5).forEach(y => {
48+
if(!win) win = range(5).every(x => {
49+
return board[y][x] === "X";
50+
});
51+
});
52+
range(5).forEach(x => {
53+
if(!win) win = range(5).every(y => {
54+
return board[y][x] === "X";
55+
});
56+
});
57+
return win;
58+
}
59+
60+
for(const selection of selections.split(",")) {
61+
boards = boards.map(board => board.map(line => line.map(col => col === selection ? "X" : col)));
62+
boards.dwth(log).forEach(board => {
63+
if(checkWin(board)) {
64+
const res = board.reduce((a, b) => a + b.reduce((t, v) => t + (v === "X" ? 0 : +v), 0), 0);
65+
(res * +selection).dwth(log); // expect-equal 16674
66+
throw new Error(`${board} wins`);
67+
}
68+
})
69+
}
70+
71+
72+
73+
74+
75+
76+
77+
78+
79+
type nobi = number | bigint;
80+
type Board<T> = {
81+
get(pos: Point2D): T;
82+
set(pos: Point2D, t: T): void;
83+
clear(): void;
84+
forEach(visitor: (v: T, pos: Point2D) => void): void;
85+
print(printer?: (v: T, pos: Point2D) => string | nobi): string;
86+
copy(): Board<T>;
87+
};
88+
function makeBoard<T>(fill: T): Board<T> {
89+
// it would be useful if board could center at 0,0 and expand infinitely
90+
let board: T[][] = [];
91+
let limits:
92+
| { min: Point2D, max: Point2D }
93+
| undefined;
94+
let reso: Board<T> = {
95+
clear: () => {
96+
board = [];
97+
},
98+
get: (pos) => {
99+
if (!limits) return fill;
100+
if (
101+
pos.op(limits.min, (a, b) => a < b).some(w => w) ||
102+
pos.op(limits.max, (a, b) => a > b).some(w => w)
103+
) return fill;
104+
if (!board[pos.y]) return fill;
105+
let bval = board[pos.y][pos.x];
106+
return bval === undefined ? fill : bval;
107+
},
108+
set: (pos, v) => {
109+
if (!limits) {
110+
limits = {min: dupe(pos), max: dupe(pos)};
111+
}
112+
limits.min = pos.op(limits.min, (a, b) => Math.min(a, b));
113+
limits.max = pos.op(limits.max, (a, b) => Math.max(a, b));
114+
if (!board[pos.y]) board[pos.y] = [];
115+
board[pos.y][pos.x] = v;
116+
},
117+
forEach: visitor => {
118+
if (!limits) return;
119+
for (let y = limits.min.y; y <= limits.max.y; y++) {
120+
for (let x = limits.min.x; x <= limits.max.x; x++) {
121+
visitor(reso.get([x, y]), [x, y]);
122+
}
123+
}
124+
},
125+
copy: () => {
126+
let nb = makeBoard<T>(fill);
127+
reso.forEach((v, pos) => nb.set(pos, v));
128+
return nb;
129+
},
130+
print: (printer = v => v as any): string => {
131+
// ratelimit print
132+
if (!limits) return "*no board to print*";
133+
let ylength = 0;
134+
for (let y = limits.min.y - 1; y <= limits.max.y + 1; y++) {
135+
ylength = Math.max(y.toString().length, ylength);
136+
}
137+
const resc: string[] = [];
138+
let llen: number = limits.max.x - limits.min.x + 3;
139+
for (let y = limits.min.y - 1; y <= limits.max.y + 1; y++) {
140+
let line = "";
141+
for (let x = limits.min.x - 1; x <= limits.max.x + 1; x++) {
142+
line += printer(reso.get([x, y]), [x, y]);
143+
}
144+
if(line.length > llen) llen = line.length;
145+
resc.push(y.toString().padStart(ylength, " ") + " | " + line + " |");
146+
}
147+
resc.unshift(
148+
" ".repeat(ylength) +
149+
" .-" +
150+
"-".repeat(llen) +
151+
"-. " + (limits.min.y - 1) + " .. " + (limits.max.y + 1),
152+
);
153+
resc.push(
154+
" ".repeat(ylength) +
155+
" '-" +
156+
"-".repeat(llen) +
157+
"-'",
158+
);
159+
return resc.join("\n");
160+
},
161+
};
162+
return reso;
163+
}

2021/solutions/day4/day4.2.ts

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
input: string, lines: string[], dblines: string[][]
3+
copy(text: string) → clipboard
4+
error(message: string) → thrown error
5+
-5..mod(3) → @mod(-5, 3)
6+
*/
7+
8+
// Cardinals:
9+
// [[1,0],[-1,0],[0,1],[0,-1]]
10+
// +Diagonals:
11+
// [[1,0],[-1,0],[0,1],[0,-1],[-1,-1],[-1,1],[1,-1],[1,1]]
12+
13+
export {};
14+
15+
const practice = `7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
16+
17+
22 13 17 11 0
18+
8 2 23 4 24
19+
21 9 14 16 7
20+
6 10 3 18 5
21+
1 12 20 15 19
22+
23+
3 15 0 2 22
24+
9 18 13 17 5
25+
19 8 7 25 23
26+
20 11 10 24 4
27+
14 21 16 12 6
28+
29+
14 21 17 24 4
30+
10 16 15 9 19
31+
18 8 23 26 20
32+
22 11 13 6 5
33+
2 0 12 3 7`;
34+
// input = practice;
35+
36+
37+
let [selections, ...boardsraw] = input.split("\n\n");
38+
39+
let boards = boardsraw.map(b => {
40+
const v = b.trim().split("\n").map(l => l.trim().split(/ +/));
41+
return v;
42+
});
43+
boards.dwth(log);
44+
45+
function checkWin(board: string[][]): boolean {
46+
let win = false;
47+
range(5).forEach(y => {
48+
if(!win) win = range(5).every(x => {
49+
return board[y][x] === "X";
50+
});
51+
});
52+
range(5).forEach(x => {
53+
if(!win) win = range(5).every(y => {
54+
return board[y][x] === "X";
55+
});
56+
});
57+
return win;
58+
}
59+
60+
let wnext = false;
61+
for(const selection of selections.split(",")) {
62+
let nwin = false;
63+
boards = boards.map(board => {
64+
// if(nwin) return board;
65+
const res = board.map(line => line.map(col => col === selection ? "X" : col))
66+
// if(checkWin(res)) nwin = true;
67+
return res;
68+
});
69+
if(wnext) {
70+
selection.dwth(log);
71+
const board = boards[0];
72+
const res = board.reduce((a, b) => a + b.reduce((t, v) => t + (v === "X" ? 0 : +v), 0), 0);
73+
res.dwth(log);
74+
(res * +selection).dwth(log); // expect-equal 7075
75+
throw new Error(`${board} wins`);
76+
}
77+
boards = boards.dwth(log).filter(board => !checkWin(board));
78+
79+
if(boards.length === 1) {
80+
wnext = true;
81+
}
82+
}
83+
84+
85+
86+
87+
88+
89+
90+
91+
92+
93+
type nobi = number | bigint;
94+
type Board<T> = {
95+
get(pos: Point2D): T;
96+
set(pos: Point2D, t: T): void;
97+
clear(): void;
98+
forEach(visitor: (v: T, pos: Point2D) => void): void;
99+
print(printer?: (v: T, pos: Point2D) => string | nobi): string;
100+
copy(): Board<T>;
101+
};
102+
function makeBoard<T>(fill: T): Board<T> {
103+
// it would be useful if board could center at 0,0 and expand infinitely
104+
let board: T[][] = [];
105+
let limits:
106+
| { min: Point2D, max: Point2D }
107+
| undefined;
108+
let reso: Board<T> = {
109+
clear: () => {
110+
board = [];
111+
},
112+
get: (pos) => {
113+
if (!limits) return fill;
114+
if (
115+
pos.op(limits.min, (a, b) => a < b).some(w => w) ||
116+
pos.op(limits.max, (a, b) => a > b).some(w => w)
117+
) return fill;
118+
if (!board[pos.y]) return fill;
119+
let bval = board[pos.y][pos.x];
120+
return bval === undefined ? fill : bval;
121+
},
122+
set: (pos, v) => {
123+
if (!limits) {
124+
limits = {min: dupe(pos), max: dupe(pos)};
125+
}
126+
limits.min = pos.op(limits.min, (a, b) => Math.min(a, b));
127+
limits.max = pos.op(limits.max, (a, b) => Math.max(a, b));
128+
if (!board[pos.y]) board[pos.y] = [];
129+
board[pos.y][pos.x] = v;
130+
},
131+
forEach: visitor => {
132+
if (!limits) return;
133+
for (let y = limits.min.y; y <= limits.max.y; y++) {
134+
for (let x = limits.min.x; x <= limits.max.x; x++) {
135+
visitor(reso.get([x, y]), [x, y]);
136+
}
137+
}
138+
},
139+
copy: () => {
140+
let nb = makeBoard<T>(fill);
141+
reso.forEach((v, pos) => nb.set(pos, v));
142+
return nb;
143+
},
144+
print: (printer = v => v as any): string => {
145+
// ratelimit print
146+
if (!limits) return "*no board to print*";
147+
let ylength = 0;
148+
for (let y = limits.min.y - 1; y <= limits.max.y + 1; y++) {
149+
ylength = Math.max(y.toString().length, ylength);
150+
}
151+
const resc: string[] = [];
152+
let llen: number = limits.max.x - limits.min.x + 3;
153+
for (let y = limits.min.y - 1; y <= limits.max.y + 1; y++) {
154+
let line = "";
155+
for (let x = limits.min.x - 1; x <= limits.max.x + 1; x++) {
156+
line += printer(reso.get([x, y]), [x, y]);
157+
}
158+
if(line.length > llen) llen = line.length;
159+
resc.push(y.toString().padStart(ylength, " ") + " | " + line + " |");
160+
}
161+
resc.unshift(
162+
" ".repeat(ylength) +
163+
" .-" +
164+
"-".repeat(llen) +
165+
"-. " + (limits.min.y - 1) + " .. " + (limits.max.y + 1),
166+
);
167+
resc.push(
168+
" ".repeat(ylength) +
169+
" '-" +
170+
"-".repeat(llen) +
171+
"-'",
172+
);
173+
return resc.join("\n");
174+
},
175+
};
176+
return reso;
177+
}

2021/solutions/day4/day4.3.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
input: string, lines: string[], dblines: string[][]
3+
copy(text: string) → clipboard
4+
error(message: string) → thrown error
5+
-5..mod(3) → @mod(-5, 3)
6+
*/
7+
8+
// Cardinals:
9+
// [[1,0],[-1,0],[0,1],[0,-1]]
10+
// +Diagonals:
11+
// [[1,0],[-1,0],[0,1],[0,-1],[-1,-1],[-1,1],[1,-1],[1,1]]
12+
13+
export {};
14+
15+
const practice = ``;
16+
17+
// input = practice;

2021/solutions/day4/day4.4.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
input: string, lines: string[], dblines: string[][]
3+
copy(text: string) → clipboard
4+
error(message: string) → thrown error
5+
-5..mod(3) → @mod(-5, 3)
6+
*/
7+
8+
// Cardinals:
9+
// [[1,0],[-1,0],[0,1],[0,-1]]
10+
// +Diagonals:
11+
// [[1,0],[-1,0],[0,1],[0,-1],[-1,-1],[-1,1],[1,-1],[1,1]]
12+
13+
export {};
14+
15+
const practice = ``;
16+
17+
// input = practice;

0 commit comments

Comments
 (0)