parent
32895b3e17
commit
94ddabc590
@ -0,0 +1,31 @@ |
||||
require "advent" |
||||
input = input(2020, 21).lines.map do |line| |
||||
data = line.match(/^([a-z ]+) \(contains (.+)\)$/).not_nil! |
||||
{data[1].split(" ").to_set, data[2].split(", ").to_set} |
||||
end |
||||
|
||||
allergens = input.flat_map(&.last.to_a).to_set |
||||
ingredients = input.flat_map(&.first.to_a).to_set |
||||
|
||||
allergen_sets = {} of String => Set(String) |
||||
allergens.each do |a| |
||||
input.each do |ings, als| |
||||
next unless als.includes? a |
||||
allergen_sets[a] ||= ings |
||||
allergen_sets[a] &= ings |
||||
end |
||||
end |
||||
|
||||
safe = ingredients.reject { |i| allergen_sets.any? &.last.includes?(i) } |
||||
puts "Part 1: #{input.sum &.first.count { |i| safe.includes? i }}" |
||||
|
||||
known_allergens = {} of String => String |
||||
while allergen_sets.size > known_allergens.size |
||||
allergen_sets.each do |a, s| |
||||
next unless s.size == 1 |
||||
new_known = s.first |
||||
known_allergens[a] = new_known |
||||
allergen_sets.each &.last.delete(new_known) |
||||
end |
||||
end |
||||
puts "Part 2: #{known_allergens.to_a.sort_by(&.first).map(&.last).join(",")}" |
@ -0,0 +1,66 @@ |
||||
require "advent" |
||||
first, second = input(2020, 22).split("\n\n") |
||||
first = first.lines[1..].map &.to_i32 |
||||
second = second.lines[1..].map &.to_i32 |
||||
|
||||
class Array(T) |
||||
def pop_left |
||||
delete_at(0) |
||||
end |
||||
|
||||
def score |
||||
total = 0 |
||||
s = size |
||||
each_with_index do |n, i| |
||||
total += n * (s - i) |
||||
end |
||||
total |
||||
end |
||||
end |
||||
|
||||
def no_rec(deck1, deck2) |
||||
while !deck1.empty? && !deck2.empty? |
||||
f, s = deck1.delete_at(0), deck2.delete_at(0) |
||||
if f > s |
||||
deck1 << f << s |
||||
else |
||||
deck2 << s << f |
||||
end |
||||
end |
||||
return !deck1.empty? |
||||
end |
||||
|
||||
def rec(deck1, deck2) |
||||
seen = Set({Int32, Int32}).new |
||||
while !deck1.empty? && !deck2.empty? |
||||
key = {deck1.score, deck2.score} |
||||
return true if seen.includes?(key) |
||||
seen << key |
||||
|
||||
f = deck1.delete_at(0) |
||||
s = deck2.delete_at(0) |
||||
|
||||
p1wins = (f <= deck1.size) && (s <= deck2.size) ? rec(deck1[0..f-1], deck2[0..s-1]) : f > s |
||||
if p1wins |
||||
deck1 << f << s |
||||
else |
||||
deck2 << s << f |
||||
end |
||||
end |
||||
return !deck1.empty? |
||||
end |
||||
|
||||
def run(first, second, proc) |
||||
((proc.call(first, second)) ? first : second).score |
||||
end |
||||
|
||||
def part1(input) |
||||
run(input[0], input[1], ->no_rec(Array(Int32), Array(Int32))) |
||||
end |
||||
|
||||
def part2(input) |
||||
run(input[0], input[1], ->rec(Array(Int32), Array(Int32))) |
||||
end |
||||
|
||||
puts part1({first, second}.clone) |
||||
puts part2({first, second}.clone) |
Loading…
Reference in new issue