advent-of-code

Entries to advent of code, multiple years
git clone git://git.finwo.net/misc/advent-of-code
Log | Files | Refs

commit d522cbdc3ea411ff6ed51dc2cc5859eeef79d577
parent e7d27a87e980ff7cda7665f5465b74cec156b0b2
Author: finwo <finwo@pm.me>
Date:   Fri, 23 Dec 2022 15:36:41 +0100

2022/22 solution

Diffstat:
A2022/day-22/index.js | 262+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A2022/day-22/sample | 14++++++++++++++
2 files changed, 276 insertions(+), 0 deletions(-)

diff --git a/2022/day-22/index.js b/2022/day-22/index.js @@ -0,0 +1,262 @@ +const fs = require('fs'); + +function drawMap(map) { + for(const row of map) { + for(let i=0; i<row.length; i++) { + process.stdout.write(directionChars[row[i]] || ' '); + } + process.stdout.write('\n'); + } +} + +function mod(n, m) { + return ((n%m)+m)%m; +} + +function move(position, movement) { + return [ + position[0] + movement[0], + position[1] + movement[1], + ]; +} + +// Fetch map +const lines = fs.readFileSync('input', 'utf-8') +// const lines = fs.readFileSync('sample', 'utf-8') + .trimEnd() + .split('\n'); + +// Fetch directions +const path = lines.pop() + .match(/(\d+|L|R)/g) + .map(stmt => isNaN(stmt) ? stmt : parseInt(stmt)) +lines.pop(); + +let mapwidth = lines + .map(line => line.length) + .reduce((r,a) => Math.max(r,a), 0) + +// Map map into something usable +for(let i=0; i<lines.length; i++) { + lines[i] = lines[i] + .split('') + .map(c => ({'.':4,'#':5}[c])); +} + +// Define movements of directions +const directions = [ + [ 1, 0 ], // right + [ 0, 1 ], // down + [ -1, 0 ], // left + [ 0, -1 ], // up +]; +const directionChars = ['>','v','<','^','.','#']; + +// How to wrap for step 1 +function positionStep1(map, position, movement, fallback) { + fallback = fallback || position; + let newpos = [...position]; + let stat = lines[newpos[1]][newpos[0]]; + + // Move until non-undefined + do { + newpos = move(newpos, movement); + newpos[1] = mod(newpos[1], lines.length); + newpos[0] = mod(newpos[0], mapwidth); + stat = lines[newpos[1]][newpos[0]]; + } while('undefined' === typeof stat); + + // Return fallback if blocked + if (stat == 5) return [...fallback]; + // Return new position, as it's available + return newpos; +} + +const Dir = { + left: '-10', + right: '10', + up: '0-1', + down: '01', +}; + +// Cube shape +// A-----B-----C +// | | | +// | a | b | +// | | | +// D-----E-----F +// | | +// | c | +// | | +// D-----G-----F +// | | | +// | d | e | +// | | | +// A-----H-----C +// | | +// | f | +// | | +// B-----C + +// Calculate wrapping method for step 2 +// Splits into 9 surfaces (manual edge wrapping) +const surfaceSize = lines[0].length / 3; +const x=0, y=1; +function positionStep2(map, position, movement) { + let newpos = move(position, movement); + let aDir = movement.join(''); + let newdir = directions.indexOf(movement); + + // AB, a > f + if (position[x] >= 50 && position[x] < 100 && position[y] == 0 && aDir == Dir.up) { + newpos = [0, position[x] - 50 + 150]; + newdir = 0; // right + } + // BC, b > f + if (position[x] >= 100 && position[x] < 150 && position[y] == 0 && aDir == Dir.up) { + newpos = [ position[x] - 100, 199 ]; + newdir = 3; // up + } + // AD, a > d + if (position[x] == 50 && position[y] < 50 && aDir == Dir.left) { + newpos = [ 0, 149 - position[y] ]; + newdir = 0; // right + } + // CF, b > e + if (position[x] == 149 && position[y] < 50 && aDir == Dir.right) { + newpos = [position[x] - 50, 149 - position[y]]; + newdir = 2; // left + } + // EF, b > c + if (position[x] >= 100 && position[y] == 49 && aDir == Dir.down) { + newpos = [99, position[x] - 50]; + newdir = 2; // left + } + // DG, c > d + if (position[x] == 50 && position[y] >= 50 && position[y] < 100 && aDir == Dir.left) { + newpos = [position[y] - 50, 100]; + newdir = 1; // down + } + // EF, c > b + if (position[x] == 99 && position[y] >= 50 && position[y] < 100 && aDir == Dir.right) { + newpos = [position[y] + 50, 49]; + newdir = 3; // up + } + // DG, d > c + if (position[x] < 50 && position[y] == 100 && aDir == Dir.up) { + newpos = [50, position[x] + 50]; + newdir = 0; // right + } + // AD, d > a + if (position[x] == 0 && position[y] >= 100 && position[y] < 150 && aDir == Dir.left) { + newpos = [50, 149 - position[y]]; + newdir = 0; // right + } + // CF, e > b + if (position[x] == 99 && position[y] >= 100 && position[y] < 150 && aDir == Dir.right) { + newpos = [149, 149 - position[y]]; + newdir = 2; // left + } + // CH, e > f + if (position[x] >= 50 && position[x] < 100 && position[y] == 149 && aDir == Dir.down) { + newpos = [49, position[x] + 100]; + newdir = 2; // left + } + // AB, f > a + if (position[x] == 0 && position[y] >= 150 && aDir == Dir.left) { + newpos = [position[y] - 100, 0]; + newdir = 1; // down + } + // CH, f > e + if (position[x] == 49 && position[y] >= 150 && aDir == Dir.right) { + newpos = [position[y] - 100, 149]; + newdir = 3; // up + } + // BC, f > b + if (position[x] < 50 && position[y] == 199 && aDir == Dir.down) { + newpos = [position[x] + 100, 0]; + newdir = 1; // down + } + + // Revert if we ran into a wall + const stat = lines[newpos[y]][newpos[x]]; + if (stat == 5) { + newpos = [...position]; + newdir = directions.indexOf(movement); + } + + return [newpos, newdir]; +} + + + +// Define our character's position +const characters = [ + // { + // pos: [ + // Math.min( + // lines[0].indexOf(4), + // lines[0].indexOf(5), + // ), + // 0, + // ], + // dir: 0, + // mv() { + // this.pos = positionStep1(lines, this.pos, directions[this.dir]); + // } + // }, + { + pos: [ + Math.min( + lines[0].indexOf(4), + lines[0].indexOf(5), + ), + 0, + ], + surface: surfaceSize == 12 ? + [ 2, 0 ] : + [ 1, 0 ], + dir: 0, + mv() { + let [pos,dir] = positionStep2(lines, this.pos, directions[this.dir]); + this.pos = pos; + this.dir = dir; + } + }, +]; + +// Go over the instructions +for(let stmt of path) { + for(const character of characters) { + lines[character.pos[1]][character.pos[0]] = character.dir; + if(isNaN(stmt)) { + const c = stmt == 'R' ? 1 : -1; + character.dir = mod(character.dir + c, directions.length); + lines[character.pos[1]][character.pos[0]] = character.dir; + } else { + // Move along + for(let i=0; i<stmt; i++) { + character.mv(); + lines[character.pos[1]][character.pos[0]] = character.dir; + } + } + } +} + +drawMap(lines); + +// Output characters and their password +for(let character of characters) { + console.log({ character, password: ((character.pos[1]+1)*1000) + ((character.pos[0]+1)*4) + character.dir }); +} + +// let position = [ +// 0 +// ]; +// let direction = 0; + + + + + +// process.stdout.write(input); diff --git a/2022/day-22/sample b/2022/day-22/sample @@ -0,0 +1,14 @@ + ...# + .#.. + #... + .... +...#.......# +........#... +..#....#.... +..........#. + ...#.... + .....#.. + .#...... + ......#. + +10R5L5R10L4R5L5