#!/usr/bin/env -S ruby require "pathname" require "set" INPUTS = [ Pathname("inputs/test.txt"), Pathname("inputs/puzzle.txt"), ].freeze VOWELS = %[a e i o u].freeze def vowel_count(input) input.each_char.sum do |char| VOWELS.include?(char) ? 1 : 0 end end def twin_letters(input) input.each_char.each_cons(2).sum do |(char, next_char)| char == next_char ? 1 : 0 end end def letter_pairs_count(input) characters = input .each_char .each_cons(4) .reject { |(a, b, c, d)| (a == b && b == c || b == c && c == d ) && a != d } last_index = characters.size pairs = characters .flat_map .with_index(1) { |(a, b, c, d), i| i == last_index ? [a+b, b+c, c+d] : [a+b] } pairs.tally.values.max || 0 end def surrounded_letter_count(input) input .each_char .each_cons(3) .count { |(a, _, b)| a == b } end def is_nice?(input) return false if input.match?(/ab|cd|pq|xy/) return false unless vowel_count(input) >= 3 return false unless twin_letters(input) >= 1 true end def is_really_nice?(input) return false if letter_pairs_count(input) < 2 return false if surrounded_letter_count(input).zero? true end def count_nice(file) file.each_line.sum do |line| line = line.chomp # chomp: true keyword argument emits warnings next 0 if line.empty? yield(line) ? 1 : 0 end end def solve_part_1(file) nice_lines = count_nice(file) { |l| is_nice?(l) } puts "\tThere are #{nice_lines} nice lines" end def solve_part_2(file) nice_lines = count_nice(file) { |l| is_really_nice?(l) } puts "\tThere are #{nice_lines} really nice lines" end def main(files) files.each do |file| puts "File: #{file}" solve_part_1(file) solve_part_2(file) end end main(INPUTS)