[2022][ruby][7.x]
change zwoxxyqouqymklprlplpuwxwsvpywpvr
commit 344011c82cd2559c7fc227ae7e1b4c06f29ebc79
author Alpha Chen <alpha@kejadlen.dev>
date
parent ktqnptmp
diff --git a/2022/ruby/day_07.rb b/2022/ruby/day_07.rb
new file mode 100644
index 0000000..a52c19e
--- /dev/null
+++ b/2022/ruby/day_07.rb
@@ -0,0 +1,69 @@
+input = ARGF.read.lines(chomp: true).slice_when { _2.start_with?(?$) }
+
+Dir = Struct.new(:parent, :name, :children) do
+  include Enumerable
+
+  def size = children.sum(&:size)
+
+  def each(&block)
+    return enum_for(__method__, &block) unless block
+
+    block.(self)
+
+    children.each do |child|
+      case child
+      when Dir
+        child.each(&block)
+      when File
+        block.(child)
+      else
+        fail child.inspect
+      end
+    end
+  end
+end
+
+File = Struct.new(:parent, :name, :size)
+
+root = Dir.new(nil, ?/, [])
+pwd = root
+
+input.each do |chunk|
+  cmd, *out = *chunk
+  case cmd
+  when /\$ cd \//
+    # no-op
+  when /\$ cd \.\./
+    pwd = pwd.parent
+  when /\$ cd (.+)/
+    pwd = pwd.children.find { _1.name == $1 }
+  when /\$ ls/
+    out.each do |line|
+      case line
+      when /(\d+) (.+)/
+        pwd.children << File.new(pwd, $2, $1.to_i)
+      when /dir (.+)/
+        pwd.children << Dir.new(pwd, $1, [])
+      else
+        fail line
+      end
+    end
+  else
+    fail chunk.inspect
+  end
+end
+
+# part 1
+p root.each
+  .select { Dir === _1 }
+  .map(&:size)
+  .select { _1 < 100_000 }
+  .sum
+
+# part 2
+p root.each
+  .select { Dir === _1 }
+  .map(&:size)
+  .sort
+  .find { _1 >= 30_000_000 - (70_000_000 - root.size) }
+