-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path23.cs
More file actions
119 lines (104 loc) · 2.78 KB
/
23.cs
File metadata and controls
119 lines (104 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System.Text;
HashSet<Point> elves = new();
for (var i = 0; Console.ReadLine() is { } line; ++i)
{
for (var j = 0; j < line.Length; ++j)
{
if (line[j] == '#')
{
elves.Add(new(j, i));
}
}
}
Dictionary<Point, List<Point>> intention = new();
List<Point[]> offsets = new()
{
new Point[] {new(-1, -1), new(0, -1), new(1, -1)},
new Point[] {new(-1, 1), new(0, 1), new(1, 1)},
new Point[] {new(-1, -1), new(-1, 0), new(-1, 1)},
new Point[] {new(1, -1), new(1, 0), new(1, 1)}
};
for (var round = 0; ; ++round)
{
if (round == 10)
{
Console.WriteLine($"Empty tiles after round 10: {EmptyTiles()}");
}
intention.Clear();
foreach (var elf in elves)
{
if (offsets.SelectMany(a => a.Select(p => p)).All(p => !elves.Contains(elf + p)))
{
continue;
}
for (var dir = 0; dir < 4; ++dir)
{
var searchPoints = offsets[dir];
var free = true;
for (var i = 0; i < 3; ++i)
{
var offset = searchPoints[i];
var target = elf + offset;
if (elves.Contains(target))
{
free = false;
}
}
if (free)
{
var offset = searchPoints[1];
var target = elf + offset;
if (!intention.TryGetValue(target, out var list))
{
list = new List<Point>();
intention[target] = list;
}
list.Add(elf);
break;
}
}
}
var first = offsets[0];
offsets.RemoveAt(0);
offsets.Add(first);
var moved = false;
foreach (var (target, list) in intention)
{
if (list.Count == 1)
{
elves.Remove(list[0]);
elves.Add(target);
moved = true;
}
}
if (!moved)
{
Console.WriteLine($"No elf moved in round {round + 1}");
break;
}
}
int EmptyTiles()
{
int xMin = elves.Min(p => p.X),
xMax = elves.Max(p => p.X),
yMin = elves.Min(p => p.Y),
yMax = elves.Max(p => p.Y);
var sb = new StringBuilder();
for (var y = yMin; y <= yMax; ++y)
{
for (var x = xMin; x <= xMax; ++x)
{
Point p = new(x, y);
sb.Append(elves.Contains(p) ? '#' : '.');
}
sb.AppendLine();
}
var area = (xMax - xMin + 1) * (yMax - yMin + 1);
Console.WriteLine($"{elves.Count} elves enclosed in area {area}");
Console.WriteLine(sb.ToString());
return area - elves.Count;
}
internal sealed record Point(int X, int Y)
{
public static Point operator +(Point a, Point b) => new(a.X + b.X, a.Y + b.Y);
}