2015/08-10, 2015/12-13, started on 2015/14
This commit is contained in:
254
2015/13/src/main.rs
Normal file
254
2015/13/src/main.rs
Normal 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)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user