87 lines
1.7 KiB
Ruby
Executable File
87 lines
1.7 KiB
Ruby
Executable File
#!/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)
|