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

View File

@@ -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;
while let Some(needle) = iter.next() {
if iter.clone().any(|haystack| haystack == needle) {
return false;
}
}
route.vec.push(*city);
route.distance += *distance;
true
})
.map(|route| {
let distance = route
.windows(2)
.map(|cities| map[cities[0]][cities[1]])
.sum();
{
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);
}
}
}
routes
(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);
}
}