Created
December 5, 2024 23:09
-
-
Save therubyhound/2e7c5c4d868d7b2bda84741fe376accb to your computer and use it in GitHub Desktop.
Advent of Code 2024, Day 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "miNitest/autorun" | |
require "debug" | |
class SafetyManual | |
attr_reader :rules, :pages | |
def initialize(input) | |
@rules, @pages = parse input | |
end | |
def sum | |
middle_pages(valid_updates).sum | |
end | |
def fixed_sum | |
middle_pages(fixed_updates).sum | |
end | |
def middle_pages(updates) | |
updates.map { |update| update[update.length / 2] } | |
end | |
def valid_updates | |
pages.select { |update| valid_update?(update) } | |
end | |
def fixed_updates | |
invalid_updates.map { |update| fix(update) } | |
end | |
def fix(update) | |
hash = rule_hash(update) | |
sorted_update = update.sort_by do |item| | |
depth = hash.keys.count { |key| hash[key]&.include?(item) } | |
depth | |
end | |
sorted_update | |
end | |
def invalid_updates | |
pages.reject { |update| valid_update?(update) } | |
end | |
def valid_update?(update) | |
relevant_rules(update).all? { |rule| valid?(rule, update) } | |
end | |
def valid?(rule, update) | |
update.find_index(rule[0]) < update.find_index(rule[1]) | |
end | |
def relevant_rules(update) | |
rules & update.product(update) | |
end | |
private | |
def parse(input) | |
rules, pages = input.split("\n\n") | |
[ | |
rules.lines.map { |line| line.split("|").map(&:to_i) }, | |
pages.lines.map { |line| line.split(",").map(&:to_i) } | |
] | |
end | |
def rule_hash(update) | |
hash = {} | |
relevant_rules(update).each do |p1, p2| | |
hash[p1] ||= [] | |
hash[p1] << p2 | |
end | |
hash | |
end | |
end | |
BLUE = "\e[34m" | |
YELLOW = "\e[33m" | |
RESET = "\e[0m" | |
safety_manual = SafetyManual.new(File.read(ARGV[0])) | |
puts "#{BLUE}Sum:#{RESET} #{YELLOW}#{safety_manual.sum}#{RESET}" | |
puts "#{BLUE}Fixed Sum:#{RESET} #{YELLOW}#{safety_manual.fixed_sum}#{RESET}" | |
INPUT = DATA.read | |
class SafetyManualTest < Minitest::Test | |
def setup | |
@safety_manual = SafetyManual.new(INPUT) | |
end | |
def fixed_sum | |
assert_equal 123, @safety_manual.sum | |
end | |
def test_sum | |
assert_equal 143, @safety_manual.sum | |
end | |
def test_middle_pages | |
updates = [ | |
[75,47,61,53,29], | |
[97,61,53,29,13], | |
[75,29,13] | |
] | |
assert_equal [61, 53, 29], @safety_manual.middle_pages(updates) | |
end | |
def test_valid_updates | |
expected = [ | |
[75,47,61,53,29], | |
[97,61,53,29,13], | |
[75,29,13] | |
] | |
assert_equal expected, @safety_manual.valid_updates | |
end | |
def test_fix | |
assert_equal [97,75,47,61,53], @safety_manual.fix([75,97,47,61,53]) | |
assert_equal [61,29,13], @safety_manual.fix([61,13,29]) | |
assert_equal [97,75,47,29,13], @safety_manual.fix([97,13,75,29,47]) | |
end | |
def test_fixed_updates | |
expected = [ | |
[97,75,47,61,53], | |
[61,29,13], | |
[97,75,47,29,13] | |
] | |
assert_equal expected, @safety_manual.fixed_updates | |
end | |
def test_invalid_updates | |
expected = [ | |
[75,97,47,61,53], | |
[61,13,29], | |
[97,13,75,29,47] | |
] | |
assert_equal expected, @safety_manual.invalid_updates | |
end | |
def test_valid? | |
assert @safety_manual.valid?([75,29], [75,47,61,53,29]) | |
end | |
def test_valid_update? | |
assert @safety_manual.valid_update?([75,47,61,53,29]) | |
refute @safety_manual.valid_update?([75,97,47,61,53]) | |
end | |
def test_relevant_rules | |
expected = [ | |
[75, 29], | |
[75, 53], | |
[75, 47], | |
[75, 61], | |
[47, 53], | |
[47, 61], | |
[47, 29], | |
[61, 53], | |
[61, 29], | |
[53, 29] | |
] | |
assert equal_array(expected, @safety_manual.relevant_rules([75,47,61,53,29])) | |
end | |
def test_rules | |
expected = [ | |
[47, 53], | |
[97, 13], | |
[97, 61], | |
[97, 47], | |
[75, 29], | |
[61, 13], | |
[75, 53], | |
[29, 13], | |
[97, 29], | |
[53, 29], | |
[61, 53], | |
[97, 53], | |
[61, 29], | |
[47, 13], | |
[75, 47], | |
[97, 75], | |
[47, 61], | |
[75, 61], | |
[47, 29], | |
[75, 13], | |
[53, 13], | |
] | |
assert_equal expected, @safety_manual.rules | |
end | |
def test_pages | |
expected = [ | |
[75,47,61,53,29], | |
[97,61,53,29,13], | |
[75,29,13], | |
[75,97,47,61,53], | |
[61,13,29], | |
[97,13,75,29,47], | |
] | |
assert_equal expected, @safety_manual.pages | |
end | |
def equal_array(expected, result) | |
expected.count == result.count && result.all? { |x| expected.include?(x) } | |
end | |
end | |
__END__ | |
47|53 | |
97|13 | |
97|61 | |
97|47 | |
75|29 | |
61|13 | |
75|53 | |
29|13 | |
97|29 | |
53|29 | |
61|53 | |
97|53 | |
61|29 | |
47|13 | |
75|47 | |
97|75 | |
47|61 | |
75|61 | |
47|29 | |
75|13 | |
53|13 | |
75,47,61,53,29 | |
97,61,53,29,13 | |
75,29,13 | |
75,97,47,61,53 | |
61,13,29 | |
97,13,75,29,47 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment