initial commit, day 10

This commit is contained in:
Ikatono
2024-12-10 14:36:10 -06:00
commit e9df3737e1
19 changed files with 2157 additions and 0 deletions

238
dotnet/06/06.cs Normal file
View 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,
};
}
}