added Pair structure
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 10 Dec 2022 04:37:31 +0000 (22:37 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 10 Dec 2022 04:37:31 +0000 (22:37 -0600)
core/container/pair.onyx [new file with mode: 0644]
core/std.onyx
tests/aoc-2021/day14.onyx
tests/aoc-2021/day21.onyx

diff --git a/core/container/pair.onyx b/core/container/pair.onyx
new file mode 100644 (file)
index 0000000..292b2cc
--- /dev/null
@@ -0,0 +1,41 @@
+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
index 1b03d81123ef2a3f8a437d84402bf87430ef76a6..7d226994bd2e159a3ec2e44a4388c3f83e4cf297 100644 (file)
@@ -12,6 +12,7 @@ package core
 #load "./container/set"
 #load "./container/bucket_array"
 #load "./container/heap"
+#load "./container/pair"
 
 #load "./conv/conv"
 #load "./conv/format"
index 1da615f43d1a705cb80750a6d19a3e270086b96c..8716771e54b663d6f4591e4e41892b20f440f25e 100644 (file)
@@ -3,14 +3,10 @@
 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;
 }
@@ -42,8 +38,8 @@ main :: (args) => {
             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 {
@@ -59,7 +55,7 @@ main :: (args) => {
         }
 
         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);
         }
 
@@ -70,8 +66,8 @@ main :: (args) => {
                 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);
                     }
@@ -82,7 +78,7 @@ main :: (args) => {
 
         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));
index cce34f153d74fc12d5ae1ea3f2a4047e65b67637..639fb6c562104dfd8d920dde5fed699fc86b38cb 100644 (file)
@@ -214,23 +214,3 @@ main :: () {
 }
 
 }
-
-
-
-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;
-