Advent of Code 2022 - Day 14: Regolith Reservoir Solution
Move and tackle obstaclesPart 1
Keep moving in a direction before switching to others. Order of direction: down, down-left, down-right.
1const dirs = [2 [0, 1], // down3 [-1, 1], // down left4 [1, 1], // down right5]67for (let [dx, dy] of dirs) {8 const [newX, newY] = [x + dx, y + dy]9 if (!obstacles.has(coordToStr([newX, newY]))) {10 return drop([newX, newY])11 }12}
When could not move, produce new sand.
1while (1) {2 const hasNextDrop = drop([500, 0])3 if (!hasNextDrop) break4}56const drop = ([x, y]) => {7 // check abyss89 // moving1011 // comes to rest12 res++13 obstacles.add(coordToStr([x, y]))1415 // signal new spawn16 return true17}
We know when falling into endless void when the movement never stops.
1if (y > maxY) {2 // endless void3 return false4}
Implementation
1const fs = require("fs")23const coordToStr = ([x, y]) => `${x} ${y}`45const readData = () => {6 const data = fs7 .readFileSync("./input", "utf-8")8 .split(/\r?\n/)9 .map(line =>10 line.split(" -> ").map(number => number.split(",").map(Number))11 )1213 let obstacles = new Set()14 let maxY = Number.NEGATIVE_INFINITY1516 for (const line of data) {17 for (let i = 0; i < line.length - 1; i++) {18 let [x1, y1] = line[i]19 let [x2, y2] = line[i + 1]20 ;[x1, x2] = [x1, x2].sort((a, b) => a - b)21 ;[y1, y2] = [y1, y2].sort((a, b) => a - b)2223 for (let x = x1; x <= x2; x++) {24 for (let y = y1; y <= y2; y++) {25 obstacles.add(coordToStr([x, y]))26 maxY = Math.max(maxY, y)27 }28 }29 }30 }3132 return { obstacles, maxY }33}3435const main = () => {36 const { obstacles, maxY } = readData()3738 let res = 03940 const drop = ([x, y]) => {41 if (y > maxY) {42 // endless void43 return false44 }4546 const dirs = [47 [0, 1], // down48 [-1, 1], // down left49 [1, 1], // down right50 ]5152 for (let [dx, dy] of dirs) {53 const [newX, newY] = [x + dx, y + dy]54 if (!obstacles.has(coordToStr([newX, newY]))) {55 return drop([newX, newY])56 }57 }5859 // comes to rest60 res++61 obstacles.add(coordToStr([x, y]))6263 return true64 }6566 while (1) {67 const hasNextDrop = drop([500, 0])68 if (!hasNextDrop) break69 }7071 console.log(res)72}7374main()
Part 2
Like part 1
Stop the spawning when the flow is blocked
1if (obstacles.has(coordToStr([x, y]))) {2 // stop the flow3 return false4}
Stop moving when touch the ground
1if (y < maxY + 1) {2 // if not touch the floor yet, then keep moving3}45// else rest
Implementation
1const fs = require("fs")23const coordToStr = ([x, y]) => `${x} ${y}`45const readData = () => {6 const data = fs7 .readFileSync("./input", "utf-8")8 .split(/\r?\n/)9 .map(line =>10 line.split(" -> ").map(number => number.split(",").map(Number))11 )1213 let obstacles = new Set()14 let maxY = Number.NEGATIVE_INFINITY1516 for (const line of data) {17 for (let i = 0; i < line.length - 1; i++) {18 let [x1, y1] = line[i]19 let [x2, y2] = line[i + 1]20 ;[x1, x2] = [x1, x2].sort((a, b) => a - b)21 ;[y1, y2] = [y1, y2].sort((a, b) => a - b)2223 for (let x = x1; x <= x2; x++) {24 for (let y = y1; y <= y2; y++) {25 obstacles.add(coordToStr([x, y]))26 maxY = Math.max(maxY, y)27 }28 }29 }30 }3132 return { obstacles, maxY }33}3435const main = () => {36 const { obstacles, maxY } = readData()3738 let res = 03940 const drop = ([x, y]) => {41 if (obstacles.has(coordToStr([x, y]))) {42 // stop the flow43 return false44 }4546 const dirs = [47 [0, 1], // down48 [-1, 1], // down left49 [1, 1], // down right50 ]5152 if (y < maxY + 1) {53 // if not touch the floor yet5455 for (let [dx, dy] of dirs) {56 const [newX, newY] = [x + dx, y + dy]57 if (!obstacles.has(coordToStr([newX, newY]))) {58 return drop([newX, newY])59 }60 }61 }6263 // comes to rest64 res++65 obstacles.add(coordToStr([x, y]))6667 return true68 }6970 while (1) {71 const hasNextDrop = drop([500, 0])72 if (!hasNextDrop) break73 }7475 console.log(res)76}7778main()
Rock drawing
I stole the inspiration from a comment
So basically instead of checking whether to go backward or forward, upward or downward, we sort the coordinate to narrow the case to just go forward and downward
1for (const line of data) {2 for (let i = 0; i < line.length - 1; i++) {3 let [x1, y1] = line[i]4 let [x2, y2] = line[i + 1]56 ;[x1, x2] = [x1, x2].sort((a, b) => a - b)7 ;[y1, y2] = [y1, y2].sort((a, b) => a - b)89 for (let x = x1; x <= x2; x++) {10 for (let y = y1; y <= y2; y++) {11 obstacles.add(coordToStr([x, y]))12 }13 }14 }15}
References
Comments
Loading comments...
Tags
adventofcode
hash table
recursion
Apply and earn a $2,500 bonus once you're hired on your first job!
Clients from the Fortune 500 to Silicon Valley startups
Choose your own rate, get paid on time
From hourly, part-time, to full-time positions
Flexible remote working environment
A lot of open JavaScript jobs!!
Fact corner: Referred talent are 5x more likely to pass the Toptal screening process than the average applicant.
Still hesitate? Read HoningJS author's guide on dealing with Toptal interview process.
Next Post
Union of ranges
Previous Post
Handle conditional statements carefully