Day 6 (almost) solved

This commit is contained in:
2024-12-12 13:24:28 -05:00
parent 9cd6824bba
commit f6adc7a818
4 changed files with 760 additions and 1 deletions

View File

@@ -9,6 +9,8 @@ import java.util.StringJoiner;
import com.mattrixwv.adventOfCode24.days.Problem; import com.mattrixwv.adventOfCode24.days.Problem;
import com.mattrixwv.adventOfCode24.days.Problem1; import com.mattrixwv.adventOfCode24.days.Problem1;
import com.mattrixwv.adventOfCode24.days.Problem10; import com.mattrixwv.adventOfCode24.days.Problem10;
import com.mattrixwv.adventOfCode24.days.Problem11;
import com.mattrixwv.adventOfCode24.days.Problem12;
import com.mattrixwv.adventOfCode24.days.Problem2; import com.mattrixwv.adventOfCode24.days.Problem2;
import com.mattrixwv.adventOfCode24.days.Problem3; import com.mattrixwv.adventOfCode24.days.Problem3;
import com.mattrixwv.adventOfCode24.days.Problem4; import com.mattrixwv.adventOfCode24.days.Problem4;
@@ -22,7 +24,10 @@ import com.mattrixwv.adventOfCode24.days.Problem9;
public class ProblemSelector{ public class ProblemSelector{
private static final Scanner input = new Scanner(System.in); private static final Scanner input = new Scanner(System.in);
//Holds the valid problem numbers //Holds the valid problem numbers
protected static final List<Integer> PROBLEM_NUMBERS = List.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); protected static final List<Integer> PROBLEM_NUMBERS = List.of(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12
);
private ProblemSelector(){ private ProblemSelector(){
@@ -44,6 +49,8 @@ public class ProblemSelector{
case 8 : day = new Problem8(); break; case 8 : day = new Problem8(); break;
case 9 : day = new Problem9(); break; case 9 : day = new Problem9(); break;
case 10 : day = new Problem10(); break; case 10 : day = new Problem10(); break;
case 11 : day = new Problem11(); break;
case 12 : day = new Problem12(); break;
default: throw new InvalidParameterException(); default: throw new InvalidParameterException();
} }
return day; return day;

View File

@@ -0,0 +1,214 @@
package com.mattrixwv.adventOfCode24.days;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.mattrixwv.Stopwatch;
import com.mattrixwv.Triple;
public class Problem11 extends Problem{
private static final String inputFileName = "days/Problem11.txt";
private List<String> map;
public Problem11(){
super();
description = "Find the number of distinct positions the guard will visit.";
result = "Unresolved";
}
public String runSolution(){
Stopwatch timer = new Stopwatch();
timer.start();
//Read the file
map = new ArrayList<>();
try(Scanner scanner = new Scanner(this.getClass().getClassLoader().getResourceAsStream(inputFileName))){
scanner.useDelimiter("\n");
while(scanner.hasNext()){
map.add(scanner.next());
}
}
//Find the current location of the guard
Triple<Integer, Integer, Character> currentLocation = findInitialLocation();
//Loop while the guard is still on the map
boolean inBounds = true;
while(inBounds){
//Move in the direction the guard is facing as far as possible, then turn right
if(currentLocation.getC() == '^'){
currentLocation = moveUp(currentLocation);
}
else if(currentLocation.getC() == '>'){
currentLocation = moveRight(currentLocation);
}
else if(currentLocation.getC() == 'v'){
currentLocation = moveDown(currentLocation);
}
else if(currentLocation.getC() == '<'){
currentLocation = moveLeft(currentLocation);
}
else{
throw new RuntimeException("There was an error in the location: " + currentLocation);
}
//Determine if the guard is still on the map
if(currentLocation.getC() == '\0'){
inBounds = false;
}
}
//Count the number of distinct locations visited
int count = 0;
Pattern xPattern = Pattern.compile("X");
for(String mapLine : map){
Matcher xMatcher = xPattern.matcher(mapLine);
while(xMatcher.find()){
++count;
}
}
//Save the results
timer.stop();
result = "The number of distinct positions the guard will visit is " + count + ".\nIt took " + timer.toString() + " to run the algorithm.";
return result;
}
private Triple<Integer, Integer, Character> findInitialLocation(){
for(int row = 0;row < map.size();++row){
String mapLine = map.get(row);
int startIndex = mapLine.indexOf("^");
if(startIndex != -1){
return new Triple<>(row, startIndex, '^');
}
}
//If it gets this far it was not found
return new Triple<>(-1, -1, '\0');
}
private Triple<Integer, Integer, Character> moveUp(Triple<Integer, Integer, Character> currentLocation){
while(true){
String currentMapString = map.get(currentLocation.getA());
//If the current Y value is == 0 then the guard left the area
if(currentLocation.getA() == 0){
currentMapString = currentMapString.replace("^", "X");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(-1, -1, '\0');
}
String nextMapString = map.get(currentLocation.getA() - 1);
//If the next Y value contains a # then the guard needs to move to the next stage
if(nextMapString.charAt(currentLocation.getB()) == '#'){
currentMapString = currentMapString.replace("^", ">");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(currentLocation.getA(), currentLocation.getB(), '>');
}
//If the next Y value is a . or X then move to the new location and mark the current location with an X
else{
currentMapString = currentMapString.replace("^", "X");
map.set(currentLocation.getA(), currentMapString);
StringBuilder newMapString = new StringBuilder(nextMapString);
newMapString.setCharAt(currentLocation.getB(), '^');
map.set(currentLocation.getA() - 1, newMapString.toString());
currentLocation = new Triple<>(currentLocation.getA() - 1, currentLocation.getB(), '^');
}
}
}
private Triple<Integer, Integer, Character> moveRight(Triple<Integer, Integer, Character> currentLocation){
while(true){
String currentMapString = map.get(currentLocation.getA());
//If the current X value is == the length of the string then the guard left the area
if(currentLocation.getB() == (currentMapString.length() - 1)){
currentMapString = currentMapString.replace(">", "X");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(-1, -1, '\0');
}
String nextMapString = map.get(currentLocation.getA());
//If the next X value contains a # then the guard needs to move to the next stage
if(nextMapString.charAt(currentLocation.getB() + 1) == '#'){
currentMapString = currentMapString.replace(">", "v");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(currentLocation.getA(), currentLocation.getB(), 'v');
}
//If the next X value is a . or X then move to the new location and mark the current location with an X
else{
currentMapString = currentMapString.replace(">", "X");
map.set(currentLocation.getA(), currentMapString);
StringBuilder newMapString = new StringBuilder(nextMapString);
newMapString.setCharAt(currentLocation.getB() + 1, '>');
map.set(currentLocation.getA(), newMapString.toString());
currentLocation = new Triple<>(currentLocation.getA(), currentLocation.getB() + 1, '>');
}
}
}
private Triple<Integer, Integer, Character> moveDown(Triple<Integer, Integer, Character> currentLocation){
while(true){
String currentMapString = map.get(currentLocation.getA());
//If the current Y value is == the length of the string then the guard left the area
if(currentLocation.getA() == (map.size() - 1)){
currentMapString = currentMapString.replace("v", "X");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(-1, -1, '\0');
}
String nextMapString = map.get(currentLocation.getA() + 1);
//If the next Y value contains a # then the guard needs to move to the next stage
if(nextMapString.charAt(currentLocation.getB()) == '#'){
currentMapString = currentMapString.replace("v", "<");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(currentLocation.getA(), currentLocation.getB(), '<');
}
//If the next Y value is a . or X then move to the new location and mark the current location with an X
else{
currentMapString = currentMapString.replace("v", "X");
map.set(currentLocation.getA(), currentMapString);
StringBuilder newMapString = new StringBuilder(nextMapString);
newMapString.setCharAt(currentLocation.getB(), 'v');
map.set(currentLocation.getA() + 1, newMapString.toString());
currentLocation = new Triple<>(currentLocation.getA() + 1, currentLocation.getB(), 'v');
}
}
}
private Triple<Integer, Integer, Character> moveLeft(Triple<Integer, Integer, Character> currentLocation){
while(true){
String currentMapString = map.get(currentLocation.getA());
//If the current X value is == 0 then the guard left the area
if(currentLocation.getB() == 0){
currentMapString = currentMapString.replace("<", "X");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(-1, -1, '\0');
}
String nextMapString = map.get(currentLocation.getA());
//If the next X value contains a # then the guard needs to move to the next stage
if(nextMapString.charAt(currentLocation.getB() - 1) == '#'){
currentMapString = currentMapString.replace("<", "^");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(currentLocation.getA(), currentLocation.getB(), '^');
}
//If the next X value is a . or X then move to the new location and mark the current location with an X
else{
currentMapString = currentMapString.replace("<", "X");
map.set(currentLocation.getA(), currentMapString);
StringBuilder newMapString = new StringBuilder(nextMapString);
newMapString.setCharAt(currentLocation.getB() - 1, '<');
map.set(currentLocation.getA(), newMapString.toString());
currentLocation = new Triple<>(currentLocation.getA(), currentLocation.getB() - 1, '<');
}
}
}
}
/*
Find the number of distinct positions the guard will visit.
The number of distinct positions the guard will visit is 4647.
It took 14.695 milliseconds to run the algorithm.
*/

View File

@@ -0,0 +1,408 @@
package com.mattrixwv.adventOfCode24.days;
import java.util.ArrayList;
import java.util.List;
import com.mattrixwv.Stopwatch;
import com.mattrixwv.Triple;
public class Problem12 extends Problem{
private static final String inputFileName = "days/Problem11.txt";
private List<String> map;
private List<Triple<Integer, Integer, Character>> patrolHistory;
private List<Triple<Integer, Integer, Character>> loopLocations;
//private int loopCounter = 0;
//private int LOOP_MAX = 7;
//private int LOOP_MAX = 100;
public Problem12(){
super();
description = "Find the number of places that a new obstacle could be placed that creates a patrol loop.";
result = "Unresolved";
}
public String runSolution(){
Stopwatch timer = new Stopwatch();
timer.start();
throw new RuntimeException("This problem is not yet solved");
//Read the file
/*
map = new ArrayList<>();
try(Scanner scanner = new Scanner(this.getClass().getClassLoader().getResourceAsStream(inputFileName))){
scanner.useDelimiter("\n");
while(scanner.hasNext()){
map.add(scanner.next());
}
}
/* */
//Answer: 6
/*
map = new ArrayList<>(List.of(
"....#.....",
".........#",
"..........",
"..#.......",
".......#..",
"..........",
".#..^.....",
"........#.",
"#.........",
"......#..."
));
/* */
//Answer: 19
/*
map = new ArrayList<>(List.of(
"...........#.....#......",
"...................#....",
"...#.....##.............",
"......................#.",
"..................#.....",
"..#.....................",
"....................#...",
"........................",
".#........^.............",
"..........#..........#..",
"..#.....#..........#....",
"........#.....#..#......"
));
/* */
/*
//Find the current location of the guard
Triple<Integer, Integer, Character> currentLocation = findInitialLocation();
patrolHistory = new ArrayList<>();
loopLocations = new ArrayList<>();
//printMap();
//Loop while the guard is still on the map
traverseMap(currentLocation, false);
//printMap();
placePotentialLoops();
//System.out.println("\n\n");
printMap();
//Save the results
timer.stop();
result = "The number of positions that a new object could be placed to create a patrol loop is " + loopLocations.size() + ".\nIt took " + timer.toString() + " to run the algorithm.";
return result;
/* */
}
private Triple<Integer, Integer, Character> findInitialLocation(){
for(int row = 0;row < map.size();++row){
String mapLine = map.get(row);
int startIndex = mapLine.indexOf("^");
if(startIndex != -1){
return new Triple<>(row, startIndex, '^');
}
}
//If it gets this far it was not found
return new Triple<>(-1, -1, '\0');
}
private void traverseMap(Triple<Integer, Integer, Character> currentLocation, boolean loopCheck){
boolean inBounds = true;
while(inBounds){
if(patrolHistory.contains(currentLocation)){
patrolHistory.add(currentLocation);
break;
}
else{
patrolHistory.add(currentLocation);
}
//Move in that direction as far as possible
if(currentLocation.getC() == '^'){
currentLocation = moveUp(currentLocation, loopCheck);
}
else if(currentLocation.getC() == '>'){
currentLocation = moveRight(currentLocation, loopCheck);
}
else if(currentLocation.getC() == 'v'){
currentLocation = moveDown(currentLocation, loopCheck);
}
else if(currentLocation.getC() == '<'){
currentLocation = moveLeft(currentLocation, loopCheck);
}
else{
throw new RuntimeException("There was an error in the location: " + currentLocation);
}
//Determine if still in bounds
//if(loopCounter > LOOP_MAX || currentLocation.getC() == '\0'){
if(currentLocation.getC() == '\0'){
inBounds = false;
}
//++loopCounter;
}
}
private Triple<Integer, Integer, Character> moveUp(Triple<Integer, Integer, Character> currentLocation, boolean loopCheck){
while(true){
String currentMapString = map.get(currentLocation.getA());
//If the current Y value is == 0 then the guard left the area
if(currentLocation.getA() == 0){
currentMapString = currentMapString.replace("^", "X");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(-1, -1, '\0');
}
String nextMapString = map.get(currentLocation.getA() - 1);
//If the next Y value contains a # then the guard needs to move to the next stage
if(nextMapString.charAt(currentLocation.getB()) == '#'){
currentMapString = currentMapString.replace("^", ">");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(currentLocation.getA(), currentLocation.getB(), '>');
}
//If the next Y value is a . or X then move to the new location and mark the current location with an X
else{
currentMapString = currentMapString.replace("^", "X");
map.set(currentLocation.getA(), currentMapString);
StringBuilder newMapString = new StringBuilder(nextMapString);
newMapString.setCharAt(currentLocation.getB(), '^');
map.set(currentLocation.getA() - 1, newMapString.toString());
currentLocation = new Triple<>(currentLocation.getA() - 1, currentLocation.getB(), '^');
//Check for the potential to create a loop
if(!loopCheck){
Triple<Integer, Integer, Character> potentialLoop = new Triple<>(currentLocation.getA() - 1, currentLocation.getB(), '>');
if(createsLoop(potentialLoop) && !loopContains(potentialLoop)){
loopLocations.add(potentialLoop);
}
}
}
}
}
private Triple<Integer, Integer, Character> moveRight(Triple<Integer, Integer, Character> currentLocation, boolean loopCheck){
while(true){
String currentMapString = map.get(currentLocation.getA());
//If the current X value is == the length of the string then the guard left the area
if(currentLocation.getB() == (currentMapString.length() - 1)){
currentMapString = currentMapString.replace(">", "X");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(-1, -1, '\0');
}
String nextMapString = map.get(currentLocation.getA());
//If the next X value contains a # then the guard needs to move to the next stage
if(nextMapString.charAt(currentLocation.getB() + 1) == '#'){
currentMapString = currentMapString.replace(">", "v");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(currentLocation.getA(), currentLocation.getB(), 'v');
}
//If the next X value is a . or X then move to the new location and mark the current location with an X
else{
currentMapString = currentMapString.replace(">", "X");
map.set(currentLocation.getA(), currentMapString);
StringBuilder newMapString = new StringBuilder(nextMapString);
newMapString.setCharAt(currentLocation.getB() + 1, '>');
map.set(currentLocation.getA(), newMapString.toString());
currentLocation = new Triple<>(currentLocation.getA(), currentLocation.getB() + 1, '>');
//Check for the potential to create a loop
if(!loopCheck){
Triple<Integer, Integer, Character> potentialLoop = new Triple<>(currentLocation.getA(), currentLocation.getB() + 1, 'v');
if(createsLoop(potentialLoop) && !loopContains(potentialLoop)){
loopLocations.add(potentialLoop);
}
}
}
}
}
private Triple<Integer, Integer, Character> moveDown(Triple<Integer, Integer, Character> currentLocation, boolean loopCheck){
while(true){
String currentMapString = map.get(currentLocation.getA());
//If the current Y value is == the length of the string then the guard left the area
if(currentLocation.getA() == (map.size() - 1)){
currentMapString = currentMapString.replace("v", "X");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(-1, -1, '\0');
}
String nextMapString = map.get(currentLocation.getA() + 1);
//If the next Y value contains a # then the guard needs to move to the next stage
if(nextMapString.charAt(currentLocation.getB()) == '#'){
currentMapString = currentMapString.replace("v", "<");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(currentLocation.getA(), currentLocation.getB(), '<');
}
//If the next Y value is a . or X then move to the new location and mark the current location with an X
else{
currentMapString = currentMapString.replace("v", "X");
map.set(currentLocation.getA(), currentMapString);
StringBuilder newMapString = new StringBuilder(nextMapString);
newMapString.setCharAt(currentLocation.getB(), 'v');
map.set(currentLocation.getA() + 1, newMapString.toString());
currentLocation = new Triple<>(currentLocation.getA() + 1, currentLocation.getB(), 'v');
//Check for the potential to create a loop
if(!loopCheck){
Triple<Integer, Integer, Character> potentialLoop = new Triple<>(currentLocation.getA() + 1, currentLocation.getB(), '<');
if(createsLoop(potentialLoop) && !loopContains(potentialLoop)){
loopLocations.add(potentialLoop);
}
}
}
}
}
private Triple<Integer, Integer, Character> moveLeft(Triple<Integer, Integer, Character> currentLocation, boolean loopCheck){
while(true){
String currentMapString = map.get(currentLocation.getA());
//If the current X value is == 0 then the guard left the area
if(currentLocation.getB() == 0){
currentMapString = currentMapString.replace("<", "X");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(-1, -1, '\0');
}
String nextMapString = map.get(currentLocation.getA());
//If the next X value contains a # then the guard needs to move to the next stage
if(nextMapString.charAt(currentLocation.getB() - 1) == '#'){
currentMapString = currentMapString.replace("<", "^");
map.set(currentLocation.getA(), currentMapString);
return new Triple<>(currentLocation.getA(), currentLocation.getB(), '^');
}
//If the next X value is a . or X then move to the new location and mark the current location with an X
else{
currentMapString = currentMapString.replace("<", "X");
map.set(currentLocation.getA(), currentMapString);
StringBuilder newMapString = new StringBuilder(nextMapString);
newMapString.setCharAt(currentLocation.getB() - 1, '<');
map.set(currentLocation.getA(), newMapString.toString());
currentLocation = new Triple<>(currentLocation.getA(), currentLocation.getB() - 1, '<');
//Check for the potential to create a loop
if(!loopCheck){
Triple<Integer, Integer, Character> potentialLoop = new Triple<>(currentLocation.getA(), currentLocation.getB() - 1, '^');
if(createsLoop(potentialLoop)){
loopLocations.add(potentialLoop);
}
}
}
}
}
private boolean createsLoop(Triple<Integer, Integer, Character> newObstacleLocation){
if(loopContains(newObstacleLocation)){
return false;
}
if(newObstacleLocation.getA() >= map.size()){
return false;
}
if(newObstacleLocation.getA() < 0){
return false;
}
if(newObstacleLocation.getB() >= map.get(newObstacleLocation.getA()).length()){
return false;
}
if(newObstacleLocation.getB() < 0){
return false;
}
if(map.get(newObstacleLocation.getA()).charAt(newObstacleLocation.getB()) != '.'){
return false;
}
boolean loop = false;
List<String> originalMap = new ArrayList<>(map);
List<Triple<Integer, Integer, Character>> originalHistory = new ArrayList<>(patrolHistory);
patrolHistory = new ArrayList<>();
//int orgLoopCnt = loopCounter;
//loopCounter = 0;
//int orgLoopMax = LOOP_MAX;
//LOOP_MAX = 1000;
StringBuilder mapLine = new StringBuilder(map.get(newObstacleLocation.getA()));
mapLine.setCharAt(newObstacleLocation.getB(), '#');
map.set(newObstacleLocation.getA(), mapLine.toString());
traverseMap(originalHistory.get(0), true);
/* */
if(newObstacleLocation.getC() == '^'){
//traverseMap(new Triple<>(newObstacleLocation.getA(), newObstacleLocation.getB() + 1, newObstacleLocation.getC()), true);
}
else if(newObstacleLocation.getC() == '>'){
//traverseMap(new Triple<>(newObstacleLocation.getA() + 1, newObstacleLocation.getB(), newObstacleLocation.getC()), true);
}
else if(newObstacleLocation.getC() == 'v'){
//traverseMap(new Triple<>(newObstacleLocation.getA(), newObstacleLocation.getB() - 1, newObstacleLocation.getC()), true);
}
else if(newObstacleLocation.getC() == '<'){
//traverseMap(new Triple<>(newObstacleLocation.getA() - 1, newObstacleLocation.getB(), newObstacleLocation.getC()), true);
}
/* */
int lastLocation = patrolHistory.indexOf(patrolHistory.get(patrolHistory.size() - 1));
if((lastLocation != -1) && (lastLocation != patrolHistory.size() - 1)){
loop = true;
}
map = originalMap;
patrolHistory = originalHistory;
//loopCounter = orgLoopCnt;
//LOOP_MAX = orgLoopMax;
return loop;
}
private boolean loopContains(Triple<Integer, Integer, Character> loopLocation){
for(Triple<Integer, Integer, Character> location : loopLocations){
if(location.getA() == loopLocation.getA() && location.getB() == loopLocation.getB()){
return true;
}
}
return false;
}
private void printMap(){
for(String mapLine : map){
System.out.println(mapLine);
}
}
private void placePotentialLoops(){
for(Triple<Integer, Integer, Character> loopLocation : loopLocations){
StringBuilder mapLine = new StringBuilder(map.get(loopLocation.getA()));
mapLine.setCharAt(loopLocation.getB(), 'O');
map.set(loopLocation.getA(), mapLine.toString());
}
}
}
//! Too small
/*
360
*/
//! Too large
/*
1938
*/
//! ?
/*
1065
*/
//! ?
/*
Find the number of places that a new obstacle could be placed that creates a patrol loop.
The number of positions that a new object could be placed to create a patrol loop is 1682.
It took 1.641 seconds to run the algorithm.
*/
//! How?
/*
1723
*/

View File

@@ -0,0 +1,130 @@
.............#........................................................#...#...........................................#...........
.....#...............................#.........................................#...#...............#........##...............#.#..
..................................#..................#.......................................#...#................................
.........................................#................#....#..............................................#................#.#
........#.........................................................#...........#.......#..............................#............
........................#.............................#.......................#.......#.......................#........#.........#
................................#.......#............................................#...........................................#
...........#........#...#..#...........................#..................#.............#.......#..........................#......
............................................#........#.......#..#......#..............................#..#................##......
............#..#...#......#.........................................##.......#..........#.......#...................#.............
.....................................................................................#.....#......................................
.......................................................#................#.....................................#...................
...........#.....#.#....................................#.......#.#...........#................#.......#.................#........
............#.............#....................#....#............................#.........................................#......
.#..........#......#................#........................#............#..#..............#.....................................
..................#....#...........................................#.....#.....#.........................................#.#......
.............#..............#..#...........................#..#..........#...............................#........................
.................................................................................................#................................
.......................................................#..............#..............................................#..#.........
......#............................#.......................#................................................................#.....
..........#.........#..................#....#....#...#......#.........#.................................#........................#
..#...#............................#............#.......###.................................#.............................#...#...
.................#....#...................#........................................................................#..........#...
....#..........................#......................................................................#.....#......#..............
.#........................................................................#..........#............#..................#............
...................##.#.......................#....#.#........................................#.........##........................
#...........................................................#..........#........#.#..................................#............
.......#...#.........................................#.......#........#...............##..#.......................................
......................#....#...............................#......................................................#..#............
......#.....................................................#...............................#......................#..#...........
.........................#.#......................................................................................................
.......................................#...............#...................#................#..........#.#......................#.
.......#......#...#...........................#.........................#...............#..#...............#.............##.......
.....#..#..#..................#............#......................................................#...#.........................#.
#.#...............#...........#................#...................................................#..........#...................
..........................................................................#...............................................#.......
.........#.......#..........................#.##.............................#..##...#.......................................#....
....#...............#..........#........................................#.....#.........................................#.........
...........#................................................#....##...................................................#..#........
........................#........#...........#...#............................................#......................##...........
......#........................................#...#.............................................#................................
#.....#......#..................................#.............#..#...............................#................................
..................#......................#..........#...................#............................................#....#.......
.................#.............................................................................#.......#..........................
......#........................................................................................#...#....................#.........
....#......................#..................##..................#.......#.......................#...........#.........#..#......
............................................................#......##.............................#.#.....#............#..........
..............#.......................#...^.....................................#.....................................#...........
..............#...##......#..#.....#..........................................................................#.......#.........#.
.#................................................................#........##......#....#.......#.................................
....#.....................#........#...........#.............................................#........#................#......#..#
...................#.............#.........#.........................#...........#..................#...................#....#....
.#...............................................#.....#..#...#...................................................................
........................##............#.....................................#........#..................................#.........
..............#................................#.....................................#...................................#........
...........#..........#...........#........#...................#..#..........................#....................................
.#..............................................................#....#.......#.....................................#..............
.....................#........#......#................#.............#........................#.......................#........#...
.........................#..............#...#....#..................#.............................................................
..#............................##.........................................................#...........................#.#..#......
.....#............#...##........#..........#....#......#................................#.................#...............#....#..
.....#...............#.............................#............#......#....#........................................#............
...#..........#.........#.....................##.......#.....#...................#................................................
.................................#...........................................#.................#...........................#......
..........................................................#........................#.......#.................................#...#
..#......#......................................#...#..#....................#...........#....#.............................#......
..#........#.............#......................#...#.....#....#........................#..#......................................
.........#...........#.......................................................................#.........#....#...#.................
..................................#....#.............##....#.......#.........#.........................................#..........
....#.................................................#.......#...........#.......................................##.....#........
..............................#.........................................................#.....#........................#..........
...#........#...........#..#..................................................#..............#.............................#......
................................................#...............................................................#.....#..#.....#..
...............#.........................#..#...................#....................................#................#...........
............................#...........................................................................................#.........
.....#.........................#.......#..#..##.............................#................##.......##............#.............
.........#........................................................................................................................
.........................#............................#........................#.....#..........#.....................#...#..#....
.......#........#..............................#..........................#...#.................#............#....................
#...#..#...............................#..........................................#...#...#.........................#.............
...........................................................#..............#..........#..................#.........................
...........................................................#..............................................................#....#..
...........#.......................#................#......#.....................................#..................#.....#.......
.....#.................................#........................#.#...................#.....#............#........................
...........................#.#............#..............#..............#..#...#..........................#................#......
.........#...................#........................#......#..#..................................................#..............
.............................................#.................................................................#.......#.......#..
#.......................#...............#.......................#...........#................................#....................
......................................#............#....................................................##...................#....
#...............#...........................................#......#....................................#...............#.........
...#...............#.................................#..................................#..#............#.........................
......................#..#............#..#..............................................#......#....#...............#.............
..................#.....................#.....#...................#..#................#....#..........#......#..........#.........
.......................#.....#..............#..........................#............#...................#.#.......................
......#...........#..............#........#........................................#......................................#.......
............#................#..##....................................................................#........................#..
...........#....................................#.............................#.....#....#...#.#......................#...........
...................................................#...............................#....................#.........#...............
........#......#..#................#..................................................................#.................#.........
.............................#................................................#...........#.....#....#............................
........#.............#.........#............#....#.....................#........#...............#................................
..#................................#................................#..#......#.............................................#.....
.........#...........................................#..................................#....#..#.....................#...........
.....................................................#.........................................................#..................
.........#...#.#.....#.......##................................#...#..........................#........#..........................
......................##...............................#..........................................................................
.........#...#.....#........................................#................#........#............#........#.....................
...............#............#.................................................................#................................#..
......#..............#...................................................#............#.....................#.....................
.........#.........#..............................................................................................................
.#........#...............#..##......#..............................#...........#..#.........#...........................#........
...................#................................................................................#...............#.............
..............................................................................#........................#................#.........
...........#.....#..#.#....................................................#......#......#..#................##...................
....#......#...................................................................#..............#.....#.........#..................#
..#...........#...#...........#.......##..........##......................#......................................................#
..................#................................................#.#............................................................
#................................................................#............#...##..........................................#...
......#............................................#.......#.#.................................................#..................
..............................#..............#.#....#............#..........................#.....................................
............................#..................................#.................#..#...........................................#.
.........................................#................#..................#...#............................#..#......#........#
....................#..............................................................#..............................#..........##...
...#......................................#...........#..#............................................#.....#....#................
................#..#....#.........................................................................................................
...................................#...................#...............................#................................#.......#.
..........#.................#.............#..................#...............................................................#....
.....#...........#........#................#.........................................#..........................#......##.........
..........................#................#..............................................................#.......................
........#.................................................................#......................#.#..........................#...