2015/08-10, 2015/12-13, started on 2015/14

This commit is contained in:
2017-12-05 08:01:57 +01:00
parent b6a89a7ab6
commit 6fc08571bf
20 changed files with 1072 additions and 156 deletions

254
2015/13/src/main.rs Normal file
View File

@@ -0,0 +1,254 @@
use std::io::{self, Read};
use std::iter::Iterator;
use std::collections::HashMap;
type Map<'a> = HashMap<&'a str, HashMap<&'a str, i64>>;
struct Permutations<'a, T: 'a> {
source: &'a [T],
iter: Vec<usize>,
done: bool,
}
impl<'a, T> Permutations<'a, T> {
fn new(source: &'a [T]) -> Permutations<T> {
Permutations {
source: source,
iter: vec![0; source.len()],
done: false,
}
}
}
impl<'a, T> Iterator for Permutations<'a, T>
where
T: Clone,
{
type Item = Vec<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.done {
None
} else {
let values = self.iter
.iter()
.map(|index| self.source[*index].clone())
.collect::<Vec<_>>();
let max = self.source.len() - 1;
self.done = true;
for i in self.iter.iter_mut().rev() {
if *i == max {
*i = 0;
continue;
}
*i += 1;
self.done = false;
break;
}
Some(values)
}
}
}
#[derive(Clone, Copy)]
enum State {
From,
TriggerTo,
To,
Sign,
Happiness(bool),
}
fn parse(input: &str) -> (&str, &str, i64) {
let mut state = State::From;
let mut from = None;
let mut to = None;
let mut happiness = None;
for token in input.split_whitespace() {
match (state, token) {
(State::From, name) => {
from = Some(name);
state = State::Sign;
}
(State::Sign, "gain") => {
state = State::Happiness(true);
}
(State::Sign, "lose") => {
state = State::Happiness(false);
}
(State::Happiness(sign), value) => {
happiness = Some(value.parse::<i64>().unwrap() * if sign { 1 } else { -1 });
state = State::TriggerTo;
}
(State::TriggerTo, "to") => {
state = State::To;
}
(State::To, name) => {
let len = name.len();
to = Some(&name[0..len - 1]);
break;
}
(_, _) => (),
}
}
(from.unwrap(), to.unwrap(), happiness.unwrap())
}
fn main() {
let mut input = String::new();
io::stdin()
.read_to_string(&mut input)
.expect("failed to read input");
let mut map = Map::new();
for line in input.lines().filter(|line| !line.is_empty()) {
let (from, to, happines) = parse(line);
map.entry(from)
.or_insert_with(HashMap::new)
.insert(to, happines);
}
{
let values = map.keys().collect::<Vec<_>>();
let mut permutations = Permutations::new(&values)
.filter(|permutation| {
let mut iter = permutation.iter();
while let Some(needle) = iter.next() {
if iter.clone().any(|haystack| haystack == needle) {
return false;
}
}
true
})
.map(|permutation| {
let mut table = permutation.clone();
table.push(permutation.first().unwrap());
let happiness: i64 = table
.windows(2)
.map(|people| {
map[people[0]][people[1]] + map[people[1]][people[0]]
})
.sum();
(permutation, happiness)
})
.collect::<Vec<_>>();
permutations.sort_by_key(|&(_, happiness)| happiness);
println!("part_one={:?}", permutations.iter().rev().next().unwrap());
}
for other in map.values_mut() {
other.insert("Me", 0);
}
let others = map.keys().map(|other| *other).collect::<Vec<_>>();
for other in others {
map.entry("Me")
.or_insert_with(HashMap::new)
.insert(other, 0);
}
{
let values = map.keys().collect::<Vec<_>>();
let mut permutations = Permutations::new(&values)
.filter(|permutation| {
let mut iter = permutation.iter();
while let Some(needle) = iter.next() {
if iter.clone().any(|haystack| haystack == needle) {
return false;
}
}
true
})
.map(|permutation| {
let mut table = permutation.clone();
table.push(permutation.first().unwrap());
let happiness: i64 = table
.windows(2)
.map(|people| {
map[people[0]][people[1]] + map[people[1]][people[0]]
})
.sum();
(permutation, happiness)
})
.collect::<Vec<_>>();
permutations.sort_by_key(|&(_, happiness)| happiness);
println!("part_two={:?}", permutations.iter().rev().next().unwrap());
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse() {
assert_eq!(
parse("Alice would gain 54 happiness units by sitting next to Bob."),
("Alice", "Bob", 54)
);
assert_eq!(
parse("Alice would lose 79 happiness units by sitting next to Carol."),
("Alice", "Carol", -79)
);
assert_eq!(
parse("Alice would lose 2 happiness units by sitting next to David."),
("Alice", "David", -2)
);
assert_eq!(
parse("Bob would gain 83 happiness units by sitting next to Alice."),
("Bob", "Alice", 83)
);
assert_eq!(
parse("Bob would lose 7 happiness units by sitting next to Carol."),
("Bob", "Carol", -7)
);
assert_eq!(
parse("Bob would lose 63 happiness units by sitting next to David."),
("Bob", "David", -63)
);
}
}