Skip to content

Instantly share code, notes, and snippets.

@Insti
Created December 3, 2021 20:25
Show Gist options
  • Save Insti/4b24f0a26dfef288eea2373732739804 to your computer and use it in GitHub Desktop.
Save Insti/4b24f0a26dfef288eea2373732739804 to your computer and use it in GitHub Desktop.
Advent of code 2021 - Day 3
# frozen_string_literal: true
require 'minitest/autorun'
require_relative 'input_data'
class InputData
@file = __FILE__
def parse
raw_data.lines.map { |line| line.scan(/\d/) }
end
end
# This is horrible and confusing
def part_one(parsed)
freq = parsed.transpose.map { |row| row.group_by { |x| x }.transform_values(&:size).invert }
something = freq.map do |f|
f.minmax.map(&:last)
end.transpose.map { |v| v.join.to_i(2) }.reduce(:*)
end
def part_two(parsed)
oxygen_rating(parsed) * co2_scrubber_rating(parsed)
end
def oxygen_rating(parsed)
candidates = parsed.dup
guard = candidates.first.size
n = 0
while candidates.size > 1 && guard
# Find the most common bit in position n
mcv = most_common_value(candidates, n, tiebreak: "1")
candidates.select! { |candidate| candidate[n] == mcv }
n += 1
guard -= 1
end
candidates.first.join.to_i(2)
end
def co2_scrubber_rating(parsed)
candidates = parsed.dup
guard = candidates.first.size
n = 0
while candidates.size > 1 && guard
# Find the most common bit in position n
mcv = least_common_value(candidates, n)
candidates.select! { |candidate| candidate[n] == mcv }
n += 1
guard -= 1
end
candidates.first.join.to_i(2)
end
def most_common_value(parsed, position, tiebreak: "1")
ones = parsed.count { |row| row[position] == "1" }
zeros = parsed.size - ones
{ -1 => "0", 0 => tiebreak, 1 => "1"}[ones <=> zeros]
end
def least_common_value(parsed, position, tiebreak: "0")
ones = parsed.count { |row| row[position] == "1" }
zeros = parsed.size - ones
{ 1 => "0", 0 => tiebreak, -1 => "1"}[ones <=> zeros]
end
class TestDay < Minitest::Test
EXAMPLE_ONE = <<~LINES
00100
11110
10110
10111
10101
01111
00111
11100
10000
11001
00010
01010
LINES
def test_part_one_example
data = InputData.new(EXAMPLE_ONE).parse
assert_equal 198, part_one(data)
end
def test_part_one_answer
data = InputData.new.parse
assert_equal 775304, part_one(data)
end
def test_example_oxygen_rating
data = InputData.new(EXAMPLE_ONE).parse
assert_equal 23, oxygen_rating(data)
end
def test_example_co2_scrubber_rating
data = InputData.new(EXAMPLE_ONE).parse
assert_equal 10, co2_scrubber_rating(data)
end
def test_part_two_example
data = InputData.new(EXAMPLE_ONE).parse
assert_equal 230, part_two(data)
end
def test_part_two_answer
data = InputData.new.parse
assert_equal 1370737, part_two(data)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment