#!/usr/bin/env ruby # frozen_string_literal: true require "pathname" require "set" def parse_file(file) file.each_line.each_with_object({}) do |line, people| name, _, rest = line.chomp.partition(" would ") change, neighbor = rest.split(" happiness units by sitting next to ") change = change.split.then { |v| v.first == "gain" ? v.last.to_i : -v.last.to_i } people[name] ||= {} people[name][neighbor.delete_suffix(".")] = change end end def optimized_seating(people) people.map do |start| visited = Set.new happiness = {} name, neighbors = start start_name = name loop do visited.add(name) happiness[name] ||= 0 nb_name, hn_change = neighbors .reject { |n, _| visited.include?(n) } .max { |(an, ac), (bn, bc)| (ac + people[an][name]) <=> (bc + people[bn][name]) } nb_name ||= start_name hn_change ||= neighbors[start_name] happiness[nb_name] ||= 0 happiness[name] += hn_change happiness[nb_name] += people[nb_name][name] name = nb_name neighbors = people[name] break if visited.size == people.size end happiness.values.sum end end def main(file_paths) file_paths.each do |file_path| puts "File: #{file_path}" people = parse_file(file_path) solution1 = optimized_seating(people).max puts " solution 1: #{solution1}" people["Self"] = people.each_with_object({}) { |(n, _), o| o[n] = 0 } people.each { |(_, nb)| nb["Self"] = 0 } solution2 = optimized_seating(people).max puts " solution 2: #{solution2}" end end main(ARGV.map { |x| Pathname(x) })