Prechádzať zdrojové kódy

Solution for advent of code day 3. (#4713)

Richard Smith 1 rok pred
rodič
commit
a536dbd8d9

+ 16 - 0
examples/advent2024/BUILD

@@ -40,3 +40,19 @@ carbon_binary(
         "day2_part2.carbon",
     ] + utils,
 )
+
+carbon_binary(
+    name = "day3_part1",
+    srcs = [
+        "day3_common.carbon",
+        "day3_part1.carbon",
+    ] + utils,
+)
+
+carbon_binary(
+    name = "day3_part2",
+    srcs = [
+        "day3_common.carbon",
+        "day3_part2.carbon",
+    ] + utils,
+)

+ 45 - 0
examples/advent2024/day3_common.carbon

@@ -0,0 +1,45 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+library "day3_common";
+
+import library "io_utils";
+
+// Reads "mul(a,b)", and returns (true, a, b).
+// On error, stops before the first invalid character and returns (false, 0, 0).
+// TODO: -> Optional((i32, i32))
+fn ReadMul() -> (bool, i32, i32) {
+  var a: i32;
+  var b: i32;
+  if (ConsumeChar(0x6D) and ConsumeChar(0x75) and ConsumeChar(0x6C) and
+      ConsumeChar(0x28) and ReadInt(&a) and ConsumeChar(0x2C) and
+      ReadInt(&b) and ConsumeChar(0x29)) {
+    return (true, a, b);
+  }
+  return (false, 0, 0);
+}
+
+// Reads "do()" or "don't()", and returns (true, was_do).
+// On error, stops before the first invalid character and returns (false, false).
+fn ReadDoOrDont() -> (bool, bool) {
+  // "do"
+  if (not ConsumeChar(0x64) or not ConsumeChar(0x6F)) {
+    return (false, false);
+  }
+
+  var do: bool = true;
+  // "n't"
+  if (ConsumeChar(0x6E)) {
+    if (not ConsumeChar(0x27) or not ConsumeChar(0x74)) {
+      return (false, false);
+    }
+    do = false;
+  }
+
+  // "()"
+  if (not ConsumeChar(0x28) or not ConsumeChar(0x29)) {
+    return (false, false);
+  }
+  return (true, do);
+}

+ 24 - 0
examples/advent2024/day3_part1.carbon

@@ -0,0 +1,24 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import Core library "io";
+
+import library "day3_common";
+import library "io_utils";
+
+fn Run() {
+  var total: i32 = 0;
+  while (PeekChar() != Core.EOF()) {
+    if (PeekChar() == 0x6D) {
+      // TODO: Use `if let` when available.
+      let result: (bool, i32, i32) = ReadMul();
+      if (result.0) {
+        total += result.1 * result.2;
+      }
+    } else {
+      ReadChar();
+    }
+  }
+  Core.Print(total);
+}

+ 31 - 0
examples/advent2024/day3_part2.carbon

@@ -0,0 +1,31 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import Core library "io";
+
+import library "day3_common";
+import library "io_utils";
+
+fn Run() {
+  var total: i32 = 0;
+  var enabled: bool = true;
+  while (PeekChar() != Core.EOF()) {
+    if (PeekChar() == 0x6D) {
+      // TODO: Use `if let` when available.
+      let result: (bool, i32, i32) = ReadMul();
+      if (result.0 and enabled) {
+        total += result.1 * result.2;
+      }
+    } else if (PeekChar() == 0x64) {
+      // TODO: Use `if let` when available.
+      let result: (bool, bool) = ReadDoOrDont();
+      if (result.0) {
+        enabled = result.1;
+      }
+    } else {
+      ReadChar();
+    }
+  }
+  Core.Print(total);
+}

+ 19 - 16
examples/advent2024/io_utils.carbon

@@ -44,30 +44,33 @@ fn ReadInt(p: i32*) -> bool {
   return read_any_digits;
 }
 
+fn PeekChar() -> i32 {
+  var next: i32 = ReadChar();
+  UnreadChar(next);
+  return next;
+}
+
+fn ConsumeChar(c: i32) -> bool {
+  var next: i32 = ReadChar();
+  if (next != c) {
+    UnreadChar(next);
+    return false;
+  }
+  return true;
+}
+
 fn SkipSpaces() -> bool {
   var skipped_any_spaces: bool = false;
-  while (true) {
-    var c: i32 = ReadChar();
-    if (c != 0x20) {
-      UnreadChar(c);
-      break;
-    }
+  while (ConsumeChar(0x20)) {
     skipped_any_spaces = true;
   }
   return skipped_any_spaces;
 }
 
 fn SkipNewline() -> bool {
-  var c: i32 = ReadChar();
   // Optional carriage return.
-  if (c == 0x0D) {
-    c = ReadChar();
-  }
+  ConsumeChar(0x0D);
   // Newline.
-  if (c == 0x0A) {
-    return true;
-  }
-  // TODO: Unread the CR?
-  UnreadChar(c);
-  return false;
+  // TODO: Unread the CR if it was present?
+  return ConsumeChar(0x0A);
 }