cleaning up the cube
This commit is contained in:
parent
767070d3e7
commit
fb753ef7bd
416
22/src/index.ts
416
22/src/index.ts
|
@ -29,12 +29,6 @@ type TrailInstructionTurns = typeof InstructionTurn[keyof typeof InstructionTurn
|
|||
type TrailSpace = {
|
||||
type: TrailSpaceTypes
|
||||
point: TrailPoint
|
||||
neighbors: {
|
||||
[TrailDirection.LEFT]?: TrailSpace
|
||||
[TrailDirection.RIGHT]?: TrailSpace
|
||||
[TrailDirection.UP]?: TrailSpace
|
||||
[TrailDirection.DOWN]?: TrailSpace
|
||||
}
|
||||
}
|
||||
|
||||
type TrailPoint = {
|
||||
|
@ -48,16 +42,15 @@ type TrailPosition = {
|
|||
}
|
||||
|
||||
type Trail = {
|
||||
start: TrailSpace
|
||||
at: TrailPosition
|
||||
start: TrailPosition
|
||||
spaces: { [coordinates: string]: TrailSpace }
|
||||
height: number
|
||||
width: number
|
||||
}
|
||||
|
||||
type TrailCube = {
|
||||
size: number
|
||||
indexes: [number, number][]
|
||||
cube: {
|
||||
size: number
|
||||
indexes: [number, number][]
|
||||
edges: TrailSpace[]
|
||||
}
|
||||
}
|
||||
|
||||
type TrailInstruction = {
|
||||
|
@ -75,86 +68,90 @@ type TrailCubeFace = {
|
|||
}
|
||||
|
||||
const TrailCompass = [
|
||||
TrailDirection.UP,
|
||||
TrailDirection.RIGHT,
|
||||
TrailDirection.DOWN,
|
||||
TrailDirection.LEFT,
|
||||
TrailDirection.UP,
|
||||
]
|
||||
|
||||
const matchTrailInstruction = /\d+(R|L)?/g
|
||||
|
||||
function parseTrailAsCube(lines: string[]): {
|
||||
trail: Trail
|
||||
cube: TrailCube
|
||||
} {
|
||||
function getNeighbors(trail: Trail, { x, y }: TrailPoint) {
|
||||
const up = y < 0 ? trail.height - 1 : y - 1
|
||||
const down = y > trail.height - 1 ? 0 : y + 1
|
||||
const left = x < 0 ? trail.width - 1 : x - 1
|
||||
const right = x > trail.width - 1 ? 0 : x + 1
|
||||
|
||||
return {
|
||||
[TrailDirection.DOWN]: { point: { x, y: down }, dir: TrailDirection.DOWN },
|
||||
[TrailDirection.UP]: { point: { x, y: up }, dir: TrailDirection.UP },
|
||||
[TrailDirection.LEFT]: { point: { x: left, y }, dir: TrailDirection.LEFT },
|
||||
[TrailDirection.RIGHT]: { point: { x: right, y }, dir: TrailDirection.RIGHT },
|
||||
}
|
||||
}
|
||||
|
||||
function parseTrail(lines: string[]): Trail {
|
||||
const start = { point: { x: 0, y: 0 }, type: TrailSpaceType.EMPTY, neighbors: {} }
|
||||
const columns: TrailSpace[][] = Array(Math.max(...lines.map((line) => line.length)))
|
||||
.fill('')
|
||||
.map(() => [])
|
||||
const trail: Trail = {
|
||||
at: {
|
||||
start: {
|
||||
space: start,
|
||||
facing: TrailDirection.RIGHT,
|
||||
},
|
||||
start,
|
||||
spaces: {},
|
||||
height: lines.length,
|
||||
width: columns.length,
|
||||
width: lines.reduce((width, line) => Math.max(width, line.length), 0),
|
||||
cube: {
|
||||
size: lines.length,
|
||||
indexes: [],
|
||||
edges: [],
|
||||
},
|
||||
}
|
||||
let minWidth = lines.length
|
||||
let minHeight = columns.length
|
||||
const column = { min: trail.height, max: 0 }
|
||||
|
||||
lines.forEach((line, y) => {
|
||||
const spaces = line.split('') as TrailSpaceTypes[]
|
||||
const row: TrailSpace[] = []
|
||||
const row = { min: trail.width, max: 0 }
|
||||
|
||||
spaces.forEach((space, x) => {
|
||||
if (TrailSpaceType.EMPTY !== space) {
|
||||
const trailSpace: TrailSpace = {
|
||||
point: { x, y },
|
||||
type: space,
|
||||
neighbors: {},
|
||||
}
|
||||
row.push(trailSpace)
|
||||
columns[x].push(trailSpace)
|
||||
|
||||
if (trail.start.space.type === TrailSpaceType.EMPTY) {
|
||||
trail.start.space = trailSpace
|
||||
}
|
||||
|
||||
setSpace(trail, trailSpace)
|
||||
|
||||
row.min = Math.min(row.min, x)
|
||||
row.max = Math.max(row.max, x)
|
||||
column.min = Math.min(column.min, y)
|
||||
column.max = Math.max(column.max, y)
|
||||
}
|
||||
})
|
||||
|
||||
minWidth = Math.min(minWidth, row.length)
|
||||
|
||||
row.forEach((space, index) => {
|
||||
if (index === 0 && y === 0) {
|
||||
trail.start = space
|
||||
trail.at.space = space
|
||||
}
|
||||
if (index !== 0 || index !== row.length - 1) {
|
||||
space.neighbors[TrailDirection.LEFT] = row[index - 1]
|
||||
space.neighbors[TrailDirection.RIGHT] = row[index + 1]
|
||||
}
|
||||
})
|
||||
trail.cube.size = Math.min(trail.cube.size, row.max - row.min + 1)
|
||||
})
|
||||
|
||||
columns.forEach((column) => {
|
||||
minHeight = Math.min(minHeight, column.length)
|
||||
|
||||
column.forEach((space, index) => {
|
||||
if (index !== 0 || index !== column.length - 1) {
|
||||
space.neighbors[TrailDirection.UP] = column[index - 1]
|
||||
space.neighbors[TrailDirection.DOWN] = column[index + 1]
|
||||
}
|
||||
setSpace(trail, space)
|
||||
})
|
||||
})
|
||||
|
||||
if (minHeight === minWidth) {
|
||||
return { trail, cube: foldTrailAsCube(trail, minHeight) }
|
||||
if (trail.cube.size !== Math.min(trail.cube.size, column.max - column.min + 1)) {
|
||||
throw new Error('Not a cube')
|
||||
}
|
||||
|
||||
throw new Error('Trail is not a cube')
|
||||
trail.cube.edges = Object.values(trail.spaces).filter((space) =>
|
||||
Object.values(getNeighbors(trail, space.point)).some(
|
||||
(neighbor) => !getSpace(trail, neighbor.point)
|
||||
)
|
||||
)
|
||||
|
||||
trail.cube.indexes = getFaceIndexes(trail.cube.edges, trail.cube.size)
|
||||
|
||||
return trail
|
||||
}
|
||||
|
||||
const arrayEquals = <T>(index: T[], index2: T[]): boolean =>
|
||||
index.length === index2.length && index.every((value, i) => value === index2[i])
|
||||
const arrayEquals = <T>(one: T[], two: T[]): boolean =>
|
||||
one.length === two.length && one.every((value, i) => value === two[i])
|
||||
|
||||
function getTurnsBeforeRotation(dirs: TrailDirections[]) {
|
||||
return dirs.reduce((foundIndex, _, index) => {
|
||||
|
@ -166,29 +163,27 @@ function getTurnsBeforeRotation(dirs: TrailDirections[]) {
|
|||
}
|
||||
|
||||
function getRotation(dirs: TrailDirections[]) {
|
||||
const isCounterClockwise = dirs.some((_, index) => {
|
||||
const first = TrailCompass.indexOf(dirs[index])
|
||||
const second = TrailCompass.indexOf(dirs[index + 1])
|
||||
if (first === -1 || second === -1) {
|
||||
return false
|
||||
return dirs.reduce((turn, _, index) => {
|
||||
if (index + 1 < dirs.length) {
|
||||
const first = TrailCompass.indexOf(dirs[index])
|
||||
const second = TrailCompass.indexOf(dirs[index + 1])
|
||||
const isCounterClockwise = first - second === 1 || second - first === 3
|
||||
const isClockwise = second - first === 1 || first - second === 3
|
||||
|
||||
if (isClockwise && isCounterClockwise) {
|
||||
return turn
|
||||
} else if (turn === InstructionTurn.COUNTER_CLOCKWISE && isClockwise) {
|
||||
return null
|
||||
} else if (turn === InstructionTurn.CLOCKWISE && isCounterClockwise) {
|
||||
return null
|
||||
} else if (isCounterClockwise) {
|
||||
return InstructionTurn.COUNTER_CLOCKWISE
|
||||
} else if (isClockwise) {
|
||||
return InstructionTurn.CLOCKWISE
|
||||
}
|
||||
}
|
||||
return first - second === 1 || (first === 0 && first - second === -3)
|
||||
})
|
||||
|
||||
const isClockwise = dirs.some((_, index) => {
|
||||
const first = TrailCompass.indexOf(dirs[index])
|
||||
const second = TrailCompass.indexOf(dirs[index + 1])
|
||||
if (first === -1 || second === -1) {
|
||||
return false
|
||||
}
|
||||
return second - first === 1 || (first === 3 && second - first === 3)
|
||||
})
|
||||
|
||||
if (isClockwise === isCounterClockwise) {
|
||||
return null
|
||||
}
|
||||
|
||||
return isClockwise ? InstructionTurn.CLOCKWISE : InstructionTurn.COUNTER_CLOCKWISE
|
||||
return turn
|
||||
}, null as TrailInstructionTurns | null)
|
||||
}
|
||||
|
||||
function isFlipped(dirs: TrailDirections[]) {
|
||||
|
@ -198,9 +193,9 @@ function isFlipped(dirs: TrailDirections[]) {
|
|||
})
|
||||
}
|
||||
|
||||
function findFaceFor(
|
||||
function findNextFaceFor(
|
||||
trail: Trail,
|
||||
index: [number, number],
|
||||
allIndexes: [number, number][],
|
||||
dir: TrailDirections
|
||||
): TrailCubeFace {
|
||||
const queue: TrailCubeFace[] = [{ index, folds: [] }]
|
||||
|
@ -212,7 +207,11 @@ function findFaceFor(
|
|||
const turnDir = getRotation(faceMap.folds)
|
||||
const turnTimes = getTurnsBeforeRotation(faceMap.folds) + 1
|
||||
|
||||
if (lastFold === dir || (isFlipped(faceMap.folds) && getOppositeDirection(lastFold) === dir)) {
|
||||
if (
|
||||
lastFold === dir ||
|
||||
(isFlipped(faceMap.folds) && getOppositeDirection(lastFold) === dir) ||
|
||||
visited.length === 5
|
||||
) {
|
||||
if (turnDir) {
|
||||
faceMap.rotation = {
|
||||
turn: turnDir,
|
||||
|
@ -224,19 +223,18 @@ function findFaceFor(
|
|||
|
||||
const x = faceMap.index[0]
|
||||
const y = faceMap.index[1]
|
||||
const neighbors = [
|
||||
[x, y + 1, TrailDirection.DOWN],
|
||||
[x, y - 1, TrailDirection.UP],
|
||||
[x - 1, y, TrailDirection.LEFT],
|
||||
[x + 1, y, TrailDirection.RIGHT],
|
||||
] as [number, number, TrailDirections][]
|
||||
|
||||
neighbors
|
||||
.map(([x, y, fold]) => {
|
||||
const turnFold = turnDir ? turnDirectionTimes(fold, turnDir, turnTimes) : fold
|
||||
return { index: [x, y], folds: [...faceMap.folds, turnFold] } as TrailCubeFace
|
||||
Object.values(getNeighbors(trail, { x, y }))
|
||||
.map((neighbor) => {
|
||||
const turnFold = turnDir
|
||||
? turnDirectionTimes(neighbor.dir, turnDir, turnTimes)
|
||||
: neighbor.dir
|
||||
return {
|
||||
index: [neighbor.point.x, neighbor.point.y],
|
||||
folds: [...faceMap.folds, turnFold],
|
||||
} as TrailCubeFace
|
||||
})
|
||||
.filter((neighbor) => allIndexes.find((index) => arrayEquals(index, neighbor.index)))
|
||||
.filter((neighbor) => trail.cube.indexes.find((index) => arrayEquals(index, neighbor.index)))
|
||||
.filter((neighbor) => !visited.find((visit) => arrayEquals(visit, neighbor.index)))
|
||||
.forEach((neighbor) => {
|
||||
queue.push(neighbor)
|
||||
|
@ -272,117 +270,43 @@ function getFaceIndexes(edges: TrailSpace[], size: number): [number, number][] {
|
|||
}, [] as [number, number][])
|
||||
}
|
||||
|
||||
function foldTrailAsCube(trail: Trail, size: number): TrailCube {
|
||||
const edges = Object.values(trail.spaces).filter((space) =>
|
||||
Object.values(space.neighbors).some((neighbor) => neighbor === undefined)
|
||||
)
|
||||
|
||||
const cube: TrailCube = {
|
||||
size,
|
||||
indexes: getFaceIndexes(edges, size),
|
||||
function findFoldedEdgeFor(
|
||||
trail: Trail,
|
||||
fromEdge: TrailSpace,
|
||||
fromDirection: TrailDirections
|
||||
): TrailSpace {
|
||||
const fromIndex = getFaceIndex(fromEdge, trail.cube.size)
|
||||
const toFaceMap = findNextFaceFor(trail, fromIndex, fromDirection)
|
||||
if (!toFaceMap) {
|
||||
throw new Error(`Could not find edge for ${fromEdge}`)
|
||||
}
|
||||
|
||||
edges.forEach((fromEdge) => {
|
||||
const fromIndex = getFaceIndex(fromEdge, cube.size)
|
||||
|
||||
TrailCompass.filter((fromDirection) => fromEdge.neighbors[fromDirection] === undefined).forEach(
|
||||
(fromDirection) => {
|
||||
const toFaceMap = findFaceFor(fromIndex, cube.indexes, fromDirection)
|
||||
if (!toFaceMap) {
|
||||
throw new Error(`Could not find edge for ${fromEdge}`)
|
||||
}
|
||||
const fromMod = getMod(fromEdge, fromDirection, cube.size)
|
||||
const oppositeDir = getOppositeDirection(fromDirection)
|
||||
const oppositeTurn = getOppositeTurn(toFaceMap.rotation?.turn || InstructionTurn.CLOCKWISE)
|
||||
const toDirection = toFaceMap.rotation?.turn
|
||||
? turnDirectionTimes(oppositeDir, oppositeTurn, toFaceMap.rotation.times)
|
||||
: fromDirection
|
||||
|
||||
const toEdge = edges
|
||||
.filter((edge) => arrayEquals(getFaceIndex(edge, cube.size), toFaceMap.index))
|
||||
.filter((edge) => edge.neighbors[toDirection] === undefined)
|
||||
.find((edge) => {
|
||||
return (
|
||||
fromMod ===
|
||||
getMod(
|
||||
edge,
|
||||
toDirection,
|
||||
cube.size,
|
||||
toFaceMap.rotation?.turn,
|
||||
toFaceMap.rotation?.times
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
if (!toEdge) {
|
||||
throw new Error(`Could not connect edge for ${JSON.stringify(fromEdge.point)}`)
|
||||
}
|
||||
|
||||
fromEdge.neighbors[fromDirection] = toEdge
|
||||
toEdge.neighbors[toDirection] = fromEdge
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
return cube
|
||||
}
|
||||
|
||||
function parseTrail(lines: string[]): Trail {
|
||||
const start = {
|
||||
point: { x: 0, y: 0 },
|
||||
type: TrailSpaceType.EMPTY,
|
||||
neighbors: {},
|
||||
edge: false,
|
||||
}
|
||||
const columns: TrailSpace[][] = Array(Math.max(...lines.map((line) => line.length)))
|
||||
.fill('')
|
||||
.map(() => [])
|
||||
const trail: Trail = {
|
||||
at: {
|
||||
space: start,
|
||||
facing: TrailDirection.RIGHT,
|
||||
},
|
||||
start,
|
||||
spaces: {},
|
||||
height: lines.length,
|
||||
width: columns.length,
|
||||
}
|
||||
|
||||
lines.forEach((line, y) => {
|
||||
const spaces = line.split('') as TrailSpaceTypes[]
|
||||
const row: TrailSpace[] = []
|
||||
|
||||
spaces.forEach((space, x) => {
|
||||
if (TrailSpaceType.EMPTY !== space) {
|
||||
const trailSpace: TrailSpace = {
|
||||
point: { x, y },
|
||||
type: space,
|
||||
neighbors: {},
|
||||
}
|
||||
row.push(trailSpace)
|
||||
columns[x].push(trailSpace)
|
||||
}
|
||||
const oppositeDir = getOppositeDirection(fromDirection)
|
||||
const oppositeTurn = getOppositeTurn(toFaceMap.rotation?.turn || InstructionTurn.CLOCKWISE)
|
||||
const toDirection = toFaceMap.rotation?.turn
|
||||
? turnDirectionTimes(oppositeDir, oppositeTurn, toFaceMap.rotation.times)
|
||||
: fromDirection
|
||||
const fromMod = getMod(fromEdge, fromDirection, trail.cube.size)
|
||||
const toEdge = trail.cube.edges
|
||||
.filter((edge) => arrayEquals(getFaceIndex(edge, trail.cube.size), toFaceMap.index))
|
||||
.filter((edge) => !getSpace(trail, getNeighbors(trail, edge.point)[toDirection].point))
|
||||
.find((edge) => {
|
||||
return (
|
||||
fromMod ===
|
||||
getMod(
|
||||
edge,
|
||||
toDirection,
|
||||
trail.cube.size,
|
||||
toFaceMap.rotation?.turn,
|
||||
toFaceMap.rotation?.times
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
row.forEach((space, index) => {
|
||||
if (index === 0 && y === 0) {
|
||||
trail.start = space
|
||||
trail.at.space = space
|
||||
}
|
||||
space.neighbors[TrailDirection.LEFT] = row[index === 0 ? row.length - 1 : index - 1]
|
||||
space.neighbors[TrailDirection.RIGHT] = row[index === row.length - 1 ? 0 : index + 1]
|
||||
})
|
||||
})
|
||||
if (!toEdge) {
|
||||
throw new Error(`Could not connect edge for ${JSON.stringify(fromEdge.point)}`)
|
||||
}
|
||||
|
||||
columns.forEach((column) => {
|
||||
column.forEach((space, index) => {
|
||||
space.neighbors[TrailDirection.UP] = column[index === 0 ? column.length - 1 : index - 1]
|
||||
space.neighbors[TrailDirection.DOWN] = column[index === column.length - 1 ? 0 : index + 1]
|
||||
setSpace(trail, space)
|
||||
})
|
||||
})
|
||||
|
||||
return trail
|
||||
return toEdge
|
||||
}
|
||||
|
||||
function parseInstructions(line: string): TrailInstruction[] {
|
||||
|
@ -412,27 +336,21 @@ function turnDirectionTimes(
|
|||
}
|
||||
|
||||
function turnDirection(facing: TrailDirections, dir: TrailInstructionTurns): TrailDirections {
|
||||
const compass = [
|
||||
TrailDirection.UP,
|
||||
TrailDirection.RIGHT,
|
||||
TrailDirection.DOWN,
|
||||
TrailDirection.LEFT,
|
||||
]
|
||||
const compass = TrailCompass
|
||||
const index = compass.indexOf(facing)
|
||||
const oppositeIndex = InstructionTurn.CLOCKWISE === dir ? index + 1 : index - 1
|
||||
|
||||
if (oppositeIndex < 0) {
|
||||
return compass[compass.length - 1]
|
||||
} else if (oppositeIndex > compass.length - 1) {
|
||||
return compass[oppositeIndex % compass.length]
|
||||
}
|
||||
return compass[oppositeIndex]
|
||||
return compass[oppositeIndex % compass.length]
|
||||
}
|
||||
|
||||
function positionMove(
|
||||
trail: Trail,
|
||||
position: TrailPosition,
|
||||
instruction: TrailInstruction,
|
||||
cube?: TrailCube
|
||||
asCube = false
|
||||
): TrailPosition {
|
||||
let dir = position.facing
|
||||
let at = position.space
|
||||
|
@ -440,18 +358,31 @@ function positionMove(
|
|||
|
||||
for (let i = 0; i < instruction.distance; i++) {
|
||||
at.type = TrailSpaceType[dir]
|
||||
next = at.neighbors[dir]
|
||||
|
||||
let neighbor = getNeighbors(trail, at.point)[dir]
|
||||
next = getSpace(trail, neighbor.point)
|
||||
|
||||
if (!next) {
|
||||
if (asCube) {
|
||||
next = findFoldedEdgeFor(trail, at, dir)
|
||||
} else {
|
||||
while (!next) {
|
||||
neighbor = getNeighbors(trail, neighbor.point)[dir]
|
||||
next = getSpace(trail, neighbor.point)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!next) {
|
||||
throw new Error(`No next space for ${at.point.y},${at.point.y} in direction ${dir}`)
|
||||
}
|
||||
|
||||
if (next.type !== TrailSpaceType.WALL) {
|
||||
if (cube) {
|
||||
const atIndex = getFaceIndex(at, cube.size)
|
||||
const nextIndex = getFaceIndex(next, cube.size)
|
||||
if (asCube) {
|
||||
const atIndex = getFaceIndex(at, trail.cube.size)
|
||||
const nextIndex = getFaceIndex(next, trail.cube.size)
|
||||
if (!arrayEquals(atIndex, nextIndex)) {
|
||||
const face = findFaceFor(atIndex, cube.indexes, dir)
|
||||
const face = findNextFaceFor(trail, atIndex, dir)
|
||||
if (face.rotation) {
|
||||
dir = turnDirectionTimes(dir, getOppositeTurn(face.rotation.turn), face.rotation.times)
|
||||
}
|
||||
|
@ -494,8 +425,8 @@ function getMod(
|
|||
case TrailDirection.DOWN:
|
||||
if (
|
||||
rotations === 0 ||
|
||||
(turn && turn === InstructionTurn.CLOCKWISE && rotations === 4) ||
|
||||
(turn && turn === InstructionTurn.CLOCKWISE && rotations === 1)
|
||||
(turn && turn === InstructionTurn.CLOCKWISE && (rotations === 4 || rotations === 1)) ||
|
||||
(turn && turn === InstructionTurn.COUNTER_CLOCKWISE && (rotations === 3 || rotations === 4))
|
||||
) {
|
||||
return space.point.x % size
|
||||
} else {
|
||||
|
@ -505,8 +436,8 @@ function getMod(
|
|||
case TrailDirection.RIGHT:
|
||||
if (
|
||||
rotations === 0 ||
|
||||
(turn && turn === InstructionTurn.CLOCKWISE && rotations === 4) ||
|
||||
(turn && turn === InstructionTurn.COUNTER_CLOCKWISE && rotations === 1)
|
||||
(turn && turn === InstructionTurn.CLOCKWISE && (rotations === 4 || rotations === 3)) ||
|
||||
(turn && turn === InstructionTurn.COUNTER_CLOCKWISE && (rotations === 1 || rotations === 4))
|
||||
) {
|
||||
return space.point.y % size
|
||||
} else {
|
||||
|
@ -525,7 +456,10 @@ function printTrail(trail: Trail): void {
|
|||
}
|
||||
}
|
||||
|
||||
function parseInput(lines: string[]): { trail: Trail; instructions: TrailInstruction[] } {
|
||||
function parseInput(lines: string[]): {
|
||||
trail: Trail
|
||||
instructions: TrailInstruction[]
|
||||
} {
|
||||
if (!lines.length) {
|
||||
throw new Error('could not parse input')
|
||||
}
|
||||
|
@ -537,62 +471,44 @@ function parseInput(lines: string[]): { trail: Trail; instructions: TrailInstruc
|
|||
return { trail, instructions }
|
||||
}
|
||||
|
||||
function parseInputAsCube(lines: string[]): {
|
||||
trail: Trail
|
||||
instructions: TrailInstruction[]
|
||||
cube: TrailCube
|
||||
} {
|
||||
if (!lines.length) {
|
||||
throw new Error('could not parse input')
|
||||
}
|
||||
|
||||
const instructionLine = lines.slice(-1)[0]
|
||||
const instructions = parseInstructions(instructionLine)
|
||||
const { trail, cube } = parseTrailAsCube(lines.slice(0, -2))
|
||||
|
||||
return { trail, instructions, cube }
|
||||
}
|
||||
|
||||
function password(destination: TrailPosition): number {
|
||||
const facings = [
|
||||
TrailDirection.RIGHT,
|
||||
TrailDirection.LEFT,
|
||||
TrailDirection.DOWN,
|
||||
TrailDirection.UP,
|
||||
]
|
||||
const row = 1000 * (destination.space.point.y + 1)
|
||||
const column = 4 * (destination.space.point.x + 1)
|
||||
const face = facings.indexOf(destination.facing)
|
||||
const face = TrailCompass.indexOf(destination.facing)
|
||||
|
||||
return row + column + face
|
||||
}
|
||||
|
||||
function solvePart1(lines: string[], debug = false): number {
|
||||
const { trail, instructions } = parseInput(lines)
|
||||
const positions: TrailPosition[] = [trail.start]
|
||||
|
||||
instructions.forEach((instruction) => {
|
||||
trail.at = positionMove(trail.at, instruction)
|
||||
const position = positionMove(trail, positions.slice(-1)[0], instruction)
|
||||
positions.push(position)
|
||||
})
|
||||
|
||||
if (debug) {
|
||||
printTrail(trail)
|
||||
}
|
||||
|
||||
return password(trail.at)
|
||||
return password(positions.slice(-1)[0])
|
||||
}
|
||||
|
||||
function solvePart2(lines: string[], debug = false): number {
|
||||
const { trail, instructions, cube } = parseInputAsCube(lines)
|
||||
const { trail, instructions } = parseInput(lines)
|
||||
const positions: TrailPosition[] = [trail.start]
|
||||
|
||||
instructions.forEach((instruction) => {
|
||||
trail.at = positionMove(trail.at, instruction, cube)
|
||||
const position = positionMove(trail, positions.slice(-1)[0], instruction, true)
|
||||
positions.push(position)
|
||||
})
|
||||
|
||||
if (debug) {
|
||||
printTrail(trail)
|
||||
}
|
||||
|
||||
return password(trail.at)
|
||||
return password(positions.slice(-1)[0])
|
||||
}
|
||||
|
||||
function run() {
|
||||
|
|
Reference in New Issue