Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { readFileSync } from 'fs'
- enum Tile {
- Round = 'O',
- Cube = '#',
- Empty = '.',
- }
- type Grid = Tile[][]
- function parse(input: string): Grid {
- return input
- .trim()
- .split('\n')
- .map((line) => line.split('').map((char) => char as Tile))
- }
- function render(grid: Grid) {
- for (let y = 0; y < grid.length; y++) {
- let row = ''
- for (let x = 0; x < grid[0].length; x++) {
- row += String(grid[y][x])
- }
- console.log(row)
- }
- console.log('----------------------------------------')
- }
- function fullyTilt(
- grid: Grid,
- direction: 'north' | 'south' | 'east' | 'west',
- ): Grid {
- switch (direction) {
- case 'north':
- return applyUntilZero(grid, tiltNorth)
- case 'south':
- return applyUntilZero(grid, tiltSouth)
- case 'west':
- return applyUntilZero(grid, tiltWest)
- case 'east':
- return applyUntilZero(grid, tiltEast)
- }
- }
- // Returns the number of round rocks that moved north one cell after one round of simulation.
- function tiltNorth(grid: Grid): number {
- let count = 0
- for (let y = 1; y < grid.length; y++) {
- for (let x = 0; x < grid[0].length; x++) {
- if (grid[y][x] === Tile.Round && grid[y - 1][x] === Tile.Empty) {
- grid[y - 1][x] = Tile.Round
- grid[y][x] = Tile.Empty
- count++
- }
- }
- }
- return count
- }
- function tiltSouth(grid: Grid): number {
- let count = 0
- for (let y = grid.length - 2; y >= 0; y--) {
- for (let x = 0; x < grid[0].length; x++) {
- if (grid[y][x] === Tile.Round && grid[y + 1][x] === Tile.Empty) {
- grid[y + 1][x] = Tile.Round
- grid[y][x] = Tile.Empty
- count++
- }
- }
- }
- return count
- }
- function tiltWest(grid: Grid): number {
- let count = 0
- for (let x = 1; x < grid[0].length; x++) {
- for (let y = 0; y < grid.length; y++) {
- if (grid[y][x] === Tile.Round && grid[y][x - 1] === Tile.Empty) {
- grid[y][x - 1] = Tile.Round
- grid[y][x] = Tile.Empty
- count++
- }
- }
- }
- return count
- }
- function tiltEast(grid: Grid): number {
- let count = 0
- for (let x = grid[0].length - 2; x >= 0; x--) {
- for (let y = 0; y < grid.length; y++) {
- if (grid[y][x] === Tile.Round && grid[y][x + 1] === Tile.Empty) {
- grid[y][x + 1] = Tile.Round
- grid[y][x] = Tile.Empty
- count++
- }
- }
- }
- return count
- }
- function applyUntilZero(input: Grid, fn: (grid: Grid) => number): Grid {
- let result = 0
- while ((result = fn(input)) !== 0) {}
- return input
- }
- function calcWeight(grid: Grid): number {
- let total = 0
- for (let y = 0; y < grid.length; y++) {
- let weight = grid.length - y
- for (let x = 0; x < grid[0].length; x++) {
- if (grid[y][x] === Tile.Round) {
- total += weight
- }
- }
- }
- return total
- }
- function part1(input: string): number {
- const grid = parse(input)
- render(grid)
- let moved = 0
- while ((moved = tiltNorth(grid)) > 0) {}
- return calcWeight(grid)
- }
- function part2(input: string): number {
- const grid = parse(input)
- const seen = new Map<string, number>() // grid -> loop first seen
- let cycling = false
- const end = 1_000_000_000
- for (let i = 0; i < end; i++) {
- fullyTilt(grid, 'north')
- fullyTilt(grid, 'west')
- fullyTilt(grid, 'south')
- fullyTilt(grid, 'east')
- const key = String(grid)
- if (!cycling && seen.has(key)) {
- const cycleStart = seen.get(key)!
- const period = i - cycleStart
- i = end - ((end - cycleStart) % period)
- cycling = true
- }
- seen.set(key, i)
- }
- return calcWeight(grid)
- }
- let input = `O....#....
- O.OO#....#
- .....##...
- OO.#O....O
- .O.....O#.
- O.#..O.#.#
- ..O..#O..O
- .......O..
- #....###..
- #OO..#....`
- input = readFileSync('day14.txt', { encoding: 'utf8' })
- console.log('part 1:', part1(input))
- console.log('part 2:', part2(input))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement