initial commit, day 10
This commit is contained in:
238
dotnet/06/06.cs
Normal file
238
dotnet/06/06.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
void Main1()
|
||||
{
|
||||
(var map, var pos) = LoadMap(Path.Join("..", "..", "06a.txt"));
|
||||
Guard guard = new(pos, Direction.North);
|
||||
HashSet<(int,int)> visited = new();
|
||||
while (map.InBounds(guard.position))
|
||||
{
|
||||
var next = Next(guard);
|
||||
if (map.Check(next.position))
|
||||
{
|
||||
guard = new(guard.position, guard.direction.Turn());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
visited.Add(guard.position);
|
||||
guard = next;
|
||||
}
|
||||
}
|
||||
Console.WriteLine(visited.Count());
|
||||
}
|
||||
|
||||
void Main2()
|
||||
{
|
||||
(var map, var pos) = LoadMap(Path.Join("..", "..", "06a.txt"));
|
||||
Guard guard = new(pos, Direction.North);
|
||||
// for (int i = 0; i < 4; i++)
|
||||
// {
|
||||
// foreach (var obs in map.Obstacles)
|
||||
// {
|
||||
// var row = map.GetRow(obs.Item1 + 1).Where(c => c > obs.Item2);
|
||||
// foreach (var candidate in row)
|
||||
// {
|
||||
// var col = map.GetColumn(candidate - 1).Where(r => r > candidate);
|
||||
// foreach (var third in col)
|
||||
// {
|
||||
// var idea = (third - 1, obs.Item2 - 1);
|
||||
// if (!map.Check(idea))
|
||||
// map.Ideas.Add(idea);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// map = map.Rotated();
|
||||
// }
|
||||
// Console.WriteLine($"Ideas {map.Ideas.Count()}");
|
||||
int count = 0;
|
||||
// foreach (var idea in map.Ideas)
|
||||
// {
|
||||
// Guard guard = new(pos, Direction.North);
|
||||
// // the 5th time the guard hits the obstacle, he must have hit twice from the same side
|
||||
// int hits = 0;
|
||||
// while (map.InBounds(guard.position))
|
||||
// {
|
||||
// var next = Next(guard);
|
||||
// if (next.position == idea)
|
||||
// {
|
||||
// hits++;
|
||||
// if (hits >= 5)
|
||||
// {
|
||||
// count++;
|
||||
// break;
|
||||
// }
|
||||
// guard = new(guard.position, guard.direction.Turn());
|
||||
// }
|
||||
// else if (map.Check(next.position))
|
||||
// {
|
||||
// guard = new(guard.position, guard.direction.Turn());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// guard = next;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
HashSet<(int,int)> visited = new();
|
||||
int ideaIndex = 0;
|
||||
while (map.InBounds(guard.position))
|
||||
{
|
||||
ideaIndex++;
|
||||
var next = Next(guard);
|
||||
if (map.Check(next.position))
|
||||
{
|
||||
guard = new(guard.position, guard.direction.Turn());
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
visited.Add(guard.position);
|
||||
if (!visited.Contains(next.position) && TestIdea(next.position, guard, map))
|
||||
count++;
|
||||
// Console.WriteLine($"Idea {ideaIndex}");
|
||||
guard = next;
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"Solution {count}");
|
||||
}
|
||||
|
||||
// Main1();
|
||||
Main2();
|
||||
|
||||
(Map,(int,int)) LoadMap(string filename)
|
||||
{
|
||||
var lines = File.ReadAllLines(filename)
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s))
|
||||
.ToList();
|
||||
var guard = (-1,-1);
|
||||
Map map = new();
|
||||
for (int i = 0; i < lines.Count(); i++)
|
||||
{
|
||||
for (int j = 0; j < lines[i].Count(); j++)
|
||||
{
|
||||
if (lines[i][j] == '#')
|
||||
map.Add((i, j));
|
||||
else if (lines[i][j] == '^')
|
||||
guard = (i, j);
|
||||
}
|
||||
}
|
||||
map.XBound = lines[0].Count();
|
||||
map.YBound = lines.Count();
|
||||
return (map, guard);
|
||||
}
|
||||
|
||||
bool TestIdea((int,int) idea, Guard guard, Map map)
|
||||
{
|
||||
HashSet<Guard> history = new();
|
||||
while (map.InBounds(guard.position))
|
||||
{
|
||||
if (history.Contains(guard))
|
||||
return true;
|
||||
history.Add(guard);
|
||||
var next = Next(guard);
|
||||
if (map.Check(next.position) || next.position == idea)
|
||||
{
|
||||
guard = new(guard.position, guard.direction.Turn());
|
||||
}
|
||||
else
|
||||
{
|
||||
guard = next;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//next position IF NO OBSTACLE
|
||||
Guard Next(Guard guard)
|
||||
{
|
||||
var pos = guard.position;
|
||||
return new(guard.direction switch
|
||||
{
|
||||
Direction.North => (pos.Item1-1, pos.Item2),
|
||||
Direction.East => (pos.Item1, pos.Item2+1),
|
||||
Direction.South => (pos.Item1+1, pos.Item2),
|
||||
Direction.West => (pos.Item1, pos.Item2-1),
|
||||
_ => throw new Exception(),
|
||||
}, guard.direction);
|
||||
}
|
||||
|
||||
class Map
|
||||
{
|
||||
public HashSet<(int,int)> Obstacles = new();
|
||||
//1 greater than largest value
|
||||
public int XBound = 0;
|
||||
public int YBound = 0;
|
||||
public HashSet<(int,int)> Ideas = new();
|
||||
public Map()
|
||||
{
|
||||
|
||||
}
|
||||
public void Add((int,int) obstacle)
|
||||
{
|
||||
Obstacles.Add(obstacle);
|
||||
}
|
||||
public bool Check((int,int) pos)
|
||||
{
|
||||
return Obstacles.Contains(pos);
|
||||
}
|
||||
public bool InBounds((int,int) pos)
|
||||
{
|
||||
return pos.Item1 >= 0 && pos.Item2 >= 0
|
||||
&& pos.Item1 < XBound && pos.Item2 < YBound;
|
||||
}
|
||||
//get list of columns with an obstacle in this row
|
||||
public List<int> GetRow(int row)
|
||||
{
|
||||
List<int> items = [];
|
||||
foreach (var pos in Obstacles)
|
||||
{
|
||||
if (pos.Item1 == row)
|
||||
items.Add(pos.Item2);
|
||||
}
|
||||
items.Sort();
|
||||
return items;
|
||||
}
|
||||
//get list of rows with an obstacle in this column
|
||||
public List<int> GetColumn(int column)
|
||||
{
|
||||
List<int> items = [];
|
||||
foreach (var pos in Obstacles)
|
||||
{
|
||||
if (pos.Item2 == column)
|
||||
items.Add(pos.Item1);
|
||||
}
|
||||
items.Sort();
|
||||
return items;
|
||||
}
|
||||
//counterclockwise rotation
|
||||
public Map Rotated()
|
||||
{
|
||||
(int,int) rotate((int,int) o) => (o.Item2, XBound - o.Item1);
|
||||
Map newmap = new();
|
||||
newmap.Obstacles = new(Obstacles.Select(rotate));
|
||||
newmap.Ideas = new(Ideas.Select(rotate));
|
||||
newmap.XBound = YBound;
|
||||
newmap.YBound = XBound;
|
||||
return newmap;
|
||||
}
|
||||
}
|
||||
|
||||
enum Direction
|
||||
{
|
||||
North,
|
||||
East,
|
||||
South,
|
||||
West,
|
||||
}
|
||||
readonly record struct Guard((int,int) position, Direction direction);
|
||||
|
||||
static class Extensions
|
||||
{
|
||||
public static Direction Turn(this Direction direction)
|
||||
{
|
||||
return direction switch
|
||||
{
|
||||
Direction.West => Direction.North,
|
||||
Direction d => d + 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user