diff --git a/2023/ruby/day_04.rb b/2023/ruby/day_04.rb
new file mode 100644
index 0000000..6102de2
--- /dev/null
+++ b/2023/ruby/day_04.rb
@@ -0,0 +1,25 @@
+cards = ARGF.read.scan(/Card\s+(\d+):+((?~\|))\|(.*)/)
+ .to_h {|id, *v|
+ [id.to_i, v.map { _1.scan(/\d+/).map(&:to_i) }]
+ }
+
+# part one
+p cards.values
+ .map {|winning,card|
+ winners = (card & winning)
+ winners.empty? ? 0 : 2 ** (winners.length - 1)
+ }
+ .sum
+
+# part two
+wins = Hash.new {|h,k|
+ winning, card = cards.fetch(k)
+ winners = winning & card
+ new_cards = (1..winners.length).map { k + _1 }
+
+ h[k] = winners.empty? ? 1 : 1 + new_cards.sum { h[_1] }
+}
+p cards.map {|id,(winning,card)|
+ wins[id]
+ }
+ .sum