def find(lines, index, search) if index > (lines.first.length() - 2) raise "Invalid index" end bits = [0, 0] # Count the occurrences of each digit at the index lines.each do |line| digit = Integer(line[index]) bits[digit] += 1 end # Not the most expressive way to do this, but should get the job done if search == 1 # Return most common value, or 1 on a tie target = bits[0] > bits[1] ? 0 : 1 else # Return least common value, or 0 on a tie target = bits[0] <= bits[1] ? 0 : 1 end # Filter lines to only the ones that have the target value at `index` lines = lines.filter { |line| line[index] == target.to_s } # If there's only one left, we found our value. # Otherwise, continue filtering at the next index if lines.length() == 1 return lines.first else return find(lines, index + 1, search) end end def run(f) lines = f.readlines() # This should filter down to a single number, which we need to convert from a base 2 bit string oxygen = find(lines, 0, 1).to_i(2) co2 = find(lines, 0, 0).to_i(2) return oxygen * co2 end