[2022][ruby][11.x] parslet
change kuzzyvonwrkmowrwsstplulwplquxvkv
commit 54a04a8f68a93d67be92fb5ac91af634fb69ccfc
author Alpha Chen <alpha@kejadlen.dev>
date
parent oslknkyu
diff --git a/2022/ruby/Gemfile b/2022/ruby/Gemfile
new file mode 100644
index 0000000..3e53076
--- /dev/null
+++ b/2022/ruby/Gemfile
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "minitest"
+gem "parslet"
diff --git a/2022/ruby/Gemfile.lock b/2022/ruby/Gemfile.lock
new file mode 100644
index 0000000..a263299
--- /dev/null
+++ b/2022/ruby/Gemfile.lock
@@ -0,0 +1,15 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    minitest (5.16.3)
+    parslet (2.0.0)
+
+PLATFORMS
+  arm64-darwin-21
+
+DEPENDENCIES
+  minitest
+  parslet
+
+BUNDLED WITH
+   2.3.18
diff --git a/2022/ruby/test_day_11.rb b/2022/ruby/test_day_11.rb
new file mode 100644
index 0000000..0daeec9
--- /dev/null
+++ b/2022/ruby/test_day_11.rb
@@ -0,0 +1,61 @@
+require "bundler/setup"
+require "minitest/autorun"
+
+require "parslet"
+
+Monkey = Struct.new(:id, :items, :operation, :test, :t, :f) do
+  def throw_to(item)
+    (item % test).zero? ? t : f
+  end
+end
+
+class MonkeyParser < Parslet::Parser
+  rule(:num) { match("[0-9]").repeat.as(:num) }
+  rule(:space) { match("\\s").repeat }
+  rule(:newline) { str("\n") }
+
+  rule(:monkey) {
+    space >> str("Monkey ") >> num.as(:id) >> str(":") >>
+    space >> str("Starting items: ") >> ( num >> ( str(", ") >> num ).repeat ).as(:items) >>
+    space >> str("Operation: new = ") >> (newline.absent? >> any).repeat.as(:op) >>
+    space >> str("Test: divisible by ") >> num.as(:test) >>
+    space >> str("If true: throw to monkey ") >> num.as(:true) >>
+    space >> str("If false: throw to monkey ") >> num.as(:false) >>
+    space
+  }
+
+  rule(:monkeys) { monkey.repeat }
+
+  root(:monkeys)
+end
+
+class MonkeyTransform < Parslet::Transform
+  rule(num: simple(:x)) { x.to_i }
+
+  rule(
+    id: simple(:id),
+    items: sequence(:items),
+    op: simple(:op),
+    test: simple(:test),
+    true: simple(:t),
+    false: simple(:f),
+  ) {
+    Monkey.new(id, items, op, test, t, f)
+  }
+end
+
+class TestDay11 < Minitest::Test
+  def test_day_11
+    tree = MonkeyParser.new.parse(<<~MONKEY)
+      Monkey 0:
+        Starting items: 79, 98
+        Operation: new = old * 19
+        Test: divisible by 23
+          If true: throw to monkey 2
+          If false: throw to monkey 3
+    MONKEY
+
+    monkeys = MonkeyTransform.new.apply(tree)
+    assert_equal [Monkey.new(0, [79, 98], "old * 19", 23, 2, 3)], monkeys
+  end
+end