1
Fork 0

feat: Day 3

This commit is contained in:
Lucas Schwiderski 2021-12-09 16:24:09 +01:00
parent a216d73e9e
commit e7795b324e
2 changed files with 76 additions and 0 deletions

34
puzzles/03_1/main.rb Normal file
View file

@ -0,0 +1,34 @@
def run(f)
len = 0
bits = []
f.each do |line|
if len == 0
# Skip the trailing newline character and convert to 0-based index
len = line.length() - 2
0.upto(len) { |n| bits[n] = [0, 0] }
end
len.downto(0) { |n|
digit = Integer(line[n])
bits[n][digit] += 1
}
end
gamma = 0
epsilon = 0
len.downto(0) { |n|
# Since we iterated from left to right on the input
# we need to do the same when building the integers
width = len - n
if bits[n][0] > bits[n][1]
gamma += 1 << width
else
epsilon += 1 << width
end
}
return gamma * epsilon
end

42
puzzles/03_2/main.rb Normal file
View file

@ -0,0 +1,42 @@
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