DEV Community

Discussion on: AoC Day 2: Inventory Management System

Collapse
 
harri_etty profile image
Harriet

Part 1 in Ruby:

have_two_letters = 0
have_three_letters = 0

File.open('./input.txt', 'r').each do |str|
  freq = str.split('').group_by(&:itself).map {|k,v| [v.size, k] }.to_h
  have_two_letters += 1 if freq[2]
  have_three_letters += 1 if freq[3]
end

puts have_three_letters * have_two_letters

I enjoyed playing around with the one liner

str.split('').group_by(&:itself).map {|k,v| [v.size, k] }.to_h

which produces a frequency chart something like this:

{1=>"j", 4=>"f", 2=>"s"}

i.e. there are exactly 2 occurrences of the letter s in str

Part 2 in Ruby

lines = File.read('./input.txt').split("\n");

def get_shared_letters(str1, str2)
  differences = 0
  same_letters = nil
  str1.split('').each_with_index do |letter, i|
    if letter != str2[i]
      differences += 1 
      same_letters = str1.dup
      same_letters.slice!(i)
    end
  end

  differences === 1 ? same_letters : nil
end

lines.each_with_index do |str1, i1|
  lines.each_with_index do |str2, i2|
    next if i2 === i1

    shared = get_shared_letters str1, str2
    puts shared if shared
  end
end

Not happy about the double loop through the input file... but also can't think of a way to avoid it! It occurred to me that sorting the list first might improve the chances of finding a match earlier in the loop since all similar strings would be together, but thinking about it, perhaps there's equal chance that the similar strings would end up being sorted to the bottom of the list and it wouldn't help at all :/

Another thought - many of the input strings are v. similar, maybe they could be grouped into sets early on (e.g. based on the first 4 chars or something) and then you only look for similar strings in the same set?

Going to read into hamming distances now!