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