Skip to content

Commit 9445814

Browse files
committed
2022/23 with iterators
1 parent 28c4e2e commit 9445814

File tree

1 file changed

+52
-72
lines changed

1 file changed

+52
-72
lines changed

2022/Day23/Solution.cs

Lines changed: 52 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -10,100 +10,80 @@ class Solution : Solver {
1010

1111
// I used complex numbers for a change. The map is represented with a hashset of positions.
1212

13-
public object PartOne(string input) {
14-
var state = Parse(input);
15-
for (var i = 0; i < 10; i++) {
16-
state = Step(state);
17-
}
18-
19-
// smallest enclosing rectangle
20-
var width = state.elves.Select(p => p.Real).Max() -
21-
state.elves.Select(p => p.Real).Min() + 1;
13+
public object PartOne(string input)
14+
=> Simulate(Parse(input)).Select(Area).ElementAt(9);
2215

23-
var height = state.elves.Select(p => p.Imaginary).Max() -
24-
state.elves.Select(p => p.Imaginary).Min() + 1;
16+
public object PartTwo(string input)
17+
=> Simulate(Parse(input)).Count();
2518

26-
return width * height - state.elves.Count;
27-
}
19+
IEnumerable<HashSet<Complex>> Simulate(HashSet<Complex> elves) {
20+
var lookAround = new Queue<Complex>(new []{ N, S, W, E });
2821

29-
public object PartTwo(string input) {
30-
// interate until fixpoint is reached
31-
var steps = 0;
22+
for (var fixpoint = false; !fixpoint; lookAround.Enqueue(lookAround.Dequeue())) {
23+
24+
// 1) collect proposals; for each position (key) compute the list of the elves
25+
// who want to step there
26+
var proposals = new Dictionary<Complex, List<Complex>>();
3227

33-
var state = Parse(input);
34-
while (!state.fixpoint) {
35-
state = Step(state);
36-
steps++;
37-
}
38-
39-
return steps;
40-
}
41-
42-
State Step(State state) {
43-
44-
bool occupied(Complex pos) => state.elves.Contains(pos);
45-
bool lonely(Complex pos) => directions.All(dir => !occupied(pos + dir));
46-
47-
// elf proposes a postion if nobody is nearby in that direction
48-
bool proposes(Complex elf, Complex dir) => ExtendDir(dir).All(d => !occupied(elf + d));
49-
50-
// for each position (key) it has a list of the elves who wants to step there
51-
var proposals = new Dictionary<Complex, List<Complex>>();
52-
53-
foreach (var elf in state.elves) {
54-
if (lonely(elf)) {
55-
continue;
56-
}
28+
foreach (var elf in elves) {
29+
var lonely = Directions.All(dir => !elves.Contains(elf + dir));
30+
if (lonely) {
31+
continue;
32+
}
5733

58-
foreach (var dir in state.directions) {
59-
if (proposes(elf, dir)) {
60-
var pos = elf + dir;
61-
if (!proposals.ContainsKey(pos)) {
62-
proposals[pos] = new List<Complex>();
34+
foreach (var dir in lookAround) {
35+
36+
// elf proposes a postion if nobody stands in that direction
37+
var proposes = ExtendDir(dir).All(d => !elves.Contains(elf + d));
38+
if (proposes) {
39+
var pos = elf + dir;
40+
if (!proposals.ContainsKey(pos)) {
41+
proposals[pos] = new List<Complex>();
42+
}
43+
proposals[pos].Add(elf);
44+
break;
6345
}
64-
proposals[pos].Add(elf);
65-
break;
6646
}
6747
}
68-
}
6948

70-
// move elves, compute fixpoint flag
71-
var fixpoint = true;
72-
foreach (var p in proposals) {
73-
var (to, from) = p;
74-
if (from.Count == 1) {
75-
state.elves.Remove(from.Single());
76-
state.elves.Add(to);
77-
fixpoint = false;
49+
// 2) move elves, compute fixpoint flag
50+
fixpoint = true;
51+
foreach (var p in proposals) {
52+
var (to, from) = p;
53+
if (from.Count == 1) {
54+
elves.Remove(from.Single());
55+
elves.Add(to);
56+
fixpoint = false;
57+
}
7858
}
79-
}
8059

81-
return new State(
82-
state.elves,
83-
state.directions.Skip(1).Concat(state.directions.Take(1)).ToList(),
84-
fixpoint
85-
);
60+
yield return elves;
61+
}
8662
}
8763

88-
State Parse(string input) {
89-
var lines = input.Split("\n");
64+
double Area(HashSet<Complex> elves) {
65+
// smallest enclosing rectangle
66+
var width = elves.Select(p => p.Real).Max() -
67+
elves.Select(p => p.Real).Min() + 1;
9068

91-
var elves = (
69+
var height = elves.Select(p => p.Imaginary).Max() -
70+
elves.Select(p => p.Imaginary).Min() + 1;
71+
72+
return width * height - elves.Count;
73+
}
74+
75+
HashSet<Complex> Parse(string input) {
76+
var lines = input.Split("\n");
77+
return (
9278
from irow in Enumerable.Range(0, lines.Length)
9379
from icol in Enumerable.Range(0, lines[0].Length)
9480
where lines[irow][icol] == '#'
9581
select new Complex(icol, irow)
9682
).ToHashSet();
97-
98-
var directions = new List<Complex>() { N, S, W, E };
99-
100-
return new State(elves, directions, fixpoint: false);
10183
}
10284

10385
/// -------
10486

105-
record State(HashSet<Complex> elves, List<Complex> directions, bool fixpoint);
106-
10787
static Complex N = new Complex(0, -1);
10888
static Complex E = new Complex(1, 0);
10989
static Complex S = new Complex(0, 1);
@@ -113,7 +93,7 @@ record State(HashSet<Complex> elves, List<Complex> directions, bool fixpoint);
11393
static Complex SE = S + E;
11494
static Complex SW = S + W;
11595

116-
static Complex[] directions = new[] { NW, N, NE, E, SE, S, SW, W };
96+
static Complex[] Directions = new[] { NW, N, NE, E, SE, S, SW, W };
11797

11898
// Extends an ordinal position with its intercardinal neighbours
11999
Complex[] ExtendDir(Complex dir) =>

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy