2015/08-10, 2015/12-13, started on 2015/14
This commit is contained in:
2
2015/08/Cargo.lock
generated
2
2015/08/Cargo.lock
generated
@@ -1,4 +1,4 @@
|
||||
[root]
|
||||
[[package]]
|
||||
name = "08"
|
||||
version = "0.1.0"
|
||||
|
||||
|
||||
@@ -6,20 +6,22 @@ use std::str;
|
||||
enum StateMachine {
|
||||
Normal,
|
||||
Escape,
|
||||
Hexadecimal(u8)
|
||||
Hexadecimal(u8),
|
||||
}
|
||||
|
||||
fn code_length(input: &str) -> usize {
|
||||
input.len()
|
||||
}
|
||||
|
||||
fn memory_length(input: &str) -> usize {
|
||||
let mut count: usize = 0;
|
||||
let mut count = 0;
|
||||
|
||||
let mut state = StateMachine::Normal;
|
||||
|
||||
for c in input.chars() {
|
||||
state = match (c, state) {
|
||||
// Normal.
|
||||
('\\', StateMachine::Normal) => {
|
||||
StateMachine::Escape
|
||||
}
|
||||
('\\', StateMachine::Normal) => StateMachine::Escape,
|
||||
(_, s @ StateMachine::Normal) => {
|
||||
count += 1;
|
||||
|
||||
@@ -27,9 +29,7 @@ fn memory_length(input: &str) -> usize {
|
||||
}
|
||||
|
||||
// Escape.
|
||||
('x', StateMachine::Escape) => {
|
||||
StateMachine::Hexadecimal(1)
|
||||
}
|
||||
('x', StateMachine::Escape) => StateMachine::Hexadecimal(1),
|
||||
(_, StateMachine::Escape) => {
|
||||
count += 1;
|
||||
|
||||
@@ -37,8 +37,7 @@ fn memory_length(input: &str) -> usize {
|
||||
}
|
||||
|
||||
// Hexadecimal.
|
||||
(_, StateMachine::Hexadecimal(mut hex)) => {
|
||||
if hex == 2 {
|
||||
(_, StateMachine::Hexadecimal(mut hex)) => if hex == 2 {
|
||||
count += 1;
|
||||
|
||||
StateMachine::Normal
|
||||
@@ -46,43 +45,49 @@ fn memory_length(input: &str) -> usize {
|
||||
hex += 1;
|
||||
|
||||
StateMachine::Hexadecimal(hex)
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// println!("{} - {} => {:?}", count, c, state);
|
||||
}
|
||||
|
||||
count - 2
|
||||
}
|
||||
|
||||
fn code_length(input: &str) -> usize {
|
||||
input.len()
|
||||
fn string_length(input: &str) -> usize {
|
||||
let mut count = 0;
|
||||
|
||||
for c in input.chars() {
|
||||
count += match c {
|
||||
'"' => 2,
|
||||
'\\' => 2,
|
||||
_ => 1,
|
||||
};
|
||||
}
|
||||
|
||||
count + 2
|
||||
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let stdin = io::stdin();
|
||||
|
||||
let lines = stdin.lock().lines()
|
||||
let lines = stdin
|
||||
.lock()
|
||||
.lines()
|
||||
.filter_map(|line| line.ok())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let count_1: usize = lines.iter()
|
||||
.map(|line| code_length(&line))
|
||||
.sum();
|
||||
let code: usize = lines.iter().map(|line| code_length(line)).sum();
|
||||
let memory: usize = lines.iter().map(|line| memory_length(line)).sum();
|
||||
let string: usize = lines.iter().map(|line| string_length(line)).sum();
|
||||
|
||||
let count_2: usize = lines.iter()
|
||||
.map(|line| memory_length(&line))
|
||||
.sum();
|
||||
|
||||
println!("count_1={}", count_1);
|
||||
println!("count_2={}", count_1 - count_2);
|
||||
println!("part_one={}", code - memory);
|
||||
println!("part_two={}", string - code);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{code_length, memory_length};
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn example_01() {
|
||||
@@ -115,4 +120,32 @@ mod tests {
|
||||
assert_eq!(6, code_length(line));
|
||||
assert_eq!(1, memory_length(line));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_05() {
|
||||
let line = r#""""#;
|
||||
|
||||
assert_eq!(6, string_length(line));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_06() {
|
||||
let line = r#""abc""#;
|
||||
|
||||
assert_eq!(9, string_length(line));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_07() {
|
||||
let line = r#""aaa\"aaa""#;
|
||||
|
||||
assert_eq!(16, string_length(line));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_08() {
|
||||
let line = r#""\x27""#;
|
||||
|
||||
assert_eq!(11, string_length(line));
|
||||
}
|
||||
}
|
||||
|
||||
102
2015/09/Cargo.lock
generated
102
2015/09/Cargo.lock
generated
@@ -1,105 +1,95 @@
|
||||
[root]
|
||||
[[package]]
|
||||
name = "09"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.5.3"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.1.16"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.18"
|
||||
version = "0.2.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "0.1.11"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.1.80"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.3.9"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "thread-id"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.2.7"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "0.1.3"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "cf186d1a8aa5f5bee5fd662bc9c1b949e0259e1bcc379d1f006847b0080c7417"
|
||||
"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
|
||||
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
|
||||
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
|
||||
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
|
||||
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
|
||||
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
|
||||
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
|
||||
"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
|
||||
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
||||
"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322"
|
||||
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
|
||||
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
@@ -4,5 +4,5 @@ version = "0.1.0"
|
||||
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "0.1"
|
||||
regex = "0.1"
|
||||
lazy_static = "1.0"
|
||||
regex = "0.2"
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#[macro_use] extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate regex;
|
||||
|
||||
|
||||
use std::io::{self, Read};
|
||||
use std::iter::Iterator;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use regex::Regex;
|
||||
@@ -10,23 +13,61 @@ use regex::Regex;
|
||||
type Map<'a> = BTreeMap<&'a str, BTreeMap<&'a str, i64>>;
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Route<'a> {
|
||||
vec: Vec<&'a str>,
|
||||
distance: i64
|
||||
struct Permutations<'a, T: 'a> {
|
||||
source: &'a [T],
|
||||
iter: Vec<usize>,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
impl<'a> Route<'a> {
|
||||
fn new() -> Route<'a> {
|
||||
Route {
|
||||
vec: Vec::new(),
|
||||
distance: 0
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn process<'a>(input: &'a str) -> Route<'a> {
|
||||
fn parse(input: &str) -> Map {
|
||||
lazy_static! {
|
||||
static ref RE: Regex = Regex::new(r"^([a-zA-Z]+) to ([a-zA-Z]+) = (\d+)$").unwrap();
|
||||
}
|
||||
@@ -34,67 +75,49 @@ fn process<'a>(input: &'a str) -> Route<'a> {
|
||||
let mut map: Map = BTreeMap::new();
|
||||
|
||||
for line in input.lines() {
|
||||
let caps = RE.captures(&line).unwrap();
|
||||
let caps = RE.captures(line).unwrap();
|
||||
|
||||
let a = caps.at(1).unwrap();
|
||||
let b = caps.at(2).unwrap();
|
||||
let a = caps.get(1).unwrap().as_str();
|
||||
let b = caps.get(2).unwrap().as_str();
|
||||
|
||||
let distance = caps.at(3).unwrap().parse::<i64>().unwrap();
|
||||
let distance = caps[3].parse::<i64>().unwrap();
|
||||
|
||||
map.entry(a).or_insert(BTreeMap::new()).insert(b, distance);
|
||||
map.entry(b).or_insert(BTreeMap::new()).insert(a, distance);
|
||||
map.entry(a)
|
||||
.or_insert_with(BTreeMap::new)
|
||||
.insert(b, distance);
|
||||
|
||||
map.entry(b)
|
||||
.or_insert_with(BTreeMap::new)
|
||||
.insert(a, distance);
|
||||
}
|
||||
|
||||
let mut routes = iterate(&map, None);
|
||||
|
||||
routes.sort_by_key(|x| x.distance);
|
||||
|
||||
routes.remove(0)
|
||||
map
|
||||
}
|
||||
|
||||
fn iterate<'a>(map: &Map<'a>, route: Option<Route<'a>>) -> Vec<Route<'a>> {
|
||||
let mut routes = Vec::new();
|
||||
fn routes<'a>(map: &'a Map<'a>) -> Vec<(Vec<&'a str>, i64)> {
|
||||
let cities = map.keys().map(|city| *city).collect::<Vec<_>>();
|
||||
|
||||
if let Some(mut route) = route {
|
||||
let prev = *route.vec.last().unwrap();
|
||||
Permutations::new(&cities)
|
||||
.filter(|route| {
|
||||
let mut iter = route.iter();
|
||||
|
||||
let mut end = true;
|
||||
|
||||
for (city, distance) in map.get(prev).unwrap().iter() {
|
||||
if route.vec.contains(city) {
|
||||
continue;
|
||||
}
|
||||
|
||||
route.vec.push(*city);
|
||||
route.distance += *distance;
|
||||
|
||||
{
|
||||
let mut sub_routes = iterate(&map, Some(route.clone()));
|
||||
|
||||
routes.append(&mut sub_routes);
|
||||
}
|
||||
|
||||
end = false;
|
||||
}
|
||||
|
||||
if end {
|
||||
routes.push(route);
|
||||
}
|
||||
} else {
|
||||
for city in map.keys() {
|
||||
let mut route = Route::new();
|
||||
|
||||
route.vec.push(*city);
|
||||
|
||||
{
|
||||
let mut sub_routes = iterate(&map, Some(route));
|
||||
|
||||
routes.append(&mut sub_routes);
|
||||
}
|
||||
while let Some(needle) = iter.next() {
|
||||
if iter.clone().any(|haystack| haystack == needle) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
routes
|
||||
true
|
||||
})
|
||||
.map(|route| {
|
||||
let distance = route
|
||||
.windows(2)
|
||||
.map(|cities| map[cities[0]][cities[1]])
|
||||
.sum();
|
||||
|
||||
(route, distance)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -102,15 +125,20 @@ fn main() {
|
||||
|
||||
io::stdin().read_to_string(&mut input).unwrap();
|
||||
|
||||
let result = process(&input);
|
||||
let map = parse(&input);
|
||||
let mut routes = routes(&map);
|
||||
|
||||
println!("{:?}", result);
|
||||
routes.sort_by_key(|&(_, distance)| distance);
|
||||
|
||||
|
||||
println!("shortest={:?}", routes.first().unwrap());
|
||||
println!("longest={:?}", routes.last().unwrap());
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::process;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn example_01() {
|
||||
@@ -118,8 +146,13 @@ mod tests {
|
||||
London to Belfast = 518\n\
|
||||
Dublin to Belfast = 141";
|
||||
|
||||
let result = process(input);
|
||||
let map = parse(input);
|
||||
let mut routes = routes(&map);
|
||||
|
||||
assert_eq!(605, result.distance);
|
||||
routes.sort_by_key(|&(_, distance)| distance);
|
||||
|
||||
println!("{:#?}", routes);
|
||||
|
||||
assert_eq!(605, routes[0].1);
|
||||
}
|
||||
}
|
||||
|
||||
4
2015/10/Cargo.lock
generated
Normal file
4
2015/10/Cargo.lock
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
[[package]]
|
||||
name = "day-10"
|
||||
version = "0.1.0"
|
||||
|
||||
6
2015/10/Cargo.toml
Normal file
6
2015/10/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day-10"
|
||||
version = "0.1.0"
|
||||
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
1
2015/10/input.txt
Normal file
1
2015/10/input.txt
Normal file
@@ -0,0 +1 @@
|
||||
1113122113
|
||||
100
2015/10/src/main.rs
Normal file
100
2015/10/src/main.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
use std::io::{self, Read};
|
||||
use std::iter::Iterator;
|
||||
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
enum Digit {
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
}
|
||||
|
||||
|
||||
struct LookAndSay {
|
||||
values: Vec<Digit>,
|
||||
}
|
||||
|
||||
impl LookAndSay {
|
||||
fn from_string(input: &str) -> Self {
|
||||
let values = input
|
||||
.chars()
|
||||
.map(|c| match c {
|
||||
'1' => Digit::One,
|
||||
'2' => Digit::Two,
|
||||
'3' => Digit::Three,
|
||||
_ => panic!("invalid input"),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
LookAndSay { values: values }
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for LookAndSay {
|
||||
type Item = Vec<Digit>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mut values = Vec::new();
|
||||
|
||||
let mut state = self.values[0];
|
||||
let mut count = 0;
|
||||
|
||||
for value in &self.values {
|
||||
if *value == state {
|
||||
count += 1;
|
||||
} else {
|
||||
values.push(match count {
|
||||
1 => Digit::One,
|
||||
2 => Digit::Two,
|
||||
3 => Digit::Three,
|
||||
_ => unreachable!(),
|
||||
});
|
||||
|
||||
values.push(state);
|
||||
|
||||
state = *value;
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
values.push(match count {
|
||||
1 => Digit::One,
|
||||
2 => Digit::Two,
|
||||
3 => Digit::Three,
|
||||
_ => unreachable!(),
|
||||
});
|
||||
|
||||
values.push(state);
|
||||
|
||||
self.values = values.clone();
|
||||
|
||||
Some(values)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let mut input = String::new();
|
||||
|
||||
io::stdin()
|
||||
.read_to_string(&mut input)
|
||||
.expect("faild to read input");
|
||||
|
||||
for line in input
|
||||
.lines()
|
||||
.map(|line| line.trim())
|
||||
.filter(|line| !line.is_empty())
|
||||
{
|
||||
let mut look_and_say = LookAndSay::from_string(line);
|
||||
|
||||
// Skip 39 iterations to get number 40.
|
||||
if let Some(value) = look_and_say.nth(39) {
|
||||
println!("part_one={}", value.len());
|
||||
}
|
||||
|
||||
// Skip 9 more iterations to get number 50.
|
||||
if let Some(value) = look_and_say.nth(9) {
|
||||
println!("part_two={}", value.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
4
2015/12/Cargo.lock
generated
Normal file
4
2015/12/Cargo.lock
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
[[package]]
|
||||
name = "day-12"
|
||||
version = "0.1.0"
|
||||
|
||||
6
2015/12/Cargo.toml
Normal file
6
2015/12/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day-12"
|
||||
version = "0.1.0"
|
||||
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
1
2015/12/input.txt
Normal file
1
2015/12/input.txt
Normal file
File diff suppressed because one or more lines are too long
397
2015/12/src/main.rs
Normal file
397
2015/12/src/main.rs
Normal file
@@ -0,0 +1,397 @@
|
||||
use std::io::{self, Read};
|
||||
use std::iter::Iterator;
|
||||
use std::borrow::Cow;
|
||||
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
enum Token<'a> {
|
||||
ObjectStart,
|
||||
ObjectEnd,
|
||||
ArrayStart,
|
||||
ArrayEnd,
|
||||
Number(i64),
|
||||
String(Cow<'a, str>),
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
enum State {
|
||||
Unknown,
|
||||
InObject,
|
||||
InArray,
|
||||
Number(usize),
|
||||
String(usize),
|
||||
}
|
||||
|
||||
|
||||
struct Parser<'a> {
|
||||
state: Vec<State>,
|
||||
input: &'a str,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
fn new(input: &'a str) -> Self {
|
||||
Parser {
|
||||
state: Vec::new(),
|
||||
input: input,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Parser<'a> {
|
||||
type Item = Token<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Token<'a>> {
|
||||
if self.index >= self.input.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut iter = self.input.chars().skip(self.index);
|
||||
|
||||
let mut next = iter.next();
|
||||
|
||||
while let Some(ch) = next {
|
||||
let state = self.state.last().unwrap_or(&State::Unknown).clone();
|
||||
|
||||
match (state, ch) {
|
||||
// Unknown.
|
||||
(State::Unknown, '-') => {
|
||||
self.state.push(State::Number(self.index));
|
||||
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::Unknown, '0'...'9') => {
|
||||
self.state.push(State::Number(self.index));
|
||||
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::Unknown, '"') => {
|
||||
self.state.push(State::String(self.index + 1));
|
||||
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::Unknown, '{') => {
|
||||
self.state.push(State::InObject);
|
||||
|
||||
self.index += 1;
|
||||
|
||||
return Some(Token::ObjectStart);
|
||||
}
|
||||
(State::Unknown, '[') => {
|
||||
self.state.push(State::InArray);
|
||||
|
||||
self.index += 1;
|
||||
|
||||
return Some(Token::ArrayStart);
|
||||
}
|
||||
|
||||
// Number.
|
||||
(State::Number(_), '0'...'9') => {
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::Number(start), _) => {
|
||||
self.state.pop();
|
||||
|
||||
return Some(Token::Number(
|
||||
self.input[start..self.index].parse::<i64>().unwrap(),
|
||||
));
|
||||
}
|
||||
|
||||
// String.
|
||||
(State::String(start), '"') => {
|
||||
self.state.pop();
|
||||
|
||||
self.index += 1;
|
||||
|
||||
return Some(Token::String(self.input[start..self.index - 1].into()));
|
||||
}
|
||||
(State::String(_), _) => {
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
|
||||
// Object.
|
||||
(State::InObject, '"') => {
|
||||
self.state.push(State::String(self.index + 1));
|
||||
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::InObject, '-') => {
|
||||
self.state.push(State::Number(self.index));
|
||||
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::InObject, '0'...'9') => {
|
||||
self.state.push(State::Number(self.index));
|
||||
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::InObject, '{') => {
|
||||
self.state.push(State::InObject);
|
||||
|
||||
self.index += 1;
|
||||
|
||||
return Some(Token::ObjectStart);
|
||||
}
|
||||
(State::InObject, '[') => {
|
||||
self.state.push(State::InArray);
|
||||
|
||||
self.index += 1;
|
||||
|
||||
return Some(Token::ArrayStart);
|
||||
}
|
||||
(State::InObject, '}') => {
|
||||
self.state.pop();
|
||||
|
||||
self.index += 1;
|
||||
|
||||
return Some(Token::ObjectEnd);
|
||||
}
|
||||
|
||||
// Array.
|
||||
(State::InArray, '"') => {
|
||||
self.state.push(State::String(self.index + 1));
|
||||
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::InArray, '-') => {
|
||||
self.state.push(State::Number(self.index));
|
||||
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::InArray, '0'...'9') => {
|
||||
self.state.push(State::Number(self.index));
|
||||
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
(State::InArray, '{') => {
|
||||
self.state.push(State::InObject);
|
||||
|
||||
self.index += 1;
|
||||
|
||||
return Some(Token::ObjectStart);
|
||||
}
|
||||
(State::InArray, '[') => {
|
||||
self.state.push(State::InArray);
|
||||
|
||||
self.index += 1;
|
||||
|
||||
return Some(Token::ArrayStart);
|
||||
}
|
||||
(State::InArray, ']') => {
|
||||
self.state.pop();
|
||||
|
||||
self.index += 1;
|
||||
|
||||
return Some(Token::ArrayEnd);
|
||||
}
|
||||
|
||||
// Everything else.
|
||||
(_, _) => {
|
||||
self.index += 1;
|
||||
next = iter.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Stack {
|
||||
sum: i64,
|
||||
in_object: bool,
|
||||
expect_key: bool,
|
||||
discard: bool,
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let mut input = String::new();
|
||||
|
||||
io::stdin()
|
||||
.read_to_string(&mut input)
|
||||
.expect("faild to read input");
|
||||
|
||||
let mut total = 0;
|
||||
let mut stack = Vec::new();
|
||||
|
||||
stack.push(Stack {
|
||||
sum: 0,
|
||||
in_object: false,
|
||||
expect_key: false,
|
||||
discard: false,
|
||||
});
|
||||
|
||||
for line in input.lines() {
|
||||
for value in Parser::new(line) {
|
||||
match value {
|
||||
Token::String(ref string) => {
|
||||
let this = stack.last_mut().unwrap();
|
||||
|
||||
if this.in_object {
|
||||
if this.expect_key {
|
||||
this.expect_key = false;
|
||||
} else if string == "red" {
|
||||
this.expect_key = true;
|
||||
this.discard = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Token::Number(number) => {
|
||||
let this = stack.last_mut().unwrap();
|
||||
|
||||
if this.in_object {
|
||||
this.expect_key = true;
|
||||
}
|
||||
|
||||
this.sum += number;
|
||||
}
|
||||
Token::ObjectStart => {
|
||||
stack.push(Stack {
|
||||
sum: 0,
|
||||
in_object: true,
|
||||
expect_key: true,
|
||||
discard: false,
|
||||
});
|
||||
}
|
||||
Token::ObjectEnd => {
|
||||
let this = stack.pop().unwrap();
|
||||
|
||||
if !this.discard {
|
||||
let entry = stack.last_mut().unwrap();
|
||||
|
||||
entry.sum += this.sum;
|
||||
}
|
||||
}
|
||||
Token::ArrayStart => {
|
||||
stack.push(Stack {
|
||||
sum: 0,
|
||||
in_object: false,
|
||||
expect_key: false,
|
||||
discard: false,
|
||||
});
|
||||
}
|
||||
Token::ArrayEnd => {
|
||||
let that = stack.pop().unwrap();
|
||||
let this = stack.last_mut().unwrap();
|
||||
|
||||
this.sum += that.sum;
|
||||
|
||||
if this.in_object {
|
||||
this.expect_key = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let this = stack.last_mut().unwrap();
|
||||
|
||||
total += this.sum;
|
||||
}
|
||||
|
||||
println!("total={}", total);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn example_01() {
|
||||
let mut parser = Parser::new(r#"[1,2,3]"#);
|
||||
|
||||
assert_eq!(parser.next(), Some(Token::ArrayStart));
|
||||
assert_eq!(parser.next(), Some(Token::Number(1)));
|
||||
assert_eq!(parser.next(), Some(Token::Number(2)));
|
||||
assert_eq!(parser.next(), Some(Token::Number(3)));
|
||||
assert_eq!(parser.next(), Some(Token::ArrayEnd));
|
||||
assert_eq!(parser.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_02() {
|
||||
let mut parser = Parser::new(r#"{"a":2,"b":4}"#);
|
||||
|
||||
assert_eq!(parser.next(), Some(Token::ObjectStart));
|
||||
assert_eq!(parser.next(), Some(Token::String("a".into())));
|
||||
assert_eq!(parser.next(), Some(Token::Number(2)));
|
||||
assert_eq!(parser.next(), Some(Token::String("b".into())));
|
||||
assert_eq!(parser.next(), Some(Token::Number(4)));
|
||||
assert_eq!(parser.next(), Some(Token::ObjectEnd));
|
||||
assert_eq!(parser.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_03() {
|
||||
let mut parser = Parser::new(r#"[[[3]]]"#);
|
||||
|
||||
assert_eq!(parser.next(), Some(Token::ArrayStart));
|
||||
assert_eq!(parser.next(), Some(Token::ArrayStart));
|
||||
assert_eq!(parser.next(), Some(Token::ArrayStart));
|
||||
assert_eq!(parser.next(), Some(Token::Number(3)));
|
||||
assert_eq!(parser.next(), Some(Token::ArrayEnd));
|
||||
assert_eq!(parser.next(), Some(Token::ArrayEnd));
|
||||
assert_eq!(parser.next(), Some(Token::ArrayEnd));
|
||||
assert_eq!(parser.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_04() {
|
||||
let mut parser = Parser::new(r#"{"a":{"b":4},"c":-1}"#);
|
||||
|
||||
assert_eq!(parser.next(), Some(Token::ObjectStart));
|
||||
assert_eq!(parser.next(), Some(Token::String("a".into())));
|
||||
assert_eq!(parser.next(), Some(Token::ObjectStart));
|
||||
assert_eq!(parser.next(), Some(Token::String("b".into())));
|
||||
assert_eq!(parser.next(), Some(Token::Number(4)));
|
||||
assert_eq!(parser.next(), Some(Token::ObjectEnd));
|
||||
assert_eq!(parser.next(), Some(Token::String("c".into())));
|
||||
assert_eq!(parser.next(), Some(Token::Number(-1)));
|
||||
assert_eq!(parser.next(), Some(Token::ObjectEnd));
|
||||
assert_eq!(parser.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_05() {
|
||||
let mut parser = Parser::new(r#"{"a":[-1,1]}"#);
|
||||
|
||||
assert_eq!(parser.next(), Some(Token::ObjectStart));
|
||||
assert_eq!(parser.next(), Some(Token::String("a".into())));
|
||||
assert_eq!(parser.next(), Some(Token::ArrayStart));
|
||||
assert_eq!(parser.next(), Some(Token::Number(-1)));
|
||||
assert_eq!(parser.next(), Some(Token::Number(1)));
|
||||
assert_eq!(parser.next(), Some(Token::ArrayEnd));
|
||||
assert_eq!(parser.next(), Some(Token::ObjectEnd));
|
||||
assert_eq!(parser.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_06() {
|
||||
let mut parser = Parser::new(r#"[-1,{"a":1}]"#);
|
||||
|
||||
assert_eq!(parser.next(), Some(Token::ArrayStart));
|
||||
assert_eq!(parser.next(), Some(Token::Number(-1)));
|
||||
assert_eq!(parser.next(), Some(Token::ObjectStart));
|
||||
assert_eq!(parser.next(), Some(Token::String("a".into())));
|
||||
assert_eq!(parser.next(), Some(Token::Number(1)));
|
||||
assert_eq!(parser.next(), Some(Token::ObjectEnd));
|
||||
assert_eq!(parser.next(), Some(Token::ArrayEnd));
|
||||
assert_eq!(parser.next(), None);
|
||||
}
|
||||
}
|
||||
4
2015/13/Cargo.lock
generated
Normal file
4
2015/13/Cargo.lock
generated
Normal file
@@ -0,0 +1,4 @@
|
||||
[[package]]
|
||||
name = "day-13"
|
||||
version = "0.1.0"
|
||||
|
||||
6
2015/13/Cargo.toml
Normal file
6
2015/13/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day-13"
|
||||
version = "0.1.0"
|
||||
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
12
2015/13/example.txt
Normal file
12
2015/13/example.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
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.
|
||||
56
2015/13/input.txt
Normal file
56
2015/13/input.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
Alice would lose 2 happiness units by sitting next to Bob.
|
||||
Alice would lose 62 happiness units by sitting next to Carol.
|
||||
Alice would gain 65 happiness units by sitting next to David.
|
||||
Alice would gain 21 happiness units by sitting next to Eric.
|
||||
Alice would lose 81 happiness units by sitting next to Frank.
|
||||
Alice would lose 4 happiness units by sitting next to George.
|
||||
Alice would lose 80 happiness units by sitting next to Mallory.
|
||||
Bob would gain 93 happiness units by sitting next to Alice.
|
||||
Bob would gain 19 happiness units by sitting next to Carol.
|
||||
Bob would gain 5 happiness units by sitting next to David.
|
||||
Bob would gain 49 happiness units by sitting next to Eric.
|
||||
Bob would gain 68 happiness units by sitting next to Frank.
|
||||
Bob would gain 23 happiness units by sitting next to George.
|
||||
Bob would gain 29 happiness units by sitting next to Mallory.
|
||||
Carol would lose 54 happiness units by sitting next to Alice.
|
||||
Carol would lose 70 happiness units by sitting next to Bob.
|
||||
Carol would lose 37 happiness units by sitting next to David.
|
||||
Carol would lose 46 happiness units by sitting next to Eric.
|
||||
Carol would gain 33 happiness units by sitting next to Frank.
|
||||
Carol would lose 35 happiness units by sitting next to George.
|
||||
Carol would gain 10 happiness units by sitting next to Mallory.
|
||||
David would gain 43 happiness units by sitting next to Alice.
|
||||
David would lose 96 happiness units by sitting next to Bob.
|
||||
David would lose 53 happiness units by sitting next to Carol.
|
||||
David would lose 30 happiness units by sitting next to Eric.
|
||||
David would lose 12 happiness units by sitting next to Frank.
|
||||
David would gain 75 happiness units by sitting next to George.
|
||||
David would lose 20 happiness units by sitting next to Mallory.
|
||||
Eric would gain 8 happiness units by sitting next to Alice.
|
||||
Eric would lose 89 happiness units by sitting next to Bob.
|
||||
Eric would lose 69 happiness units by sitting next to Carol.
|
||||
Eric would lose 34 happiness units by sitting next to David.
|
||||
Eric would gain 95 happiness units by sitting next to Frank.
|
||||
Eric would gain 34 happiness units by sitting next to George.
|
||||
Eric would lose 99 happiness units by sitting next to Mallory.
|
||||
Frank would lose 97 happiness units by sitting next to Alice.
|
||||
Frank would gain 6 happiness units by sitting next to Bob.
|
||||
Frank would lose 9 happiness units by sitting next to Carol.
|
||||
Frank would gain 56 happiness units by sitting next to David.
|
||||
Frank would lose 17 happiness units by sitting next to Eric.
|
||||
Frank would gain 18 happiness units by sitting next to George.
|
||||
Frank would lose 56 happiness units by sitting next to Mallory.
|
||||
George would gain 45 happiness units by sitting next to Alice.
|
||||
George would gain 76 happiness units by sitting next to Bob.
|
||||
George would gain 63 happiness units by sitting next to Carol.
|
||||
George would gain 54 happiness units by sitting next to David.
|
||||
George would gain 54 happiness units by sitting next to Eric.
|
||||
George would gain 30 happiness units by sitting next to Frank.
|
||||
George would gain 7 happiness units by sitting next to Mallory.
|
||||
Mallory would gain 31 happiness units by sitting next to Alice.
|
||||
Mallory would lose 32 happiness units by sitting next to Bob.
|
||||
Mallory would gain 95 happiness units by sitting next to Carol.
|
||||
Mallory would gain 91 happiness units by sitting next to David.
|
||||
Mallory would lose 66 happiness units by sitting next to Eric.
|
||||
Mallory would lose 75 happiness units by sitting next to Frank.
|
||||
Mallory would lose 99 happiness units by sitting next to George.
|
||||
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)
|
||||
);
|
||||
}
|
||||
}
|
||||
6
2015/14/Cargo.toml
Normal file
6
2015/14/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "day-14"
|
||||
version = "0.1.0"
|
||||
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
3
2015/14/src/main.rs
Normal file
3
2015/14/src/main.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
Reference in New Issue
Block a user