--- /dev/null
+package core
+
+//
+// A `Pair` represents a pair of values of heterogenous types.
+// This structure does not do much on its own; however, it
+// is useful because provides overloads for formatting, hashing
+// and equality. This means you can use a `Pair(T, R)` as a key
+// for a Map or Set out of the box, provided T and R are hashable
+// and equatable.
+//
+
+@conv.Custom_Format.{#solidify _format {First_Type=First_Type, Second_Type=Second_Type}}
+Pair :: struct (First_Type: type_expr, Second_Type: type_expr) {
+ first: First_Type;
+ second: Second_Type;
+}
+
+#inject Pair {
+ make :: (x: $X, y: $Y) => Pair(X, Y).{x, y};
+
+ _format :: (output: ^conv.Format_Output, format: ^conv.Format, p: ^Pair($First_Type, $Second_Type)) {
+ conv.format(output, "({}, {})", p.first, p.second);
+ }
+}
+
+#overload
+core.hash.to_u32 :: (p: Pair($First_Type/hash.Hashable, $Second_Type/hash.Hashable)) => {
+ h := 7;
+ h += h << 5 + hash.to_u32(p.first);
+ h += h << 5 + hash.to_u32(p.second);
+ return h;
+}
+
+
+#operator == (p1, p2: Pair($First_Type/Equatable, $Second_Type/Equatable)) => {
+ return p1.first == p2.first && p1.second == p2.second;
+}
+
+#local Equatable :: interface (t: $T) {
+ { t == t } -> bool;
+}
\ No newline at end of file
#load "./container/set"
#load "./container/bucket_array"
#load "./container/heap"
+#load "./container/pair"
#load "./conv/conv"
#load "./conv/format"
use package core
Rule :: struct {
- pair: Pair;
+ pair: Pair(u8, u8);
insert: u8;
}
-Pair :: struct {a, b:u8;}
-#match hash.to_u32 (p: Pair) => cast(u32) (p.a * 3 + p.b * 7);
-#operator == (p1, p2: Pair) => p1.a == p2.a && p1.b == p2.b;
-
State :: struct {
now, next: u64;
}
io.skip_whitespace(^reader);
}
- polymer_state: Map(Pair, State);
- add_to_state :: macro (pair: Pair, count: u64) {
+ polymer_state: Map(Pair(u8, u8), State);
+ add_to_state :: macro (pair: Pair(u8, u8), count: u64) {
if polymer_state->has(pair) {
(^polymer_state[pair]).next += ~~count;
} else {
}
for start_polymer.count - 1 {
- p := Pair.{ start_polymer[it], start_polymer[it + 1] };
+ p := Pair(u8, u8).{ start_polymer[it], start_polymer[it + 1] };
add_to_state(p, 1);
}
pair_count := ^polymer_state[rule.pair];
if pair_count != null {
if pair_count.now > 0 {
- pair1 := Pair.{ rule.pair.a, rule.insert };
- pair2 := Pair.{ rule.insert, rule.pair.b };
+ pair1 := Pair(u8, u8).{ rule.pair.first, rule.insert };
+ pair2 := Pair(u8, u8).{ rule.insert, rule.pair.second };
add_to_state(pair1, pair_count.now);
add_to_state(pair2, pair_count.now);
}
mode: Map(u8, u64);
for^ polymer_state.entries {
- mode[it.key.b] = mode[it.key.b] + it.value.now;
+ mode[it.key.second] = mode[it.key.second] + it.value.now;
}
maximum := array.fold(mode.entries, cast(u64) 0, (x, y) => math.max(x.value, y));
}
}
-
-
-
-Pair :: struct (T1: type_expr, T2: type_expr) {
- first: T1;
- second: T2;
-}
-
-#inject Pair {
- hash :: (p: Pair($T/hash.Hashable, $R/hash.Hashable)) -> u32 {
- h := 7;
- h += h << 5 + hash.to_u32(p.first);
- h += h << 5 + hash.to_u32(p.second);
- return h;
- }
-}
-
-#operator == (p1: Pair, p2: typeof p1) =>
- p1.first == p2.first && p1.second == p2.second;
-