158 lines
5.2 KiB
Rust
158 lines
5.2 KiB
Rust
use core::panic;
|
|
use std::collections::HashMap;
|
|
|
|
use utils::{math::factorial, permutation};
|
|
|
|
pub fn process_part1(input: &str) -> i32 {
|
|
let mut happiness_table = HashMap::new();
|
|
let mut people = Vec::new();
|
|
input.lines().for_each(|line| {
|
|
let words = line.split_whitespace().collect::<Vec<&str>>();
|
|
let happiness = match words[2] {
|
|
"gain" => words[3].parse::<i32>().expect("Should be number"),
|
|
"lose" => -words[3].parse::<i32>().expect("Should be number"),
|
|
_ => panic!("Should not happen"),
|
|
};
|
|
let person = words[0].to_string();
|
|
let mut next_to = words[10].to_string();
|
|
next_to.pop();
|
|
if !people.contains(&person) {
|
|
people.push(person.clone());
|
|
}
|
|
happiness_table.insert((person, next_to), happiness);
|
|
});
|
|
|
|
let num_people = people.len();
|
|
|
|
let possible_permutations = factorial(num_people.try_into().unwrap());
|
|
|
|
let mut highest_happiness = 0;
|
|
for idx in 1..possible_permutations {
|
|
let mut happiness = 0;
|
|
let permutation = permutation::nth_lex(people.clone(), idx.try_into().unwrap()).unwrap();
|
|
|
|
for (pos, person) in permutation.clone().iter().enumerate() {
|
|
let left_neighbor = {
|
|
if pos == 0 {
|
|
permutation[num_people - 1].clone()
|
|
} else {
|
|
permutation[pos - 1].clone()
|
|
}
|
|
};
|
|
let right_neighbor = {
|
|
if pos == num_people - 1 {
|
|
permutation[0].clone()
|
|
} else {
|
|
permutation[pos + 1].clone()
|
|
}
|
|
};
|
|
|
|
let left_happiness = happiness_table
|
|
.get(&(person.to_owned(), left_neighbor))
|
|
.unwrap();
|
|
let right_happiness = happiness_table
|
|
.get(&(person.to_owned(), right_neighbor))
|
|
.unwrap();
|
|
happiness += left_happiness + right_happiness;
|
|
}
|
|
|
|
if happiness > highest_happiness {
|
|
highest_happiness = happiness;
|
|
}
|
|
}
|
|
|
|
highest_happiness
|
|
}
|
|
|
|
pub fn process_part2(input: &str) -> i32 {
|
|
let mut happiness_table = HashMap::new();
|
|
let mut people = Vec::new();
|
|
input.lines().for_each(|line| {
|
|
let words = line.split_whitespace().collect::<Vec<&str>>();
|
|
let happiness = match words[2] {
|
|
"gain" => words[3].parse::<i32>().expect("Should be number"),
|
|
"lose" => -words[3].parse::<i32>().expect("Should be number"),
|
|
_ => panic!("Should not happen"),
|
|
};
|
|
let person = words[0].to_string();
|
|
let mut next_to = words[10].to_string();
|
|
next_to.pop();
|
|
if !people.contains(&person) {
|
|
people.push(person.clone());
|
|
}
|
|
happiness_table.insert((person, next_to), happiness);
|
|
});
|
|
|
|
for person in &people {
|
|
happiness_table.insert(("Fabian".to_string(), person.to_owned()), 0);
|
|
happiness_table.insert((person.to_owned(), "Fabian".to_string()), 0);
|
|
}
|
|
|
|
people.push("Fabian".to_string());
|
|
|
|
let num_people = people.len();
|
|
|
|
let possible_permutations = factorial(num_people.try_into().unwrap());
|
|
|
|
let mut highest_happiness = 0;
|
|
for idx in 1..possible_permutations {
|
|
let mut happiness = 0;
|
|
let permutation = permutation::nth_lex(people.clone(), idx.try_into().unwrap()).unwrap();
|
|
|
|
for (pos, person) in permutation.clone().iter().enumerate() {
|
|
let left_neighbor = {
|
|
if pos == 0 {
|
|
permutation[num_people - 1].clone()
|
|
} else {
|
|
permutation[pos - 1].clone()
|
|
}
|
|
};
|
|
let right_neighbor = {
|
|
if pos == num_people - 1 {
|
|
permutation[0].clone()
|
|
} else {
|
|
permutation[pos + 1].clone()
|
|
}
|
|
};
|
|
|
|
let left_happiness = happiness_table
|
|
.get(&(person.to_owned(), left_neighbor))
|
|
.unwrap();
|
|
let right_happiness = happiness_table
|
|
.get(&(person.to_owned(), right_neighbor))
|
|
.unwrap();
|
|
happiness += left_happiness + right_happiness;
|
|
}
|
|
|
|
if happiness > highest_happiness {
|
|
highest_happiness = happiness;
|
|
}
|
|
}
|
|
|
|
highest_happiness
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
const INPUT: &str = "Alice would gain 54 happiness units by sitting next to Bob.
|
|
Alice would lose 79 happiness units by sitting next to Carol.
|
|
Alice would lose 2 happiness units by sitting next to David.
|
|
Bob would gain 83 happiness units by sitting next to Alice.
|
|
Bob would lose 7 happiness units by sitting next to Carol.
|
|
Bob would lose 63 happiness units by sitting next to David.
|
|
Carol would lose 62 happiness units by sitting next to Alice.
|
|
Carol would gain 60 happiness units by sitting next to Bob.
|
|
Carol would gain 55 happiness units by sitting next to David.
|
|
David would gain 46 happiness units by sitting next to Alice.
|
|
David would lose 7 happiness units by sitting next to Bob.
|
|
David would gain 41 happiness units by sitting next to Carol.";
|
|
|
|
#[test]
|
|
fn part1() {
|
|
let result = process_part1(INPUT);
|
|
assert_eq!(result, 330);
|
|
}
|
|
}
|