Skip to content

Instantly share code, notes, and snippets.

@ZeikJT
Last active February 5, 2023 19:11
Show Gist options
  • Save ZeikJT/4cf0de1d18539e3ee310d9d0b577c7aa to your computer and use it in GitHub Desktop.
Save ZeikJT/4cf0de1d18539e3ee310d9d0b577c7aa to your computer and use it in GitHub Desktop.
Advent of Code 2022
function getElfCalories(str) {
return str.trim().split('\n').reduce((arr, val) => {
if (val === '') {
arr.push(0)
} else {
const maxIndex = arr.length - 1
arr[maxIndex] = arr[maxIndex] + Number(val)
}
return arr
}, [0])
}
function adventOfCode2022_Day01_Part1(str) {
return Math.max(...getElfCalories(str))
}
function adventOfCode2022_Day01_Part2(str) {
return getElfCalories(str).sort((a,b) => a > b ? 1 : a < b ? -1 : 0).slice(-3).reduce((total, val) =>(total + val, 0)
}
const ROCK_VALUE = 1
const PAPER_VALUE = 2
const SCISSORS_VALUE = 3
const LOSE_VALUE = 0
const TIE_VALUE = 3
const WIN_VALUE = 6
function getRPSValues(str) {
return str.trim().split('\n').map((line) => line.split(' '))
}
function adventOfCode2022_Day02_Part1(str) {
const outcomeValueMap = {
A: {
X: TIE_VALUE,
Y: WIN_VALUE,
Z: LOSE_VALUE,
},
B: {
X: LOSE_VALUE,
Y: TIE_VALUE,
Z: WIN_VALUE,
},
C: {
X: WIN_VALUE,
Y: LOSE_VALUE,
Z: TIE_VALUE,
},
}
const value = {
X: ROCK_VALUE,
Y: PAPER_VALUE,
Z: SCISSORS_VALUE,
}
return getRPSValues(str).reduce((total, [opponent, self]) => {
return total + value[self] + outcomeValueMap[opponent][self]
}, 0)
}
function adventOfCode2022_Day02_Part2(str) {
const choiceValueMap = {
A: {
X: SCISSORS_VALUE,
Y: ROCK_VALUE,
Z: PAPER_VALUE,
},
B: {
X: ROCK_VALUE,
Y: PAPER_VALUE,
Z: SCISSORS_VALUE,
},
C: {
X: PAPER_VALUE,
Y: SCISSORS_VALUE,
Z: ROCK_VALUE,
},
}
const outcomeValue = {
X: LOSE_VALUE,
Y: TIE_VALUE,
Z: WIN_VALUE,
}
return getRPSValues(str).reduce((total, [opponent, self]) => {
return total + choiceValueMap[opponent][self] + outcomeValue[self]
}, 0)
}
function getLines(str) {
return str.trim().split('\n')
}
function getLetterValue(letter) {
const charCode = letter.charCodeAt(0)
if (charCode >= 97) {
// a-z
return charCode - 96
}
// A-Z
return charCode - 38
}
function adventOfCode2022_Day03_Part1(str) {
return getLines(str).map((line) => {
const len = line.length
return [line.slice(0, len / 2), line.slice(len / 2)]
}).reduce((total, [left, right]) => {
for (const letter of left) {
if (right.includes(letter)) {
return total + getLetterValue(letter)
}
}
// Shouldn't happen.
return total
}, 0)
}
function adventOfCode2022_Day03_Part2(str) {
return getLines(str).reduce((arr, line) => {
let lines = arr[arr.length - 1]
if (lines.length === 3) {
lines = [line]
arr.push(lines)
} else {
lines.push(line)
}
return arr
}, [[]]).reduce((total, [line1, line2, line3]) => {
for (const letter of line1) {
if (line2.includes(letter) && line3.includes(letter)) {
return total + getLetterValue(letter)
}
}
// Shouldn't happen.
return total
}, 0)
}
function getLines(str) {
return str.trim().split('\n').map((line) => line.split(',').map((range) => range.split('-').map(Number)))
}
function adventOfCode2022_Day04_Part1(str) {
return getLines(str).reduce((total, [[start1, end1], [start2, end2]]) => {
const startMin = Math.min(start1, start2)
const endMax = Math.max(end1, end2)
if ((startMin === start1 && endMax === end1) || (startMin === start2 && endMax === end2)) {
return total + 1
}
return total
}, 0)
}
function adventOfCode2022_Day04_Part2(str) {
return getLines(str).reduce((total, [[start1, end1], [start2, end2]]) => {
if ((start1 >= start2 && start1 <= end2) || (end1 >= start2 && end1 <= end2) || (start2 >= start1 && start2 <= end1) || (end2 >= start1 && end2 <= end1)) {
return total + 1
}
return total
}, 0)
}
function getData(str) {
const lines = str.split('\n')
const columns = (lines[0].length + 1) / 4
const data = new Array(columns).fill(0).map(() => [])
const separator = lines.findIndex((line) => line.startsWith(' 1 '))
for (let i = 0; i < separator; i++) {
for (let j = 0; j < columns; j++) {
const char = lines[i][(j * 4) + 1]
if (char !== ' ') {
data[j].unshift(char)
}
}
}
return {lines, columns, data, separator}
}
function getMoveData(line) {
return /move (\d+) from (\d+) to (\d+)/.exec(line).slice(1).map((n) => Number.parseInt(n))
}
function adventOfCode2022_Day05_Part1(str) {
const {lines, columns, data, separator} = getData(str)
for (let i = separator + 2; i < lines.length; i++) {
if (!lines[i].trim()) {continue}
const [count, from, to] = getMoveData(lines[i])
for (let j = 0; j < count && data[from - 1].length; j++) {
data[to - 1].push(data[from - 1].pop())
}
}
return data.map((column) => column.pop()).join('')
}
function adventOfCode2022_Day05_Part2(str) {
const {lines, columns, data, separator} = getData(str)
for (let i = separator + 2; i < lines.length; i++) {
if (!lines[i].trim()) {continue}
const [count, from, to] = getMoveData(lines[i])
data[to - 1].push(...data[from - 1].splice(count * -1, count))
}
return data.map((column) => column.pop()).join('')
}
function findUniqueStringPosition(str, length) {
const seenSet = new Set
for (let i = length - 1; i < str.length; i++) {
seenSet.clear()
for (let j = i - (length - 1); j <= i; j++) {
seenSet.add(str[j])
}
if (seenSet.size === length) {
return i + 1
}
}
}
function adventOfCode2022_Day06_Part1(str) {
return findUniqueStringPosition(str, 4)
}
function adventOfCode2022_Day06_Part2(str) {
return findUniqueStringPosition(str, 14)
}
class File {
constructor(name, parentFolder = null, size = 0) {
this.name = name
this.parentFolder = parentFolder
this.size = size
}
}
class Folder extends File {
constructor(...args) {
super(...args)
this.children = new Map()
}
createSubfolder(name, parentFolder) {
this.children.set(name, new Folder(name, parentFolder))
}
createFile(name, size) {
this.children.set(name, new File(name, this, size))
this.addFileSize(size)
}
addFileSize(size) {
this.size += size
this.parentFolder?.addFileSize(size)
}
}
function buildFileSystem(str, includeFiles = false) {
let lsState = false
const root = new Folder('root')
let currentFolder = root
for (const line of str.trim().split('\n')) {
if (line.startsWith('$ cd ')) {
lsState = false
if (line === '$ cd /') {
currentFolder = root
} else if (line === '$ cd ..') {
currentFolder = currentFolder.parentFolder
} else {
currentFolder = currentFolder.children.get(line.substring(5))
if (!currentFolder) {
throw new Error('Subfolder not found')
}
}
} else if (line.startsWith('$ ls')) {
lsState = true
} else if (lsState) {
if (line.startsWith('dir ')) {
currentFolder.createSubfolder(line.substring(4), currentFolder)
} else {
const match = /^(?<size>\d+)\s(?<name>[\w\.]+)$/.exec(line)
if (!match) {
throw new Error('Unexpected line, expected file format')
}
const fileSize = Number.parseInt(match.groups.size)
if (includeFiles) {
currentFolder.createFile(match.groups.name, fileSize)
} else {
currentFolder.addFileSize(fileSize)
}
}
} else {
throw new Error('Unknown line and state combo')
}
}
return root
}
function adventOfCode2022_Day07_Part1(str) {
const fileSystem = buildFileSystem(str)
function getTotalSubfolderSizeSmallerThan(root, maxSize) {
return Array.from(root.children.values())
.reduce((totalSize, folder) => {
if (folder.size <= maxSize) {
totalSize += folder.size
}
return totalSize + getTotalSubfolderSizeSmallerThan(folder, maxSize)
}, 0)
}
return getTotalSubfolderSizeSmallerThan(fileSystem, 100000)
}
function adventOfCode2022_Day07_Part2(str) {
const fileSystem = buildFileSystem(str)
const minimumSizeNeeded = 30000000 - (70000000 - fileSystem.size)
function getMinumumFolderSize(root, currentMinimum = root.size) {
for (const folder of root.children.values()) {
if (folder.size > minimumSizeNeeded) {
if (folder.size < currentMinimum) {
currentMinimum = folder.size
}
currentMinimum = getMinumumFolderSize(folder, currentMinimum)
}
}
return currentMinimum
}
return getMinumumFolderSize(fileSystem, fileSystem.size)
}
function adventOfCode2022_Day08_Part1(str) {
const map = str.trim().split('\n')
const length = map[0].length
const height = map.length
let visibleCount = (length + height - 2) * 2
function isVisible(x, y) {
const value = map[y][x]
let visible = true
for (let xl = 0; xl < x; xl++) {
if (map[y][xl] >= value) {
visible = false
break
}
}
if (!visible) {
visible = true
for (let xr = x + 1; xr < length; xr++) {
if (map[y][xr] >= value) {
visible = false
break
}
}
}
if (!visible) {
visible = true
for (let yt = 0; yt < y; yt++) {
if (map[yt][x] >= value) {
visible = false
break
}
}
}
if (!visible) {
visible = true
for (let yb = y + 1; yb < height; yb++) {
if (map[yb][x] >= value) {
visible = false
break
}
}
}
return visible
}
for (let y = 1; y < height - 1; y++) {
for (let x = 1; x < length - 1; x++) {
isVisible(x, y) && visibleCount++
}
}
return visibleCount
}
function adventOfCode2022_Day08_Part2(str) {
const map = str.trim().split('\n')
const length = map[0].length
const height = map.length
let highestScore = 0
function getScore(x, y) {
const value = map[y][x]
let score = 1
for (let xl = x - 1; xl >= 0; xl--) {
if (xl === 0 || map[y][xl] >= value) {
score *= x - xl
break
}
}
for (let xr = x + 1; xr < length; xr++) {
if (xr === length - 1 || map[y][xr] >= value) {
score *= xr - x
break
}
}
for (let yt = y - 1; yt >= 0; yt--) {
if (yt === 0 || map[yt][x] >= value) {
score *= y - yt
break
}
}
for (let yb = y + 1; yb < height; yb++) {
if (yb === height - 1 || map[yb][x] >= value) {
score *= yb - y
break
}
}
return score
}
for (let y = 1; y < height - 1; y++) {
for (let x = 1; x < length - 1; x++) {
const score = getScore(x, y)
if (score > highestScore) {
highestScore = score
}
}
}
return highestScore
}
class Map {
constructor(segmentCount = 2) {
this.map = [[1]]
this.count = 1
this.width = 1
this.height = 1
this.rope = new Array(segmentCount).fill(0).map(() => ({x: 0, y: 0}))
this.head = this.rope[0]
this.segments = this.rope.filter((e, index) => index !== 0)
this.tail = this.rope[segmentCount - 1]
}
extendMap(dir, size) {
if (size <= 0) {
return
}
if (dir === 'L' || dir === 'R') {
this.width += size
if (dir === 'L') {
for (const segment of this.rope) {
segment.x += size
}
}
for (const row of this.map) {
const newColumns = new Array(size).fill(0)
if (dir === 'L') {
row.splice(0, 0, ...newColumns)
} else {
row.push(...newColumns)
}
}
} else if (dir === 'U' || dir === 'D') {
this.height += size
if (dir === 'U') {
for (const segment of this.rope) {
segment.y += size
}
}
const newRows = new Array(size).fill(0).map(() => new Array(this.width).fill(0))
if (dir === 'U') {
this.map.splice(0, 0, ...newRows)
} else {
this.map.push(...newRows)
}
}
}
maybeRepositionSegments() {
for (let i = 1; i < this.rope.length; i++) {
const prev = this.rope[i - 1]
const next = this.rope[i]
const prevRelX = prev.x - next.x
const prevRelY = prev.y - next.y
if (Math.abs(prevRelX) <= 1 && Math.abs(prevRelY) <= 1) {
continue
}
next.x += Math.sign(prevRelX)
next.y += Math.sign(prevRelY)
if (next === this.tail && !this.map[next.y][next.x]) {
this.map[next.y][next.x] = 1
this.count += 1
}
}
}
moveHead(dir, dist) {
if (dir === 'L') {
this.extendMap(dir, dist - this.head.x)
for (let x = 0; x < dist; x++) {
this.head.x -= 1
this.maybeRepositionSegments()
}
} else if (dir === 'R') {
this.extendMap(dir, dist - ((this.width - 1) - this.head.x))
for (let x = 0; x < dist; x++) {
this.head.x += 1
this.maybeRepositionSegments()
}
} else if (dir === 'U') {
this.extendMap(dir, dist - this.head.y)
for (let y = 0; y < dist; y++) {
this.head.y -= 1
this.maybeRepositionSegments()
}
} else if (dir === 'D') {
this.extendMap(dir, dist - ((this.height - 1) - this.head.y))
for (let y = 0; y < dist; y++) {
this.head.y += 1
this.maybeRepositionSegments()
}
}
}
}
function adventOfCode2022_Day09_Part1(str) {
const map = new Map()
for (const move of str.trim().split('\n')) {
const dir = move[0]
const dist = Number.parseInt(move.substring(2))
map.moveHead(dir, dist)
}
return map.count
}
function adventOfCode2022_Day09_Part2(str) {
const map = new Map(/* head= */ 1 + /* segments= */ 9)
for (const move of str.trim().split('\n')) {
const dir = move[0]
const dist = Number.parseInt(move.substring(2))
map.moveHead(dir, dist)
}
return map.count
}
function adventOfCode2022_Day10_Part1(str) {
const checkpoints = new Array(6).fill(0).map((z, i) => (20 + (40 * i)))
let x = 1
let cycle = 0
let sum = 0
function incrementCycle() {
cycle += 1
if (checkpoints.includes(cycle)) {
sum += (x * cycle)
}
}
for (const command of str.trim().split('\n')) {
if (command === 'noop') {
incrementCycle()
} else if (command.startsWith('addx')) {
incrementCycle()
incrementCycle()
x += Number.parseInt(command.substring(5))
} else {
throw new Error(`Unknown command: ${command}`)
}
}
return sum
}
function adventOfCode2022_Day10_Part2(str) {
let x = 1
let cycle = 0
const screen = []
function incrementCycle() {
const pos = cycle % 40
if (pos === 0) {
screen.push(line = [])
}
if (x - 1 === pos || x === pos || x + 1 === pos) {
line[pos] = '#'
} else {
line[pos] = ' '
}
cycle += 1
}
for (const command of str.trim().split('\n')) {
if (command === 'noop') {
incrementCycle()
} else if (command.startsWith('addx')) {
incrementCycle()
incrementCycle()
x += Number.parseInt(command.substring(5))
} else {
throw new Error(`Unknown command: ${command}`)
}
}
console.log(screen.map((line) => line.join('')).join('\n'))
return screen
}
function parse(str) {
const monkeys = []
let lastMonkey = null
for (const line of str.trim().split('\n')) {
if (line.startsWith('Monkey ')) {
const index = Number.parseInt(line[7])
if (monkeys.length !== index) {
throw new Error(`Unexpected out-of-order index: ${index}`)
}
monkeys[index] = lastMonkey = {
index,
inspected: 0,
}
} else if (line.startsWith(' Starting items: ')) {
lastMonkey.items = line.substring(18).split(', ').map((n) => Number.parseInt(n))
} else if (line.startsWith(' Operation: new = old ')) {
const op = line[23]
let op2 = line.substring(25)
if (/^\d+$/.test(op2)) {
op2 = Number.parseInt(op2)
}
lastMonkey.operation = function(oldValue) {
const b = op2 === 'old' ? oldValue : op2
if (op === '+') {
return oldValue + b
} else if (op === '*') {
return oldValue * b
}
throw new Error(`Unknown operation: ${op}`)
}
} else if (line.startsWith(' Test: divisible by ')) {
lastMonkey.testDivisibleBy = Number.parseInt(line.substring(21))
} else if (line.startsWith(' If true: throw to monkey ')) {
lastMonkey.ifDivisibleTrue = Number.parseInt(line.substring(29))
} else if (line.startsWith(' If false: throw to monkey ')) {
lastMonkey.ifDivisibleFalse = Number.parseInt(line.substring(30))
} else if (line) {
throw new Error(`Unknown directive: ${line}`)
}
}
return monkeys
}
function getMonkeyBusiness(monkeys, rounds, divide) {
const wrapValue = monkeys.reduce((wrapValue, {testDivisibleBy}) => wrapValue * testDivisibleBy, 1)
for (let round = 0; round < rounds; round++) {
for (const monkey of monkeys) {
if (monkey.items) {
for (const item of monkey.items) {
monkey.inspected += 1
let newValue = monkey.operation(item)
if (divide) {
newValue = Math.floor(newValue / 3)
}
if (newValue > wrapValue) {
newValue %= wrapValue
}
const isDivisible = (newValue % monkey.testDivisibleBy) === 0
monkeys[isDivisible ? monkey.ifDivisibleTrue : monkey.ifDivisibleFalse].items.push(newValue)
}
monkey.items = []
}
}
}
return monkeys
.sort((a, b) => a.inspected > b.inspected ? 1 : -1)
.slice(-2)
.reduce((monkeyBusiness, monkey) => monkeyBusiness * monkey.inspected, 1)
}
function adventOfCode2022_Day11_Part1(str) {
return getMonkeyBusiness(parse(str), 20, true)
}
function adventOfCode2022_Day11_Part2(str) {
return getMonkeyBusiness(parse(str), 10000, false)
}
// Implemented based on Wikipedia pseudocode: https://en.wikipedia.org/wiki/A*_search_algorithm#Pseudocode
// A* finds a path from start to goal.
// h is the heuristic function. h(n) estimates the cost to reach goal from node n.
function A_Star(map, start, goal, h) {
// The set of discovered nodes that may need to be (re-)expanded.
// Initially, only the start node is known.
// This is usually implemented as a min-heap or priority queue rather than a hash-set.
const openSet = new Set([start])
// For node n, cameFrom[n] is the node immediately preceding it on the cheapest path from start
// to n currently known.
const cameFrom = new Map()
// For node n, gScore[n] is the cost of the cheapest path from start to n currently known.
const gScore = new Map([[start, 0]])
// For node n, fScore[n] := gScore[n] + h(n). fScore[n] represents our current best guess as to
// how cheap a path could be from start to finish if it goes through n.
const fScore = new Map([[start, h(goal, start)]])
while (openSet.size) {
// This operation can occur in O(Log(N)) time if openSet is a min-heap or a priority queue
const current = Array.from(openSet).reduce((f, n) => {
const {lowFScore, fNode} = f
const nFScore = fScore.get(n)
if (nFScore < lowFScore) {
return {
fScore: nFScore,
fNode: n,
}
}
return f
})
if (current === goal) {
let c = goal
const total_path = [c]
while (cameFrom.has(c)) {
c = cameFrom.get(c)
total_path.unshift(c)
}
return total_path
}
openSet.delete(current)
for (const neighbor of current.n) {
// d(current,neighbor) is the weight of the edge from current to neighbor
// tentative_gScore is the distance from start to the neighbor through current
const tentative_gScore = gScore.get(current) + 1
if (tentative_gScore < (gScore.get(neighbor) ?? Number.POSITIVE_INFINITY)) {
// This path to neighbor is better than any previous one. Record it!
cameFrom.set(neighbor, current)
gScore.set(neighbor, tentative_gScore)
fScore.set(neighbor, tentative_gScore + h(goal, neighbor))
openSet.add(neighbor)
}
}
}
// Open set is empty but goal was never reached
throw new Error('Goal unreachable')
}
function parseIntoMap(str) {
const min = 'a'.charCodeAt(0)
let s = null
let e = null
const map = str.trim().split('\n').map((line, y) => line.split('').map((letter, x) => {
const node = {x, y, h: 0, n: []}
if (letter === 'S') {
return s = node
}
if (letter === 'E') {
return e = node
}
node.h = letter.charCodeAt(0) - min
return node
}))
for (const row of map) {
for (const cell of row) {
for (const [xOff, yOff] of [[-1, 0], [1, 0], [0, -1], [0, 1]]) {
const neighbor = map[yOff + cell.y]?.[xOff + cell.x]
if (neighbor) {
if (cell.h >= neighbor.h - 1) {
cell.n.push(neighbor)
}
}
}
}
}
return {
s,
e,
map,
}
}
function distance(e, n) {
return Math.abs(e.x - n.x) + Math.abs(e.y - n.y)
}
function adventOfCode2022_Day12_Part1(str) {
const {s, e, map} = parseIntoMap(str)
const path = A_Star(map, s, e, distance)
// return map.map((row) => {
// return row.map((n) => {
// return path.includes(n) ? 'X' : ' '
// }).join('')
// }).join('\n')
return path.length - 1
}
function adventOfCode2022_Day12_Part2(str) {
const {e, map} = parseIntoMap(str)
return map.flat().filter((n) => n.h === 0 && n !== e).reduce((prevData, next) => {
try {
const aStar = A_Star(map, next, e, distance)
if (aStar.length < prevData.aStar.length) {
return {
aStar,
n: next,
}
}
} catch {}
return prevData
}, {aStar: {length: Number.POSITIVE_INFINITY}, n: null}).aStar.length - 1
}
function isInOrder(left, right) {
for (let i = 0; i < left.length && i < right.length; i++) {
const l = left[i]
const r = right[i]
const lNumber = typeof l === 'number'
const rNumber = typeof r === 'number'
if (lNumber && rNumber) {
if (l !== r) {
return l < r
}
} else {
const result = isInOrder(lNumber ? [l] : l, rNumber ? [r] : r)
if (result !== null) {
return result
}
}
}
if (left.length !== right.length) {
return left.length < right.length
}
return null
}
function parseToLines(str) {
// Could have written a parser, but eh.
return str.trim().split('\n').filter((line) => line).map(JSON.parse)
}
function adventOfCode2022_Day13_Part1(str) {
return parseToLines(str).reduce((pairs, row, i) => {
if ((i & 1) === 0) {
pairs.push([row])
} else {
pairs[pairs.length - 1].push(row)
}
return pairs
}, []).reduce((total, [left, right], index) => {
return total + (isInOrder(left, right) ? index + 1 : 0)
}, 0)
}
function adventOfCode2022_Day13_Part2(str) {
const sortedLines = parseToLines(str).concat([[[2]], [[6]]]).sort((a, b) => isInOrder(a,b) ? -1 : 1)
return (sortedLines.findIndex((arr) => arr.length === 1 && arr[0].length === 1 && arr[0][0] === 2) + 1) *
(sortedLines.findIndex((arr) => arr.length === 1 && arr[0].length === 1 && arr[0][0] === 6) + 1)
}
function parseToMap(str) {
let minX = Number.POSITIVE_INFINITY
let maxX = 0
let minY = Number.POSITIVE_INFINITY
let maxY = 0
const walls = str.trim().split('\n').map((line) => line.split(' -> ').map((point) => point.split(',').map(Number)).map(([x, y]) => ({x, y})))
for (const wall of walls) {
for (const {x, y} of wall) {
if (x < minX) {
minX = x
}
if (x > maxX) {
maxX = x
}
if (y < minY) {
minY = y
}
if (y > maxY) {
maxY = y
}
}
}
const map = new Array(maxY + 2).fill(0).map(() => [])
for (const wall of walls) {
let from = null
for (const to of wall) {
if (from) {
for (let {x, y} = from; x !== to.x || y !== to.y; x += Math.sign(to.x - from.x), y += Math.sign(to.y - from.y)) {
map[y][x] = '#'
}
map[to.y][to.x] = '#'
}
from = to
}
}
return {map, minX, maxX, maxY}
}
function adventOfCode2022_Day14_Part1(str) {
const {map, minX, maxX, maxY} = parseToMap(str)
const sandSpawnX = 500
let sandX = sandSpawnX
let sandY = 0
let sandCount = 1
for (let i = 0; i < 1000000; i++) {
sandY++
if (!map[sandY][sandX]) {
map[sandY - 1][sandX] = undefined
map[sandY][sandX] = 'O'
} else if (!map[sandY][sandX - 1]) {
map[sandY - 1][sandX] = undefined
sandX--
map[sandY][sandX] = 'O'
} else if (!map[sandY][sandX + 1]) {
map[sandY - 1][sandX] = undefined
sandX++
map[sandY][sandX] = 'O'
} else {
sandX = sandSpawnX
sandY = 0
map[sandY][sandX] = 'O'
sandCount++
}
if (sandX < minX || sandX >= maxX || sandY >= maxY) {
break
}
}
return sandCount - 1
}
function adventOfCode2022_Day14_Part2(str) {
const {map, minX, maxX, maxY} = parseToMap(str)
const sandSpawnX = 500
let sandX = sandSpawnX
let sandY = 0
let sandCount = 1
for (let i = 0; i < 1000000000; i++) {
sandY++
if (sandY === maxY + 2) {
sandX = sandSpawnX
sandY = 0
map[sandY][sandX] = 'O'
sandCount++
} else if (!map[sandY][sandX]) {
map[sandY - 1][sandX] = undefined
map[sandY][sandX] = 'O'
} else if (!map[sandY][sandX - 1]) {
map[sandY - 1][sandX] = undefined
sandX--
map[sandY][sandX] = 'O'
} else if (!map[sandY][sandX + 1]) {
map[sandY - 1][sandX] = undefined
sandX++
map[sandY][sandX] = 'O'
} else {
if (sandY === 1) {
break
}
sandX = sandSpawnX
sandY = 0
map[sandY][sandX] = 'O'
sandCount++
}
}
return sandCount
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment