Skip to content

Instantly share code, notes, and snippets.

@therubyhound
Created December 3, 2024 19:56
Show Gist options
  • Save therubyhound/d3c76e58ba9b39265fa98bed09732f36 to your computer and use it in GitHub Desktop.
Save therubyhound/d3c76e58ba9b39265fa98bed09732f36 to your computer and use it in GitHub Desktop.
Advent of Code 2024, Day 3
require "minitest/autorun"
class Recovery
def initialize(input, parser: BasicParser)
@input = input
@parser = parser
end
def total
data.sum { |x, y| x.to_i * y.to_i }
end
private
def data
@data ||= @parser.new(@input).parse
end
end
class BasicParser
PATTERN = /mul\((\d{1,3}),(\d{1,3})\)/
def initialize(input)
@input = input
end
def parse
@input.scan(PATTERN)
end
end
class ConditionalParser
PATTERN = /mul\((\d{1,3}),(\d{1,3})\)|(do\(\))|(don't\(\))/
def initialize(input)
@input = input
@active = true
end
def parse
commands.each_with_object([]) do |command, instructions|
case command.first
when "do()"
@active = true
when "don't()"
@active = false
else
instructions << command if @active
end
end
end
private
def commands
@input.scan(PATTERN).map(&:compact)
end
end
BLUE = "\e[34m"
YELLOW = "\e[33m"
RESET = "\e[0m"
recovery = Recovery.new(File.read(ARGV[0]))
puts "#{BLUE}Transaction Total: #{YELLOW}#{recovery.total}#{RESET}"
conditional_recovery = Recovery.new(File.read(ARGV[0]), parser: ConditionalParser)
puts "#{BLUE}Conditional Transaction Total: #{YELLOW}#{conditional_recovery.total}#{RESET}"
PART_1_INPUT = "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"
PART_2_INPUT = "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"
class RecoveryTest < Minitest::Test
def test_part_1_total
recover_memory = Recovery.new(PART_1_INPUT)
assert_equal 161, recover_memory.total
end
def test_part_2_total
recover_memory = Recovery.new(PART_2_INPUT, parser: ConditionalParser)
assert_equal 48, recover_memory.total
end
end
class BasicParserTest < Minitest::Test
def test_parse
basic_parser = BasicParser.new PART_1_INPUT
expected = [["2","4"], ["5","5"], ["11","8"], ["8","5"]]
assert_equal expected, basic_parser.parse
end
end
class ConditionalParserTest < Minitest::Test
def test_parse
conditional_parser = ConditionalParser.new PART_2_INPUT
assert_equal [["2", "4"], ["8","5"]], conditional_parser.parse
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment