From b4a23badc27229ebdf38aa2a9f9bfd0660dbacf9 Mon Sep 17 00:00:00 2001 From: Andres Date: Sun, 15 Dec 2024 20:23:54 +0100 Subject: [PATCH] 2024 day 15 --- 2024/day-15/day15-part2.test.ts | 98 +++++++++ 2024/day-15/day15-part2.ts | 364 ++++++++++++++++++++++++++++++++ 2024/day-15/day15.test.ts | 80 +++++++ 2024/day-15/day15.ts | 239 +++++++++++++++++++++ 2024/day-15/input.txt | 71 +++++++ 2024/day-15/test-input.txt | 21 ++ 6 files changed, 873 insertions(+) create mode 100644 2024/day-15/day15-part2.test.ts create mode 100644 2024/day-15/day15-part2.ts create mode 100644 2024/day-15/day15.test.ts create mode 100644 2024/day-15/day15.ts create mode 100644 2024/day-15/input.txt create mode 100644 2024/day-15/test-input.txt diff --git a/2024/day-15/day15-part2.test.ts b/2024/day-15/day15-part2.test.ts new file mode 100644 index 0000000..861f6e7 --- /dev/null +++ b/2024/day-15/day15-part2.test.ts @@ -0,0 +1,98 @@ +import { expect, test } from "bun:test" +import * as path from "node:path" +import { logLines } from "../../utils/log-lines.ts" +import { + canExecuteMove, + executeMove, + getGPS, + getRobotStartingPosition, + part2, +} from "./day15-part2.ts" + +test("day 15, part 2 test", async () => { + const testInput = await Bun.file( + path.resolve(__dirname, "test-input.txt"), + ).text() + const input = await Bun.file(path.resolve(__dirname, "input.txt")).text() + + const testResult = await part2(testInput) + console.log("\n\n") + console.log("Test data:", testResult) + expect(testResult).toEqual(9021) + + // const finalResult = await part2(input) + // console.log("Full data:", finalResult) + // expect(finalResult).toEqual(0) + + console.log("\n\n") +}, 1000000000000) + +// test("day 15, part 2, canExecuteMove", async () => { +// const testInput = ` +// +// ############## +// ##......##..## +// ##..........## +// ##...[][]...## +// ##....[]....## +// ##.....@....## +// ############## +// +// `.trim() +// const [gridStr] = testInput.split("\n\n") +// const grid = gridStr.split("\n").map((x) => x.split("")) +// const startingPos = getRobotStartingPosition(grid) +// try { +// const testResult = canExecuteMove(startingPos, grid, "^") +// console.log(testResult) +// } catch (e) { +// console.log("error", e) +// } +// }) + +test("day 15, part 2, executeMove", async () => { + const testInput = ` + +0#################### +1##[]..[]......[][]## +2##[]........@..[].## +3##..........[][][]## +4##...........[][].## +5##..##[]..[]......## +6##...[]...[]..[]..## +7##.....[]..[].[][]## +8##........[]......## +9#################### + +`.trim() + const move = "v" + const [gridStr] = testInput.split("\n\n") + const grid = gridStr.split("\n").map((x) => x.split("")) + const startingPos = getRobotStartingPosition(grid) + try { + const testResult = canExecuteMove(startingPos, grid, move) + console.log(testResult) + executeMove(grid, move, startingPos, "@") + logLines(grid.map((x) => x.join(""))) + } catch (e) { + console.log("error", e) + } +}) + +test("day 15, part 2, getGPS", () => { + const gridStr = ` +#################### +##[].......[].[][]## +##[]...........[].## +##[]........[][][]## +##[]......[]....[]## +##..##......[]....## +##..[]............## +##..@......[].[][]## +##......[][]..[]..## +#################### + `.trim() + const grid = gridStr.split("\n").map((x) => x.split("")) + + expect(getGPS(grid)).toEqual(9021) +}) diff --git a/2024/day-15/day15-part2.ts b/2024/day-15/day15-part2.ts new file mode 100644 index 0000000..625fc16 --- /dev/null +++ b/2024/day-15/day15-part2.ts @@ -0,0 +1,364 @@ +import { logLines } from "../../utils/log-lines.ts" +const keypress = async () => { + process.stdin.setRawMode(true) + return new Promise((resolve) => + process.stdin.once("data", (data) => { + const byteArray = [...data] + if (byteArray.length > 0 && byteArray[0] === 3) { + console.log("^C") + process.exit(1) + } + process.stdin.setRawMode(false) + resolve() + }), + ) +} +enum Move { + Up = "^", + Down = "v", + Right = ">", + Left = "<", +} + +enum Unit { + Box = "O", + Robot = "@", + Wall = "#", + Empty = ".", +} + +enum LargeUnit { + BoxLeft = "[", + BoxRight = "]", +} + +type Grid = (Unit | LargeUnit)[][] +type Coordinates = [number, number] + +export async function part2(input: string) { + const { moves, grid } = parseInput(input) + for (const move of moves) { + console.log(`Moving ${move}`) + logGrid(grid) + await keypress() + try { + const robotPosition = getRobotStartingPosition(grid) + canExecuteMove(robotPosition, grid, move) + executeMove(grid, move, robotPosition, Unit.Robot) + } catch (e) { + // console.log("error", e.message) + } + } + logGrid(grid) + return getGPS(grid) +} + +export function parseInput(input: string) { + const [gridStr, movesStr] = input.split("\n\n") + const moves = movesStr + .split("\n") + .join("") + .split("") + .map((move) => { + if (move === Move.Up) { + return Move.Up + } + if (move === Move.Down) { + return Move.Down + } + if (move === Move.Right) { + return Move.Right + } + if (move === Move.Left) { + return Move.Left + } + throw new Error(`Invalid input: ${move}`) + }) + + const grid = gridStr.split("\n").map((line) => + line.split("").flatMap((u) => { + if (u === Unit.Box) { + return [LargeUnit.BoxLeft, LargeUnit.BoxRight] + } + if (u === Unit.Empty) { + return [Unit.Empty, Unit.Empty] + } + if (u === Unit.Robot) { + return [Unit.Robot, Unit.Empty] + } + if (u === Unit.Wall) { + return [Unit.Wall, Unit.Wall] + } + throw new Error(`Invalid input unit: ${u}`) + }), + ) + return { moves, grid } +} + +export function getRobotStartingPosition(grid: Grid): Coordinates { + for (let i = 0; i < grid.length; i++) { + const line = grid[i] + for (let i1 = 0; i1 < line.length; i1++) { + const unit = line[i1] + if (unit === Unit.Robot) { + return [i, i1] + } + } + } + throw new Error("Robot not found") +} + +export function canExecuteMove( + position: Coordinates, + grid: Grid, + move: Move, +): Coordinates { + // console.log("CAN EXECUTE?: ") + // logGrid(grid) + + const { unit: nextItem, coordinates: nextItemCoordinates } = getNextItem( + position, + grid, + move, + ) + const currentUnit = grid[position[0]][position[1]] + + if (!nextItem) { + throw new Error("wtf") + } + if (nextItem === Unit.Wall) { + throw new Error("Wall found, can't execute move sequence.") + } + if (nextItem === Unit.Empty) { + return nextItemCoordinates + } + if (move === Move.Up || move === Move.Down) { + if (currentUnit === Unit.Robot) { + if (nextItem === LargeUnit.BoxRight) { + const checkRight = canExecuteMove(nextItemCoordinates, grid, move) + const checkLeft = canExecuteMove( + [nextItemCoordinates[0], nextItemCoordinates[1] - 1], + grid, + move, + ) + return + } + if (nextItem === LargeUnit.BoxLeft) { + const checkRight = canExecuteMove( + [nextItemCoordinates[0], nextItemCoordinates[1] + 1], + grid, + move, + ) + const checkLeft = canExecuteMove(nextItemCoordinates, grid, move) + return + } + } + if (currentUnit === LargeUnit.BoxRight) { + if (nextItem === LargeUnit.BoxLeft) { + const checkUp = canExecuteMove(nextItemCoordinates, grid, move) + const checkRight = canExecuteMove( + [nextItemCoordinates[0], nextItemCoordinates[1] + 1], + grid, + move, + ) + return + } + } + if (currentUnit === LargeUnit.BoxLeft) { + if (nextItem === LargeUnit.BoxRight) { + const checkUp = canExecuteMove(nextItemCoordinates, grid, move) + const checkLeft = canExecuteMove( + [nextItemCoordinates[0], nextItemCoordinates[1] - 1], + grid, + move, + ) + return + } + } + } + + return canExecuteMove(nextItemCoordinates, grid, move) +} + +export function executeMove( + grid: Grid, + move: Move, + currentCoordinates: Coordinates, + currentUnit: Unit | LargeUnit, +) { + if (move === Move.Down) { + const [cr, cc] = currentCoordinates + const [nr, nc] = [cr + 1, cc] + const nextUnit = grid[nr][nc] + if (currentUnit === Unit.Robot && nextUnit === LargeUnit.BoxLeft) { + grid[nr][nc] = currentUnit + grid[nr][nc + 1] = Unit.Empty + grid[cr][cc] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc + 1], LargeUnit.BoxRight) + } else if (currentUnit === Unit.Robot && nextUnit === LargeUnit.BoxRight) { + grid[nr][nc] = currentUnit + grid[nr][nc - 1] = Unit.Empty + grid[cr][cc] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc - 1], LargeUnit.BoxLeft) + } else if ( + currentUnit === LargeUnit.BoxLeft && + nextUnit === LargeUnit.BoxRight + ) { + grid[nr][nc] = currentUnit + grid[nr][nc - 1] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc - 1], LargeUnit.BoxLeft) + } else if ( + currentUnit === LargeUnit.BoxRight && + nextUnit === LargeUnit.BoxLeft + ) { + grid[nr][nc] = currentUnit + grid[nr][nc + 1] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc + 1], LargeUnit.BoxRight) + } else if (nextUnit === Unit.Empty) { + if (currentUnit === Unit.Robot) { + grid[cr][cc] = Unit.Empty + } + grid[nr][nc] = currentUnit + return + } else if ( + currentUnit === LargeUnit.BoxRight && + nextUnit === LargeUnit.BoxRight + ) { + grid[nr][nc] = currentUnit + grid[nr][nc - 1] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc - 1], LargeUnit.BoxLeft) + } else if ( + currentUnit === LargeUnit.BoxLeft && + nextUnit === LargeUnit.BoxLeft + ) { + grid[nr][nc] = currentUnit + grid[nr][nc + 1] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc + 1], LargeUnit.BoxRight) + } + } else if (move === Move.Up) { + const [cr, cc] = currentCoordinates + const [nr, nc] = [cr - 1, cc] + const nextUnit = grid[nr][nc] + if (currentUnit === Unit.Robot && nextUnit === LargeUnit.BoxLeft) { + grid[nr][nc] = currentUnit + grid[nr][nc + 1] = Unit.Empty + grid[cr][cc] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc + 1], LargeUnit.BoxRight) + } else if (currentUnit === Unit.Robot && nextUnit === LargeUnit.BoxRight) { + grid[nr][nc] = currentUnit + grid[nr][nc - 1] = Unit.Empty + grid[cr][cc] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc - 1], LargeUnit.BoxLeft) + } else if ( + currentUnit === LargeUnit.BoxLeft && + nextUnit === LargeUnit.BoxRight + ) { + grid[nr][nc] = currentUnit + grid[nr][nc - 1] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc - 1], LargeUnit.BoxLeft) + } else if ( + currentUnit === LargeUnit.BoxRight && + nextUnit === LargeUnit.BoxLeft + ) { + grid[nr][nc] = currentUnit + grid[nr][nc + 1] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc + 1], LargeUnit.BoxRight) + } else if (nextUnit === Unit.Empty) { + if (currentUnit === Unit.Robot) { + grid[cr][cc] = Unit.Empty + } + grid[nr][nc] = currentUnit + return + } else if ( + currentUnit === LargeUnit.BoxRight && + nextUnit === LargeUnit.BoxRight + ) { + grid[nr][nc] = currentUnit + grid[nr][nc - 1] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc - 1], LargeUnit.BoxLeft) + } else if ( + currentUnit === LargeUnit.BoxLeft && + nextUnit === LargeUnit.BoxLeft + ) { + grid[nr][nc] = currentUnit + grid[nr][nc + 1] = Unit.Empty + executeMove(grid, move, [nr, nc], nextUnit) + executeMove(grid, move, [nr, nc + 1], LargeUnit.BoxRight) + } + } else if (move === Move.Right) { + const [cr, cc] = currentCoordinates + const [nr, nc] = [cr, cc + 1] + const nextUnit = grid[nr][nc] + grid[nr][nc] = currentUnit + if (currentUnit === Unit.Robot) { + grid[cr][cc] = Unit.Empty + } + if (nextUnit === Unit.Empty) { + return + } + executeMove(grid, move, [nr, nc], nextUnit) + } else if (move === Move.Left) { + const [cr, cc] = currentCoordinates + const [nr, nc] = [cr, cc - 1] + const nextUnit = grid[nr][nc] + + grid[nr][nc] = currentUnit + if (currentUnit === Unit.Robot) { + grid[cr][cc] = Unit.Empty + } + if (nextUnit === Unit.Empty) { + return + } + executeMove(grid, move, [nr, nc], nextUnit) + } else throw new Error(`wrong move: ${move}`) +} + +function getNextItem([r, c]: Coordinates, grid: Grid, move: Move) { + let coordinates: Coordinates + if (move === Move.Left) { + coordinates = [r, c - 1] + } else if (move === Move.Right) { + coordinates = [r, c + 1] + } else if (move === Move.Up) { + coordinates = [r - 1, c] + } else if (move === Move.Down) { + coordinates = [r + 1, c] + } else { + throw new Error("Invalid input for getNextItem") + } + + const unit = grid[coordinates[0]][coordinates[1]] as + | Unit + | LargeUnit + | undefined + return { unit, coordinates } +} + +export function getGPS(grid: Grid) { + let GPS = 0 + for (let i = 0; i < grid.length; i++) { + const line = grid[i] + for (let i1 = 0; i1 < line.length; i1++) { + const unit = line[i1] + if (unit === LargeUnit.BoxLeft) { + GPS += i * 100 + i1 + } + } + } + return GPS +} + +function logGrid(grid: Grid) { + logLines(grid.map((x) => x.join(""))) +} diff --git a/2024/day-15/day15.test.ts b/2024/day-15/day15.test.ts new file mode 100644 index 0000000..a025db3 --- /dev/null +++ b/2024/day-15/day15.test.ts @@ -0,0 +1,80 @@ +import { expect, test } from "bun:test" +import * as path from "node:path" +import { logLines } from "../../utils/log-lines.ts" +import { + canExecuteMove, + executeMove, + getRobotStartingPosition, + parseInput, + part1, +} from "./day15.ts" + +test("day 15, part 1", async () => { + const testInput = await Bun.file( + path.resolve(__dirname, "test-input.txt"), + ).text() + const input = await Bun.file(path.resolve(__dirname, "input.txt")).text() + + console.log("\n\n") + + // const testResult = await part1(testInput) + // console.log("Test data:", testResult) + // expect(testResult).toEqual(10092) + + const finalResult = await part1(input) + console.log("Full data:", finalResult) + expect(finalResult).toEqual(0) + + console.log("\n\n") +}, 1000000000000) + +// test("day 15, canExecuteMove", async () => { +// const testInput = ` +// +// ######## +// #...@OO# +// ##..O..# +// #...O..# +// #.#.O..# +// #...O..# +// #......# +// ######## +// +// v +// +// `.trim() +// const { grid, moves } = parseInput(testInput) +// const startingPos = getRobotStartingPosition(grid) +// try { +// const testResult = canExecuteMove(startingPos, grid, moves[0]) +// console.log(testResult) +// } catch (e) { +// console.log("error", e) +// } +// }) + +test("day 15, executeMove", async () => { + const testInput = ` + +######## +#...@OO# +##..O..# +#...O..# +#.#.O..# +#...O..# +#......# +######## + +v + +`.trim() + const { grid, moves } = parseInput(testInput) + const startingPos = getRobotStartingPosition(grid) + try { + const testResult = canExecuteMove(startingPos, grid, moves[0]) + const newGrid = executeMove(grid, moves[0], testResult) + logLines(newGrid.map((x) => x.join(""))) + } catch (e) { + console.log("error", e) + } +}) diff --git a/2024/day-15/day15.ts b/2024/day-15/day15.ts new file mode 100644 index 0000000..4ba05d0 --- /dev/null +++ b/2024/day-15/day15.ts @@ -0,0 +1,239 @@ +import { logLines } from "../../utils/log-lines.ts" +const keypress = async () => { + process.stdin.setRawMode(true) + return new Promise((resolve) => + process.stdin.once("data", (data) => { + const byteArray = [...data] + if (byteArray.length > 0 && byteArray[0] === 3) { + console.log("^C") + process.exit(1) + } + process.stdin.setRawMode(false) + resolve() + }), + ) +} +enum Move { + Up = "^", + Down = "v", + Right = ">", + Left = "<", +} + +enum Unit { + Box = "O", + Robot = "@", + Wall = "#", + Empty = ".", +} + +type Grid = Unit[][] +type Coordinates = [number, number] + +export async function part1(input: string) { + const { moves, grid } = parseInput(input) + let robotPosition = getRobotStartingPosition(grid) + for (const move of moves) { + try { + const emptySqCoords = canExecuteMove(robotPosition, grid, move) + robotPosition = await executeMove(grid, move, emptySqCoords) + } catch (e) { + // console.log("error", e.message) + } + } + logGrid(grid) + return getGPS(grid) +} + +export function parseInput(input: string) { + const [gridStr, movesStr] = input.split("\n\n") + const moves = movesStr + .split("\n") + .join("") + .split("") + .map((move) => { + if (move === Move.Up) { + return Move.Up + } + if (move === Move.Down) { + return Move.Down + } + if (move === Move.Right) { + return Move.Right + } + if (move === Move.Left) { + return Move.Left + } + throw new Error(`Invalid input: ${move}`) + }) + + const grid = gridStr.split("\n").map((line) => + line.split("").map((u) => { + if (u === Unit.Box) { + return Unit.Box + } + if (u === Unit.Empty) { + return Unit.Empty + } + if (u === Unit.Robot) { + return Unit.Robot + } + if (u === Unit.Wall) { + return Unit.Wall + } + throw new Error(`Invalid input unit: ${u}`) + }), + ) + return { moves, grid } +} + +export function getRobotStartingPosition(grid: Grid): Coordinates { + for (let i = 0; i < grid.length; i++) { + const line = grid[i] + for (let i1 = 0; i1 < line.length; i1++) { + const unit = line[i1] + if (unit === Unit.Robot) { + return [i, i1] + } + } + } + throw new Error("Robot not found") +} + +export function canExecuteMove( + position: Coordinates, + grid: Grid, + move: Move, +): Coordinates { + // console.log("CAN EXECUTE?: ") + // logGrid(grid) + + const { unit: nextItem, coordinates: nextItemCoordinates } = getNextItem( + position, + grid, + move, + ) + + if (!nextItem) { + throw new Error("wtf") + } + if (nextItem === Unit.Wall) { + throw new Error("Wall found, can't execute move sequence.") + } + if (nextItem === Unit.Empty) { + return nextItemCoordinates + } + return canExecuteMove(nextItemCoordinates, grid, move) +} + +export async function executeMove( + grid: Grid, + move: Move, + emptySquareCoordinates: Coordinates, +): Promise { + if (move === Move.Down) { + let currentCoordinates = emptySquareCoordinates + while (true) { + // console.log(move, currentCoordinates) + // logGrid(grid) + const [cr, cc] = currentCoordinates + const prevItem = grid[cr - 1][cc] + if (prevItem === Unit.Robot) { + grid[cr][cc] = Unit.Robot + grid[cr - 1][cc] = Unit.Empty + return [cr, cc] + } + grid[cr][cc] = prevItem + currentCoordinates = [cr - 1, cc] + } + } + if (move === Move.Up) { + let currentCoordinates = emptySquareCoordinates + while (true) { + // console.log(move, currentCoordinates) + // logGrid(grid) + const [cr, cc] = currentCoordinates + const prevItem = grid[cr + 1][cc] + if (prevItem === Unit.Robot) { + grid[cr][cc] = Unit.Robot + grid[cr + 1][cc] = Unit.Empty + return [cr, cc] + } + grid[cr][cc] = prevItem + currentCoordinates = [cr + 1, cc] + } + } + if (move === Move.Right) { + let currentCoordinates = emptySquareCoordinates + while (true) { + // await keypress() + // console.log(move, currentCoordinates) + // logGrid(grid) + + const [cr, cc] = currentCoordinates + const prevItem = grid[cr][cc - 1] + if (prevItem === Unit.Robot) { + grid[cr][cc] = Unit.Robot + grid[cr][cc - 1] = Unit.Empty + return [cr, cc] + } + grid[cr][cc] = prevItem + currentCoordinates = [cr, cc - 1] + } + } + if (move === Move.Left) { + let currentCoordinates = emptySquareCoordinates + while (true) { + // await keypress() + // console.log(move, currentCoordinates) + // logGrid(grid) + + const [cr, cc] = currentCoordinates + const prevItem = grid[cr][cc + 1] + if (prevItem === Unit.Robot) { + grid[cr][cc] = Unit.Robot + grid[cr][cc + 1] = Unit.Empty + return [cr, cc] + } + grid[cr][cc] = prevItem + currentCoordinates = [cr, cc + 1] + } + } + throw new Error("asdf") +} + +function getNextItem([r, c]: Coordinates, grid: Grid, move: Move) { + let coordinates: Coordinates + if (move === Move.Left) { + coordinates = [r, c - 1] + } else if (move === Move.Right) { + coordinates = [r, c + 1] + } else if (move === Move.Up) { + coordinates = [r - 1, c] + } else if (move === Move.Down) { + coordinates = [r + 1, c] + } else { + throw new Error("Invalid input for getNextItem") + } + + const unit = grid[coordinates[0]][coordinates[1]] as Unit | undefined + return { unit, coordinates } +} + +function getGPS(grid: Grid) { + let GPS = 0 + for (let i = 0; i < grid.length; i++) { + const line = grid[i] + for (let i1 = 0; i1 < line.length; i1++) { + const unit = line[i1] + if (unit === Unit.Box) { + GPS += i * 100 + i1 + } + } + } + return GPS +} + +function logGrid(grid: Grid) { + logLines(grid.map((x) => x.join(""))) +} diff --git a/2024/day-15/input.txt b/2024/day-15/input.txt new file mode 100644 index 0000000..d3af33d --- /dev/null +++ b/2024/day-15/input.txt @@ -0,0 +1,71 @@ +################################################## +#.O#..O.O..OO..O.OO.#..O...O.O.##O.O..O.O...OOO..# +#..#O.........OO.OO......O..#.O.O.O.O....O#OO.O..# +##O......O.O...O...O..#.OOO......O.O.O.....O.OOO.# +#.OOO#O.O..O...O...O#O...O...O...O#O.......O.OOO.# +#.OO...#...#O.#...#...O..O.#.O.OO...#OO.OOO...O.O# +#..O..OOO.O......O....O............OO...O.#.#..#O# +#OO.OOO#.O.......O##........O..O....O.....#O.....# +#...OO..O..OOOO....#..#.OOO.O...O..O.O.....O.....# +#..O.#.O.O..........O...#.O........#......O..#.#.# +#.O...O#O.O.O......#..O#O....#..O...#....##......# +#..O...#.O#..O.....O...O#O.....O#.O#..#...#OOO...# +#..O...OO.O............O.#.O.O..O....O.O.O.......# +#..OOO.......O.##.O.O.#.O...#.#O#........O.O#O#..# +#......#O#.O.#.OO.OO....O..O.O.OO.O#....OO......## +#O.#O#...O.OO..O..OO.#..O.O.......O....OOO.......# +#.....O.O.O...##O..##.##.O.O#OO.O.#O#........O.OO# +#......O.........O..O.#..............#.O.#.O..O..# +#.O...O.OOO..O.O.....O...O..O......O.OO...OO..O### +#.O....O##O......OOOO..OO...O.....#...O....#..#..# +#O....O...O..#....O.....O..#......O....OOO.O.....# +#.....#.O..O..O..O.O.OO.O.O.#O.........OO.O.O....# +#....O.....O.O....O...O...O...O..O....O...OO..O#.# +#..OO..#O.O..O.....O...O..O...O.O....OO...O..#...# +#OO..O....O.O.O..O.....O@...OO#....OO.O.OO#O#O.#.# +#....O.OO......OO#.OO.O.#OOO.OOO.......#..O..O...# +##.O#.O............O...#...OO.OO........OO.OO#...# +#O.....O.O#OO........O#O......#...#O.O.OO..O...O.# +#.....O.#..OO#.OO...O...O.OO.#O.OO.O......O....OO# +#O.#.....##O.O......O...O.O#.O....#O.O..O...O....# +#.O#.....#..........O.#..O#..O..O#O...O.#O#O.....# +#.#..O.O..#.O##.O.OOO....O....O...OO..O..O...O#..# +#O.....O.....O..O.OO.O.......O......O.OO.OO......# +#O.OO.O....#..OO..O....O.#...#..#.......O#.OOOOOO# +#.............O#OO.#....O.......OO#......O.......# +##.OO.O..O.....#..#O....#O.O...#.O..OO....OO.O...# +#....O...OO.#..O.OO.OO.OOO........O..........O.O.# +#O.O..O.......O...#O...O.O...#...O#.....O...O.O.O# +#...#.O..OO.OO....O....O..O...O....O#..OOO.......# +#...#..OO..O.......O.O.O.OOO.O.#...O#.#..#O..#...# +#.O#..O..OO..#O...O.#.....O..O......OO.OOOO##.O.## +#.#O....O.......O.#O.....O....#...O....OO.......O# +#...#....O..O..........OO...OO#.....OO..O...O.#O.# +#.O.#O.#....O..#.OO.O#..##.....OOO..#OOO...##O..O# +#...O...O..OOO......##OOO.....O....#......O..#...# +#...O...#O#...#...O.........O.O....#O.OO.....O.OO# +#O....O..##.O#....O....#.OOO#O..O..#O....#.O.....# +#......#O...OOO...O..#...O.O#...........OO..O...O# +#O....O...O...O.#O..O..OOO..#.OO.O.O.........O...# +################################################## + +v<<^^<><>vv^^><<^^>^>vv^vvvv^^<>^>>^^><>v>>>^vvvv<^^<^<<^><<^v<^^>>><>>><><<<>v>^^^<^^>>^vv>^^<<^^v^<<^v><>vv>v<<^<^vv^<^>^v<^vvv>^>>^v>^>v^>v^^vv^v>>^v<<<^>v>>^^<><<^^>v><vv^^>v^v<^<>>>^v>v^^v^>^^>>v>^v^v>v>>>vv^>>^vv>^>v^<<<>^>>^<>^^><<>>^>^^v>v>^^v^^^^>^^<^>^<><<>^>v<<<^^v^<><^vvv>>^v>vvv^^<>>v^<<>>v<>>^^v>>>^^v^v<>v>^^>v<^^<><<<>^v^<^vv>^><<<><<>v>vvv<<^<^v^^<>>>>><>><^v<>><>vv^v^<<^v<<<>^>><>^<<<^<>>v<><>v<^vvv^>^<^v^vv>^^<^>><>><<^>^<>v<^>v<^<>^^v><^v><>>^v^<^<>^v^^<>vv^<><^>v<^vvv><^^>vv<<^^^<<<><<<<^v^><<<^v<>vvvv<^^vvv>>^^v>^v<^v^<^v>^>^^<<><><>>^^><^^>v>><<<>>v>v^>^<^<<^<<<>^v^>^<<<^>^v^<<^^vv>v^^v<^>^>v>^<>>><<^>vvv^v><>^^^<>v>vv^<>>>>v^^v<^>v^^>v^>^<>>^><<^vv<^>v<^ +>^>v^v<><^^<<><<<^^v<>vv<^>^^^>>^v^>^>^vv<<^<<>>>v^<<^vv><<^^>><>^>>v^^<^>^><>v>>^>vv^v>>v>><<^v<>v^vv><<>v^>^>>>><>>>^>>v>vv^vv>^>>>v>^^<^vv><^<<>^>>>>v^vvv><<^<^v<<^^^>^^<^>vvvv^v<>^vv><^<>^>vv<<<>^v<<<>vv>^<<^>><<^<<><<>^>>^v<>>>^v>^v>^>v<<^<^^^>^><^>>>v^<^^><><>^>v>v>v>^>^v<<>^<>^><>><<^<>^>^v<<^v^v<><<^vv^>>^v>vv>v<<>>>>^v<><v<^^^>v^^><<^>vv<^<^v>>vv^v^^^>v^><<>^vv>^<^^^>vv<^>v<>^^^^>v>>v^<^v>>^^<>>vv<^^^<<><<^<>v<<>>^<>v<<^v><^<^^v^<^^>>^vv<>vvv<^v>>^^<^>v^^>v^v>vvvv^><>>v>v>v>>^>v<<><^><>^<>^v>>>^><>^^v>>v^<^^^^^<^v>vv^^vvvvvv^vvv<<^<<><^^^>vv>^v^^v^vv<^v<<>><>^>vv><<>^vv^<><>vv>><<^<>^vvv>vvvv^<><<<^v>v<>vv>>^v<v>>vvv>v<><<<^>v<^>v<<>^>v<><>v^v^vv^^<<^><><>v<>^^<>^>^>^>v>^^v^^<^^vv<<^^<^^v<^<^vv>v><>>vv>^v<><v^^v<<^^v>^<^vv<^>v>v<>^<<^v>><>>^v<<>^v^>^>>vv^^>vv^v^vv<<^^>^^>>>>vv>v<<<^^<>^^>v<^v<<^^^>^^^^^>vv^>>^>><>>vvv<v^>^^><<^^<<^v>^v>^><^<<<><>>^><>v^v<><>v>^>>><>^<<^<>>>^^>>>^<^>>^^<^><><>^^v^v^>^^><>v>^^<>v>v^^v>^v^v<>><^v<<>^^^vv^<<^><^vvv>>^<<<><^^^>>><<><>>>^v^^<>^^^>^vv<>>vv<>>vv>v^>v^v^v^^v>vv<<>^v>^>^^>^>>v^v^><<^<>>vv^^<>vv><>>v^^>v>v<>>v^^v>^^v^vv<^vv>>>>^<^^<^>><<>^<>^>^<^>>^>^^>>v>>v^>>^^v^>^>v^^>vv<^>^^<<><<^^<^><^>^^<<<>>v<^>^vv<<v^v^>><^^^^v^v^<<><>^><^v<^<>>>^<<<^^<^<>>^v<>^vv<^>>>^vv<^<>^><^>^><^>><^v<<<>v^vv>^<><<^v<<^<<^v<<>^^><^vv>^<<><v<>v>><^>^>^v>>^^vv<^vvv^><<>v<>^^^>v^><^<<>v^<^v<><>>>^v>^<<^^<>vv<^v>^>^^^>v>^>>v>^<^<><^>vvv^>^^v^^^><>^v><>v<><<^v>><<><<>v>^>v^<>v^><><^v^v>>^^<> +vv^<>^<>v<>^<<^v^<><><^<^>>v^>v<^^<>>^>^<<^v<<^><>v^^v^<>v^^v^^><^<^<<<^><^>>>v>^>vv^vvv>^v^>>><<^v>>^vv^><<>v^>>^vv^<^vvv^v^v^<^^v>>v^v^>>>vv^><>^v^<^>^>^><^v^v^^>>^^vvvv><>^>>>v><>^v<v<^<^<^><^>^<^^>^>vv^v><<^v^v>v^vvvv^>^v><>v><v<>^>vv>^v^<>v^^>v^<^v<<<>v^<^^>^v>^<>>^>v^^^<>>v>^^^^^>>^<^^<>>><>>vv<^^>>v<>^<^^<>^vv^>>v<<>^^><^<^^^><>>^>>v><<>^v<>><><^v>v>^>><><>^>>^>^<^>v^v^<<>>^^<>><^^^^>vvvvv<^<<<>vv>^>>^^^>^^<<><><^>>>^^vv><^<<^<<>^^v^vvv>^<^vv^^><^v^<><>v><^v>>><^<>>v>v^><<<^<<^<<^^>^<^vv>>>^^^><^<v>v^>^vv>v>vv<<^<v^<>^v>^^^v<>v^v>>^<^v>v^<>^^<>>^v<><^v<<>v^>^v>>>><>^v><>^>v>^^^^><^^>^>v>^^^v^v><<^>v^>^<^<><^v>vv^<^>><><>vv>>vv>v^^^v<^<^^v>^^<<^v><^^^<v^^v^v^><^>>>v>>^^>v<^<>>v<<^^v<<><^>><><v +>>^>>v^<<>>vv<^^v^^>^<><>>>^>v<>vv><^^^>^>>^<>v^vvv^v^^v>>>><<<>^^<>vv>>>v^^v^vv<^<^>^^^>>v>^>>>v^<>v^<^^vvv<>v^<^^v<<v<<^>v^v^^^v^<>>^<^v>><>v<^<^v>^>>><^>><^<<><>^v>>^^^vv<v>>v>><<^^v^^^v^^vv<>v><^>^v<>^>^vv>v^<>vv<>>^v^^>>>^<^><<<^>><>v^v>>>><<<^v<^v^<<^<>>v<>^>v<>vv<>^vv<<><><<^>v<^<<^v^vv^<>v<^>vvv^v><^>>^<<^v^<>^><<<^^><^vv^<^^^<>><>v^^<^>^^<^^^^>^<<<^v^<^>>v>v<^vvv<>>><>>v><^>>>vvv^v^<<><>vv^<^^^>vvvvv^<vv>>>v^<^v<vv^<>vv^>v^<^v^<<^<<^<<^vv^>>^<><^^^^v<<<^<<>v>^^v^><^v^<^<>vv^>>v<^v><>^v<^^>>v>>vvvv<^^^<<>^<><<>^<><><>v>^>>v>>><<<<^<>v>^^^^>vv^><<^v<^v^<>^^<<>vv<^vv<^vv^v^>^vv>^^^^>><^>^^>v<>^<>^>>v>^^<>v>^><^>^><^>v>v>>^v>v><<>>>^>^^^<^^><><^<> +v><^>v<>v<^<^<^<>v<^v^<^>>vvvvv<>>>>^>>^<^^<^^^^v^>v^>v^^v^>^^^<>^^>>vvv^>><>^v<<^vv>v>>v^<>v^^^v<^v>vv^>>^v>v<>>^v^<>vvvvv<^^v^>>v^>^v^^>><>vvv^v^^>v><v<^>vv<^>^v<>^>>>>v^<>^^<<^v^v<>>v<>><v^v>><>><>^vv^>^><^<>v^>>><>v^vv><>v>>><<>>^^v^^><>^^v^^<<<<^^^<^><>v<^>>v<^>><^<^<<<>>^^<>>^v>v^^^<^^<<^<<^v>^<><>>v^^^v<><<>^<<^^^<>^>^v<^>>^<^<^<^<>>v<>>>^^<<^<><^^^>>v^<<<>>v^v^v^<^^><><^^>vvv^vv<^^>>>><^^v>>>><><<><<>>v^v^v<^^v>v^^^^^v>v>>>v^>^^>>>^v><<^<><^<^><<>>^^^^^v<^^v^^^v><^^<^vv>>^<^^>>>><<<>v<>^>^^^>v><>^^^^^v>>>^<^<<<>><^>>^v>v<^<<^>v^>>^^v><^v^><>^<<^v>^>v<>>^^<>^v^<<^v<<><<>vvv><^^^>^>v^vv>^^^vvv<>v^>^^<>>^v^<>^vv>v>>^^^<^^>^^>>v>><^<^^^^>^^>^>^v><<><^><>^<>>^>^v<^>^<>v>^<>^<>>^v^<^>><<^>vv<<^v<<<<^><>^^^v^v<>^v>v^<<>>^>>v^>^vvv^^<><<<>>><><^vvv>^>v>^^><<>>v<^<>>v^v>>v<^^<>v<<^>^<vvv^<<^<<^>v^v>^^<<<<>v<>^^>>^v<^v<>v<^>><>>v>v><>^^v>v<<^<^^^v^v><<>v<^<><<^v>>>^<>^>^^^^<<<^<>vv^^^<^vvv^v<<^<>vv<>^^>^<^<>><<<^^><^<<<^>^>^<^^>>^>v<>v><^>>^<^<^v<^>>^<^>v>^^<<<v^>^v>vvv><><^^>^>^>^vv^>v^<<>vv<^^^^<^^>^v^>^v><^v<^>^>>v^<<^<><>^^^>^<>^>^v<><<<<<<<>^>>^^vvv^^vv<<<<<<<^v<^>v^<^<^vv<<^^>>^><<>><^^>>v^v><>><v>^>>^v>^v^v^<>>^^^<^^>^>^><v>^<>^<^>>^>v>^<<^v>v<<^^<^^>>v^^^>v^v<^>^vv>vv^^<><^>>><<>>vvv>>^>>^^<^v<>>^^v<^<<^>^<^^>^>v>>><^<^^v^<<>v^v<><<>v><>^^<^^^vv^v>v^v^>>^v^>^v^v>vv<^>v^^><^>>>v^<^<>^><^^>v><^^^<>^>>v^^<^>^^^>^<>>v^v><>v<<>^>^vv^>^<^<><^vv>v^><>^v>^<<<^v>^>v^>><<<<^<^>vv<>>^v^<>v><>>^v>^>v^><^vv>^v^>v<>^>^<>^v<^>>^v^<><<<^<<><^v>>^ +^>>vv>^>>^^^^v^>^^^^^v^<<^>>>vvv><^v><>^<^>^^^v>v><>^>v>vv>><^>>v^<^v^v^><><<>^^^^^>^^>>>v<<<^v<^><<^>v<<>>v><<^<<<>^<^<><^v^^^>vv>vv>vv>^v>^>><^>v<^<^>^>vv^^>vv>^vvv^vv<^>^^^^^^>^>>^v<<>>v<>v><>^^<<<<<^v<vv^^>>>v^^^^^>^v>>>^^v^^>><><<^^^^v><<>>^<<>vv^^>><<<<^v^^>><>>^^vv^>v^v^<<^^^<<^^<>^^^<v<<^>>v>^v<><>vv><>v>v^^^<^^^><>^<^v^^<>^^<><>^^^>^^>v^vv><<^<<><^>>v>v<>>v>^>^^^<^<^><^>vvv<<^^v>>>><^v^<>v^v^>^><<<^<<<<<>v^>>><^^^v^^<>vv><^^^<>v^^^^vv>>><vv^vv<><^>vv^v>>vv<^^<<>>^^<^<v^>^<<^<>><<>>^vv>^v>vv<<>>vv^^^v><>>^^^v^v^>^v<<>vv<^vv<>>v>>^<^>vv><>^^>^vv<<>>vv^<^<<^><<<^^>>v^>>v^>v>^>^<>>>^>v^v<^>>v^^^^><^v^>><><^>^^^v<>vv^^>vvv>v><>v>v<>v>><<>>^v^^<^>vvv<>v<<vv<<>vv>>vv<^v<^^^><>v>v^><<^>^vv>>>>v<^v^< +><<^v<>>v>>>vv><^^>>>v>v^v<>^<>><<>^v>v><<<^<^v>v>vv><^^v^^>^<^<^><^^>>>v>^v<^v^^^>v^^vvv><<^>^>vv>^<^^^^<^^v^^>>>^<<<<><^^<<>v>>>v^<<>>v<>v^vvvvvvv<^^vv^vv<<^<^v<<vv><<^<><<>^^<<^v^^>v>v<>^v><>vv<>v>vv><^v^<^<^<>>^>^v^v>^^^v^^v><><><^>v>^<<^>vv>v>>>^<>^>^^v>vv><^>v><<<<>v^v>>vv^^<>^>^^^>><<^^^^^^>>^<<>><<^<>v<^<<><<^^^v<vvvv<>v<<>>^v<>v^<>v><^<>^<<^^v>v>>vv>^<^>^v>>vv>v<<<^<>><^<>>^v^vv<<>v^v^>>^v^^^^v^v<^^v<^v<<^^v^>v>vv^<<><^>>^><^<><^>>vvv>^<^^>v>^>><><^^>vvv<<>vvv^^<>v>v>^^>^<<>^<<<<>>vv^v<<<>v^vv>><><<^v<>>><<<>^<<>>>>v^v^<>>v<>>><>^v^vv>^v^^>^>v><<^vv<^>^vvv>^^^><>>vv<><<<^<<^<<^>^<^v^>>v>><^v<<>v<^>^v><>>>vv>>^v><<>^^^>^^<v^<<>^>vv>>v^v^^^v^<>>>v^vv<<><>>v^^^v>v^^ +<>v>v<>v>^^<^^<>^>>>><<>^>v>vv^v^>^v>v^>^^>^<>>>^>v^<^<^v<^^<^>>vv>vv^<>vv>^>^^<<>^>v^^><^<^^<>>v>>^v^>>^>>>^>^^^^<>vvvv^^^^v^v>^<^vvv^v^>^^^>^<^>>v^>><^<^^v^>^<v<<^v>><<<>v^>>>>><<>^v<>vvv>^>><><>^v<^^^>v><^v^<<<>>^^>^v^^v<>><^<^>^<^>^><^><^<<>^<>v>>>>^vv<>^v^>^<^vv<<^^>^<^v^<<<^>^<^<<>^>^v^v<<>vvv^vv<^v^v>^>>v<>^^v<^^v>vv>v^v>^>^>v^vv<v>^>v<>^^>^^^^v>^^^vv<>^><><><>><<><<^v<^><<^v>><^<^<>><<>v>^v^v>>^^>v^^>vv^v>^^^v>v>^<^^v^v<^^<^vv^vv^>>^^v^vv>><^>^^<<^>>><^^>v>^v>vv^^^<^<^^v^^^<>>>v^^v><^^<><<>v^>v^^><><^><<><>v<^^>v^>>v>><><<<^<^<><>^v<<>^<<><^^<>v<>^>><>>^<>v^><>v^^>^^<<<>v^<>><>>^>^<<>vv<<><>>>v><<>v<<^>v<<>>^v>vv<^<>v^>vvv>^^^^v>v>v^>^<>^<<^^vv>v^v<>v^>^^<^^<>v<^v>^>v^vv^vvv>^^v^^^^^>^vvv<^vvvv<^<><<><<<<<<^v>><>><>v>^^<^<^>>>>^>v^<^<>v^<>>vv<>v<>>>v +v<><<v>^>v>>vvv^^v>v<>^>vv>>v>^v>vv^vvv^<<^v>>^>^^<^>>^<^><^>v<^<>v>v<>^^^^>vv^>v^>vv^^<<^>v>v>>^<>v^vv>vvv>v^v^>v><^>vv^^^^v>>>^vv^>^^>v^^v>v<>^v<^^vv<^v><<><<^>v<>>v>^>^^<^^>v<^v^v<^<>v>v>^><<^>>>^^v><<^^^>v>vvv>>v>v>v>>>^^^<^^>v><<>>vvv^<^v<>v><^vv>^><^>>>>^>vv^>>vvv<^^v^>v<<>>v^v^^^>^^vv<>v^<>>vv>^<^>^>>^^<<^^^<^v^^^<^>v^vv>vv^>v^v<^<^v<>^^<^v^<>^^><<^><<>v^>v^^<^^<<<^>><>>v<>^<>v<>v<<^^><>>^>>>^^^^>vv^v>>v^^<>vv>^v^<<^<^><<^^>^vv^<<<<<^v>^^v^<^<vv>^<<><^vv<<<^^<^^>vv<^<<<>v>v^^^v^^<<<^<>v<^<>>vv^<^vvvv>v><><<<>v<^<<>v><>v<>><^v^>>>^vvv^^^^>><^vv^v>>^>v<<>>v<><^v<^^^>vv>^>>^<>v^>^^<>v<<>v<>><><>><>>v^v<^vvvv^v><<^>v^v><<^v<^^<<^^^<>vvv^>vv^>vvv>^v>>>v^<<^v^<><^>v>v^>^<>>v>>>^<<>><<^><>v>^^^vv<^v>v^v>v><^v^> +<>>^>><^><^^^>^vv<>v><>v>v>><>>vv^>^>v>>>^>vv>^^>v^v>v><^>v<^^^v><>>^<><^v>><>>^<^><^>>vvvvv^^<<^vv<>>><><>>^>^v>v^>vv^v<<^v^^v<>vv^v^v<^>>v>vv^<^v<<^<>^^<<<^>v>^>^^>v>>^>>><^<^^^>v<>^^vv>><>>><^^>v>^<^<^^<>^>^<<>v^<>v^<^>^^>vv<>^>vv^^><><^^v^<<^v^^v><^^>>>><><^vv^><>v^^>>vvv><^<<>v^>v>^^<><^^v>><^^><>>vv>>v<^>v^vv^^>^>>vv>v>>vv>^^v^>^>>^<^><^><<>>><^<v^^^>^>^v^^^v>^<^^>^v^>^^v>^><>vv^v^v>>>v^vv>>v<>v^^>>^vvv^vvv<<>^^v<^^^v<^v<><>v>>>^^>v><<>>^<<^><>^><^><<>>^v>>>^v^>v^v>^>v^>^><><^>><^v>vv<^vv^<^>>v<><^v>>vv^^v>^<>^>v<<>>vv^v<^>>v<><^v><>^^<^v^^^>>>v><^<>>>><vv>v>^^^^^^v>>^<>>vv^<^>>^>>>vv^>v<^v<>v>>v>>>^^<>>vvv<^<<>v>>><^>^<^v>v<><>vv>>>><<<<>^^><>v^v>v<>>>>^<^^ +vv>>>><>^<<<^><^^<^v>^^><>>><>^vv<^v^^^<^^<<^^<<<>>^>^^v<><>^^<<^<<><^^v>^<<^<>^v<^^^>^>^<^vvv^v^^v>v^^<>>^<^<<>^>>>vv>vv<>vv<^>^>v<<>v>>>>^^^v><>^v<^v^>^^<<>^>^>v^vv^^>^>^v^vv^<>^<^^<><^>v><<^v<<<>>v><<<^>><^^^>^<>^>^>>>v^>^><<^^^>v>>><^^^v^<<>^<>^^>v^<^^^<v^v>^><>v^v^vv^<^<<vv^^<^v^<><^>>^v^<<>>><^<v^vv^^^^<^^^v<>vvv^>>>v^>v>^vv>><^^v<<^>^>v><<<>>v>vv>^v^>><>>^<><<<^<^v>v>^<<<<>v<^<^<^<>^^v<><^><<<>v<^v>vvvv<<<^v<>v^^^><>><<^^v>>^>v>^^<<<^>v>v>^<^>^^v^>^>^^^^<^^<>^<^v^^^^>^<^>^v>^<<><^<^vvv>^^^v^v^^><>v>v^><<^><<^^><^>^v^^^^><><^>v^^v<^<<<^>^v<<<<^<^vv^<^^v^>^v>v<>^^<^^^^>^^^<<^>>v<<^^v>v^^>^<^^^<>v<^<>vv>>v>^>>^v>v^<>v^>^^vvv^<>>>>>^^^<<^<<^^<^><^^<^<>>^v<>v^v<>vv>>v>>^v>v>v<>v<^<^^vv<>^^>><<>^vv><^^^>>>>v>v>^v<><<<<<^v^>^^^^vv><>vv<^<^>^v<^>^>^^v^<^^>>vv><^vvv>v>><^>^>>>vv^^v>>v^vv>>^v^<<^^<<^<><^<>>^>^v><>>^v<<>^>><>>v<^>>vv^>>^v<<<<^<>v<<^v><^v^><>>v<<>^>>^^^^v><>>^<<^v^>^^><^>vv^^<^^v<>^^v^v^^>v<><<<^><>>^>v^v<>vv^>v<^>^<^>v>^<<>><>>>><>v>v^^<>vv>><><^^>>><>^><<^v<><^v^<>>^^v^v^vvv<^^>^v<>v<^^^^<<><<^<<<^<>v^^v^v^^^<<<^><<<^^<^^>vv^v<>v>>><>^<<>^><>^>^v>^<vv^>>>^^>^<>v^v^<^vvv>vvv>v><>vv>><>v>v>>>>v^>v>v<^v><<>^>>v^>^^>v^<>v^>vvv>v<>>v>>^^v>>v^>^^<>vv^^v<^<>v<<>>>v^v<<<^<>>>^>v>v>v<^^>v>^^^>vv>^^>^<<>^^v>^>v>vv><>^>v^v><^>>^>^^>>v^^^>><<>v><^<>>>^<>>>vv^>>v^<>v<^<<>^>>><^^^>^><<>v><>v^v^v<>vvvv><^^>>^>>v<>^<>v<^^v><^>v<<^^>>^^^>v^^>v<<><>><>^<>vv>v^>>>^v>><^^<>vv^^<^^v^v^>^<>v><>^^vv<<>v<<<^v^^>>v^<<^<<<>^v<>v><<^^v^><^^<^<<<^^>>>^vv<>^>>v>vvv><^<^< +^v<>><<>v^>^>v>v<^^>v<<^v><^>><<>^^>>v^><^^>><^^><<^v>v<>^^^v^<^^^^^vv^vv^^>v<^>>>v<>vv>>^>vv<>^>>^^>>vv>^v<<><^>>><^<^v^<^<>^^^vv^<<^^v<>>^<^^>><^v><^^>><<<^>v><>>>^v><^>^>v>v>v><^>>^><^vv>^><^^>v<>v<>>^^>^^<^^v^<>v^^^^v^>^v^<^^>>v>v^>v^^vv<<>^v>vvv^<^>><^^^>^^>>^<<^>>>>^^>^v>v^<<^>v^>^^^v<>><^<>^v^v>vv>^>>^><<<<^>>^>><^^v>v^>><^<<^^>v^<<><>^>><>>^><^v<><>v>^^v>^>v^<^^v>vvvv^^>^<^>>v<><<<>>vv<<<<^^>>v<^v>>>>v^^>v>>vvvv>v>><><v^^v>v^v^^<^vvv^^^^v<^v>>v^>^^v<^^<^<>><>v>v^v^v><>^<^v^>v^>v^>v>^<^<^>vv><^^^^v><<>>v>>^<>>><<><>v><^v>vv>v>>><>>v^<<>^<<^^>^^v^v^<<><^>>>>^>>v^>>><^>v>^v>>>v>>>v<^v<<<^^^<^^^<^vv>>v>>v^v<^>>^<<<>^v^>v>vv^<>^>^^>>v>>^<<>^^v>>v><^<^<^vvv>>^<^^^><^^v<<>>v>>>>>>>^>vvv<^>vv^v^v>>>>>vv^ +<<^^^v^^>^v<<^>>vv^><^<>^^><^>^>v>>>v>v^>v<^v^>>vv><>^v>v>><^><<<>^<>^>><><>^>>^v^<^^^<^<v><<<><^v><^><<^v>>v<^>^<><<^^<^<^>>v^v><>v>>>^><>><><<>vv^>><^>>vvvv^^>><>^<<>^vvvv>><^<^^^^<><^vv>v^^><v<<<>vv>v<>^^<>^^>>vvv^v^>vvv<^<>>v^^^v^<<^<>vv<^vvvv<<^^^^^<^<<^^<<>>>v^v^<<>^>><<>>>><^^^^^vvv><^>>>>v^^>v>^^>^<^v^>^>vvv<<<^^v><^v<><^v>>>>v>>^><^^>v<>^^vv<<v^^>^<>^v<^<<^^>>^<^vv>^^v<^>vv<<>^>>^v^><<^>>^<><v>v>vv<<^v<^>^vv^<><>^>><>>vv^^^<^<<^^<^vvv^>>^^v^><><<<^><^^^<>>>>vvvvv>vv^v><<^>><>^v^<><<>v^^>>^v^^^>><^>^<^>v><<>>vv^^^>vv>^>^><>v>v<<^^><>^>^v><>^>^><<<^^><<<>^^<^v<^><^>^>v>v>>vv^^>>>v><^>>v^vv><<>><>^>^v>>vv>^>vv^v^>>^<<>^^>vv^<<^<^^>v^>><>>>v^><^>^^><<>> +>^<<><>^>><^^v>v^v>v>vv<<>^><>^v<>><<<<>^^vv>v><>^^><^^<><^>>><>v>^^^><^<^vv^v^<^>v<<^<>v^v^^^>>v><^>v^^v<>^vv<>^<>^^<<^^v<^<>>^<^<^^v<>v<^^><<^^>v^><^^v<<^>v^v<<>v<^<^v<>v<^>v>vvv^><<<^v<^^>v><^v^v<^<><<<^vvv>^v<^>>>^v^>>^<>v^vv^^^>^^>><>^v><<<^v^>^^><>v>^^^>>^^v^>^vvv^<^<<<^^<>^>>^>^vv^v>^^^v><^v<>>><>vv<^^v>^vv>>><^<^v<^>>>^v>><>><^<>vv^<^vv>>>^<>^^^v<<>><<<>>v<<<<^v^>^^<^<>>v^^vv>^^^>v>^vv>v^<^^<>v><>^^v<>vv<>^v^^^v<><^v>^>v<<>v<<>>>^>v>><>v>vv^<^^^>v<^<><<<>v>^>^<^^>>v^<><^^<<>>vvv>v<>>^^^vv>vvvv<<<^^^>v^>^^>>^^vvv>v^>>^><>v<>v^>vv<>>>>v>vv><v^>v<^>>^v<>>>v^<^>v><><<<<>^<><<>^>>>^^vv>>^<^vv<>v<^v^>^^>>>>>><>>^<><^^<><<^v<>>v>>>>>^<^^>v^<^v<>^>>><>>^^v^>>^<><^>>>^<>>>^>vv<<^>v<^><<^>v><>v^v>vv<<^<<^^><<<^>v><>v^<^^^><>><^>^v>v^vv>^<^>v< +vvv^<^>><>>^>>v^v^^>><>v>v^^^<>v<>^^<>vv>v>>^^^vv<^<^v^v^<>v<^^<>vvv^v^v>>><<><>^v^>^v^<^>v>v<><>^>^>^><^>vv>^^^<><^>v>^^>^v<^><>vv>><>>>v>^<^v>v^^<^<>v>^><>>v>v^><><><<^vv<>^<<<^v<>>v>v^v><><>v^v>^<<>>^^^><>v^^<^><<^><^<>^<^v<<<>v>^<^vvv<<^^<<><<>^>v>^>^>^>>v>^^<>^v><<^<>^><^>>>><<<^<<^v>^<^^<^^v<>v^v<^>>>v^>v><^^>^^><^v<<<><<><v>>><<>>v>^v^v<<^v^^<^v^<^<>v>>^vv<^<^vv^><>^>>^^vv^^^>v<>>^>>^<^v<v<>^v^><^>^v>><<>^>v><^v>v>^v>>v^v><<>^^<<<<^^^^>v><^<<v<^^<^><^>^>>>>v>>^<>v>v<><^^^v<><^><>v>^>vvv>v^^vv<<>v<>vv^^^>v^<^v><<^>>^<v><>v>>v>>^>v^v>v^>v^>v^<^v^^>><<>^>v^<>v^>vvv>>><^>vv^^v<>vvv^<^^v^>>>^v>v<>v>^^>>vv>^vvv>^vv^>vv^^v^^<<<^<^<><v<^^<>v><<<> +>v<<^v>^>^<<<^<>>^>^<^vv^^v>>v<<^>>^^v>^>^>^><>>><><>>v^>v^>^^v^^v<>v^>><>>^^v<<><^^<<<<>v<^>>^><^<^v^v>^>^>vv^v>^><<><><<^>>>>^<^<^>^^>^^<<>^^^^^<>^>vv^^^><^>>^v^^^>^>>vv>^v^^v<^^v><^^<<<^^>^<<<>>^^v^>v^>^<>>v^>^<<^<<^vv>vv>>v^^>vv<>>vv^v^><^^<><>><^>>vv^>>^<^v><<>^^v^<>v>vvvvvvvv>>>v>^v>v<>v>^>v^<>>vvv^^>v<^>>^^<v><^^^^><^<>>^^v<><<>v<^vv<^<>^v>>>v><<^>^>^v<>>^^^>v>^>><<<>><^vv<^>^>v^^v^v^^>v^><><^vv>^>>^v^v>><v^^v<>v>^>v><>vvv>>vv>v<^vv<>v>>v><<>v<>^<^^^v^<<><^v^<<<>v<<>><^<^<^>>v^<>^<><^<^<^<>^^v<^^>^^<v>v<<>^^v>v>>^>^^>>^v><>^>>>><><>v<>^<>vv<>v>^>vv>><^v^vv^>^<^<<>^><<^>v>^^>vv^^<^vv^>vvv^>vv^>^<^>^^<<>^^vv^v^>^v><^^<^^<>^<>v<<>>>^v><>>>v<v<>v>vv>^^v^^v>>^v^^vv<<^>>^<^<^<^v^>vvv>>^^>^<<^<>>>vv<>v><<>^v^v>^^v^<<><v>v>>v>^<>v^<<<><<><^>v^<>v>^v<<<>^^>^^^^>vv><^>vv<>^^<^^^v<^<^vvvv<><^><<>>v<<^v>vv^<^^v<<>^vv>>>v>^>>v^<>>^<<^^v<><>>>^>>>^v^^^><<<>>v>^^<^<>><><>^^v^<<^>^<>^>>>^v>v^^^v^<<>v<>>><><^>^^>v>v>vv<^>>^v>><<>v^^><^vv>>>>v^<^^^<vv>^v<<v^v>^v>vv<><^^>v<<<>^>^<<>>vv>v>>>><^>v^><>vv^^vv^^>^><<>v^^>>^v<><^^v>>v^^><^>^v>>>>>><^<<<^v>^v^^^><^>^<>^<>v^<^^^^^>v<<^^>^^<>v^^v<>>>v<^^><>^<^>><>v>v<>>^><<^v<^^^>>>^>v<^>^vvv<>>^>>v^^<<^<<<^>v<<>v<^<<^vv>v>^^>v>^<>v<v^^^v^>>v^^>^^v^v^<<<<>>^vv<>>v>vv^<>vv^>v^^v^v>v>>^>vv>v><^<>vvvv^v>^^vv>>^vvv^^^v>vv^>>vvv<^v>^><<<<^>^v^>v^>>v<>>v<<>>^v>^^<<<v<^v>>>^^>v>v^>><^<^v<<^v^vv^><>>^^<<>^v><>>^>v>^v<<^^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^ +vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv< +<>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^ +^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^>< +^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^ +<><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<> +^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<>< +v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^ \ No newline at end of file