-
Notifications
You must be signed in to change notification settings - Fork 1
/
day25.c3
125 lines (110 loc) · 2.95 KB
/
day25.c3
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
120
121
122
123
124
125
/*
* Advent of Code 2023 day 25
*/
import std::io;
import std::time;
import std::math;
import std::collections::list;
import std::sort;
import std::collections::map;
fn void main()
{
io::printn("Advent of code, day 25.");
@pool()
{
// Simple benchmarking with Clock, "mark" returns the last duration and resets the clock
Clock c = clock::now();
io::printfn("* Sizes part 1: %d - completed in %s", part1(), c.mark());
};
}
struct Edge
{
long a;
long b;
}
def NameMap = HashMap(<String, long>);
def EdgeList = List(<Edge>);
fn long part1()
{
File f = file::open("day25.txt", "rb")!!;
defer (void)f.close();
NameMap map;
map.temp_init(2048);
EdgeList original_list;
original_list.temp_init(2048);
// Parse graph
while (try line = io::readline(&f))
{
String[] parts = line.split(": ", 2);
String lhs = parts[0];
long id = map.@get_or_set(lhs, (long)map.len());
foreach (node : parts[1].split(" "))
{
long other = map.@get_or_set(node, (long)map.len());
original_list.push({ id, other });
}
}
const long ID_MULT = 10000;
// Set a maximum for number of tries, in case we have a bug! :D
for (int loop = 0; loop < 1000000; loop++)
{
@pool()
{
// We have an id counter for our new merged nodes.
long id = 0;
assert(map.len() < ID_MULT, "Too many edges!");
// Make a copy
EdgeList list;
list.temp_init(2048);
list.add_all(&original_list);
// Until we (maybe) have three wires
while (list.len() > 3)
{
// Grab one edge
int remove_index = rand((int)list.len());
Edge e = list[remove_index];
// Check the number of nodes already merged:
// we have ID_MULT * id + merged nodes
// unless it's a non-generated node.
long a_count = e.a < ID_MULT ? 1 : e.a % ID_MULT;
long b_count = e.b < ID_MULT ? 1 : e.b % ID_MULT;
// Create a new node according to the above
id++;
long new = id * ID_MULT + a_count + b_count;
// Remove the edge.
list.remove_at(remove_index);
// Walk through the edges
usz len = list.len();
for (usz i = 0; i < len; i++)
{
Edge* other = &list[i];
// Replace with the new merged vertex
if (other.a == e.a || other.a == e.b) other.a = new;
if (other.b == e.a || other.b == e.b) other.b = new;
// Remove any loops
if (other.a == other.b)
{
list.remove_at(i);
len--;
i--;
}
}
}
// We're done, so we now check if we only have two groups left
// (joined by 3 edges)
List(<long>) elements;
elements.temp_init(16);
foreach (e : list)
{
if (!elements.contains(e.a)) elements.push(e.a);
if (!elements.contains(e.b)) elements.push(e.b);
}
// If we don't have it - keep looking.
if (elements.len() != 2) continue;
// We found the solution, return it as node_id % ID_MULT == number of nodes
// Here we assume both nodes have been merged!
return (elements[0] % ID_MULT) * (elements[1] % ID_MULT);
};
}
assert(false, "No solution");
}