Skip to content

Commit c6aca6c

Browse files
author
Alberto Bastos
committed
Day 17 Part 1
1 parent 8ab86cf commit c6aca6c

File tree

3 files changed

+85
-69
lines changed

3 files changed

+85
-69
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,7 @@ typings/
5959

6060
# next.js build output
6161
.next
62+
63+
# manually added
64+
*.py
65+
out_*

input/d17.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1669,4 +1669,4 @@ y=625, x=580..601
16691669
y=542, x=492..510
16701670
y=633, x=637..660
16711671
x=506, y=208..230
1672-
x=631, y=1832..1834
1672+
x=631, y=1832..1834

src/d17.js

Lines changed: 80 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ function programReadLine(rl) {
2222
});
2323

2424
rl.on("close", () => {
25-
let data = run(JSON.parse(JSON.stringify(CLAY_INPUT)));
26-
console.log("Answer (part I):", data.part1);
27-
console.log("Answer (part II):", data.part2);
25+
let data = run(CLAY_INPUT);
26+
console.log("Answer (part I):", data.part1); // expected: 33724
27+
console.log("Answer (part II):", data.part2); // expected: ?
2828
console.timeEnd("d17");
2929
});
3030
}
@@ -46,112 +46,104 @@ function run(clayInput) {
4646

4747
data.part1 = Object.values(data.filledByXY).filter(contents => contents === WATER || contents === WATER_FLOW).length;
4848

49-
//printData(data, 494, 507, 0, data.maxY);
49+
//printData(data);
5050

5151
return data;
5252
}
5353

5454
function flowWater(data, cursor) {
5555
if (cursor.y >= data.maxY) return; // recursion end condition
5656

57+
//console.log("flow", cursor);
58+
5759
let cursorDown = { ...cursor, y: cursor.y + 1 };
5860
let cursorLeft = { ...cursor, x: cursor.x - 1 };
5961
let cursorRight = { ...cursor, x: cursor.x + 1 };
6062

61-
//console.log("flow", cursor);
62-
6363
if (isEmpty(data, cursorDown)) {
64-
fill(data, cursorDown, WATER_FLOW);
64+
// can keep flowing down, call recursively
65+
if (cursorDown.y >= data.minY) fill(data, cursorDown, WATER_FLOW); // careful, answer expects only water from first row with clay!
6566
flowWater(data, cursorDown);
6667
}
6768

6869
if (isStale(data, cursorDown) && isEmpty(data, cursorLeft)) {
70+
// we have either stale water or clay below and free space to the left, water can flow that way
6971
fill(data, cursorLeft, WATER_FLOW);
7072
flowWater(data, cursorLeft);
7173
}
7274

7375
if (isStale(data, cursorDown) && isEmpty(data, cursorRight)) {
76+
// we have either stale water or clay below and free space to the right, water can flow that way
7477
fill(data, cursorRight, WATER_FLOW);
7578
flowWater(data, cursorRight);
7679
}
7780

78-
if (isBetweenWalls(data, cursor)) {
79-
fillToWalls(data, cursor);
81+
if (isStale(data, cursorDown) && hasWallLeft(data, cursor) && hasWallRight(data, cursor)) {
82+
// we are either stale water or clay below and walls on both sides, water will fill that space
83+
fillLeft(data, cursor, WATER);
84+
fillRight(data, cursor, WATER);
8085
fill(data, cursor, WATER);
8186
}
8287
}
8388

84-
function isBetweenWalls({ filledByXY }, cursor) {
85-
// see if we reach a wall on each side
86-
let wallLeft, wallRight;
89+
function isEmpty(data, cursor) {
90+
return !getContents(data, cursor);
91+
}
92+
93+
function isStale(data, cursor) {
94+
return [WATER, CLAY].indexOf(getContents(data, cursor)) > -1;
95+
}
96+
97+
function isClay(data, cursor) {
98+
return getContents(data, cursor) === CLAY;
99+
}
100+
101+
function hasWallLeft(data, cursor) {
87102
let offset = -1;
88-
searchLeft: while (true) {
89-
let cursorLeft = { ...cursor, x: cursor.x + offset };
90-
if (isEmpty({ filledByXY }, cursorLeft)) {
91-
wallLeft = false;
92-
break searchLeft;
93-
}
94-
if (isWall({ filledByXY }, cursorLeft)) {
95-
wallLeft = true;
96-
break searchLeft;
97-
}
98-
// water (either stale or flow), keep looking left
103+
while (true) {
104+
let cursorOffset = { ...cursor, x: cursor.x + offset };
105+
if (isEmpty(data, cursorOffset)) return false;
106+
if (isClay(data, cursorOffset)) return true;
99107
offset--;
100108
}
101-
offset = 1;
102-
searchRight: while (true) {
103-
let cursorRight = { ...cursor, x: cursor.x + offset };
104-
if (isEmpty({ filledByXY }, cursorRight)) {
105-
wallRight = false;
106-
break searchRight;
107-
}
108-
if (isWall({ filledByXY }, cursorRight)) {
109-
wallRight = true;
110-
break searchRight;
111-
}
112-
// water (either stale or flow), keep looking right
109+
}
110+
111+
function hasWallRight(data, cursor) {
112+
let offset = 1;
113+
while (true) {
114+
let cursorOffset = { ...cursor, x: cursor.x + offset };
115+
if (isEmpty(data, cursorOffset)) return false;
116+
if (isClay(data, cursorOffset)) return true;
113117
offset++;
114118
}
115-
return wallLeft && wallRight;
116119
}
117120

118-
function fillToWalls({ filledByXY }, cursor) {
121+
function fillLeft(data, cursor, contents) {
119122
let offset = -1;
120-
fillLeft: while (true) {
121-
let cursorLeft = { ...cursor, x: cursor.x + offset };
122-
if (isWall({ filledByXY }, cursorLeft)) {
123-
break fillLeft;
124-
}
125-
fill({ filledByXY }, cursorLeft, WATER);
123+
while (true) {
124+
let cursorOffset = { ...cursor, x: cursor.x + offset };
125+
if (isClay(data, cursorOffset)) return;
126+
fill(data, cursorOffset, contents);
126127
offset--;
127128
}
128-
offset = 1;
129-
fillRight: while (true) {
130-
let cursorRight = { ...cursor, x: cursor.x + offset };
131-
if (isWall({ filledByXY }, cursorRight)) {
132-
break fillRight;
133-
}
134-
fill({ filledByXY }, cursorRight, WATER);
135-
offset++;
136-
}
137129
}
138130

139-
function isEmpty({ filledByXY }, cursor) {
140-
return !filledByXY[strXY(cursor)];
141-
}
142-
143-
function isStale({ filledByXY }, cursor) {
144-
let contents = filledByXY[strXY(cursor)];
145-
return contents === WATER || contents === CLAY;
131+
function fillRight(data, cursor, contents) {
132+
let offset = 1;
133+
while (true) {
134+
let cursorOffset = { ...cursor, x: cursor.x + offset };
135+
if (isClay(data, cursorOffset)) return;
136+
fill(data, cursorOffset, contents);
137+
offset++;
138+
}
146139
}
147140

148-
function isWall({ filledByXY }, cursor) {
149-
return filledByXY[strXY(cursor)] === CLAY;
141+
function getContents(data, cursor) {
142+
return data.filledByXY[strXY(cursor)];
150143
}
151144

152-
function fill({ filledByXY }, cursor, contents) {
153-
//console.log("fill", cursor, contents);
154-
filledByXY[strXY(cursor)] = contents;
145+
function fill(data, cursor, contents) {
146+
data.filledByXY[strXY(cursor)] = contents;
155147
}
156148

157149
function strXY({ x, y }) {
@@ -165,14 +157,34 @@ function parseLineContents(var1, start1, end1, var2, start2, end2) {
165157
return contents;
166158
}
167159

168-
function printData(data, minX, maxX, minY, maxY) {
160+
function printData(data) {
161+
let boundaries = Object.keys(data.filledByXY)
162+
.map(xy => xy.split(",").map(Number))
163+
.reduce(
164+
(acc, [x, y]) => {
165+
acc.minX = Math.min(acc.minX, x);
166+
acc.maxX = Math.max(acc.maxX, x);
167+
acc.minY = Math.min(acc.minY, y);
168+
acc.maxY = Math.max(acc.maxY, y);
169+
return acc;
170+
},
171+
{
172+
minX: Infinity,
173+
maxX: -Infinity,
174+
minY: Infinity,
175+
maxY: -Infinity
176+
}
177+
);
178+
169179
let str = "";
170-
for (let yi = minY; yi <= maxY; yi++) {
171-
for (let xi = minX; xi <= maxX; xi++) {
172-
str += data.filledByXY[strXY({ x: xi, y: yi })] || ".";
180+
for (let yi = boundaries.minY; yi <= boundaries.maxY; yi++) {
181+
for (let xi = boundaries.minX; xi <= boundaries.maxX; xi++) {
182+
str += getContents(data, { x: xi, y: yi }) || ".";
173183
}
174184
str += "\n";
175185
}
186+
187+
console.log(boundaries);
176188
console.log(str);
177189
}
178190

0 commit comments

Comments
 (0)