parent
1697560761
commit
d9c69654e9
@ -1,28 +1,28 @@
|
||||
Faerun to Tristram = 65
|
||||
Faerun to Tambi = 129
|
||||
Faerun to Norrath = 144
|
||||
Faerun to Snowdin = 71
|
||||
Faerun to Straylight = 137
|
||||
Faerun to AlphaCentauri = 3
|
||||
Faerun to Arbre = 149
|
||||
Tristram to Tambi = 63
|
||||
Tristram to Norrath = 4
|
||||
Tristram to Snowdin = 105
|
||||
Tristram to Straylight = 125
|
||||
Tristram to AlphaCentauri = 55
|
||||
Tristram to Arbre = 14
|
||||
Tambi to Norrath = 68
|
||||
Tambi to Snowdin = 52
|
||||
Tambi to Straylight = 65
|
||||
Tambi to AlphaCentauri = 22
|
||||
Tambi to Arbre = 143
|
||||
Norrath to Snowdin = 8
|
||||
Norrath to Straylight = 23
|
||||
Norrath to AlphaCentauri = 136
|
||||
Norrath to Arbre = 115
|
||||
Snowdin to Straylight = 101
|
||||
Snowdin to AlphaCentauri = 84
|
||||
Snowdin to Arbre = 96
|
||||
Straylight to AlphaCentauri = 107
|
||||
Straylight to Arbre = 14
|
||||
AlphaCentauri to Arbre = 46
|
||||
Faerun to Norrath = 129
|
||||
Faerun to Tristram = 58
|
||||
Faerun to AlphaCentauri = 13
|
||||
Faerun to Arbre = 24
|
||||
Faerun to Snowdin = 60
|
||||
Faerun to Tambi = 71
|
||||
Faerun to Straylight = 67
|
||||
Norrath to Tristram = 142
|
||||
Norrath to AlphaCentauri = 15
|
||||
Norrath to Arbre = 135
|
||||
Norrath to Snowdin = 75
|
||||
Norrath to Tambi = 82
|
||||
Norrath to Straylight = 54
|
||||
Tristram to AlphaCentauri = 118
|
||||
Tristram to Arbre = 122
|
||||
Tristram to Snowdin = 103
|
||||
Tristram to Tambi = 49
|
||||
Tristram to Straylight = 97
|
||||
AlphaCentauri to Arbre = 116
|
||||
AlphaCentauri to Snowdin = 12
|
||||
AlphaCentauri to Tambi = 18
|
||||
AlphaCentauri to Straylight = 91
|
||||
Arbre to Snowdin = 129
|
||||
Arbre to Tambi = 53
|
||||
Arbre to Straylight = 40
|
||||
Snowdin to Tambi = 15
|
||||
Snowdin to Straylight = 99
|
||||
Tambi to Straylight = 70
|
@ -1,65 +1,75 @@
|
||||
pub fn solve(input: &str) -> i32 {
|
||||
let presents = input.split("\n").map(|line| Present::new(line)).collect::<Vec<Present>>();
|
||||
presents.iter().fold(0u32, |acc, present| acc + present.ribbon()) as i32
|
||||
let presents =
|
||||
input.split('\n').map(|line| Present::new(line)).collect::<Vec<Present>>();
|
||||
presents.iter().fold(0u32, |acc, present| acc + present.ribbon()) as i32
|
||||
}
|
||||
|
||||
struct Present {
|
||||
length: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
length: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Present {
|
||||
fn new(input: &str) -> Self {
|
||||
let dimensions = input.split("x")
|
||||
.map(|d| d.parse::<u32>().unwrap())
|
||||
.collect::<Vec<u32>>();
|
||||
Present { length: dimensions[0], width: dimensions[1], height: dimensions[2] }
|
||||
fn new(input: &str) -> Self {
|
||||
let dimensions = input.split('x')
|
||||
.map(|d| d.parse::<u32>().unwrap())
|
||||
.collect::<Vec<u32>>();
|
||||
Present {
|
||||
length: dimensions[0],
|
||||
width: dimensions[1],
|
||||
height: dimensions[2],
|
||||
}
|
||||
}
|
||||
|
||||
fn wrapping_paper(&self) -> u32 {
|
||||
self.surface_area() + self.slack()
|
||||
}
|
||||
fn wrapping_paper(&self) -> u32 {
|
||||
self.surface_area() + self.slack()
|
||||
}
|
||||
|
||||
fn ribbon(&self) -> u32 {
|
||||
*self.perimeters().iter().min().unwrap_or(&0) + self.volume()
|
||||
}
|
||||
fn ribbon(&self) -> u32 {
|
||||
*self.perimeters().iter().min().unwrap_or(&0) + self.volume()
|
||||
}
|
||||
|
||||
fn surface_area(&self) -> u32 {
|
||||
self.side_areas().iter().fold(0, |acc, &area| acc + 2 * area)
|
||||
}
|
||||
fn surface_area(&self) -> u32 {
|
||||
self.side_areas().iter().fold(0, |acc, &area| acc + 2 * area)
|
||||
}
|
||||
|
||||
fn slack(&self) -> u32 {
|
||||
*self.side_areas().iter().min().unwrap_or(&0)
|
||||
}
|
||||
fn slack(&self) -> u32 {
|
||||
*self.side_areas().iter().min().unwrap_or(&0)
|
||||
}
|
||||
|
||||
fn perimeters(&self) -> Vec<u32> {
|
||||
vec![self.length + self.width,
|
||||
self.width + self.height,
|
||||
self.height + self.length ].iter().map(|&x| 2 * x).collect()
|
||||
}
|
||||
fn perimeters(&self) -> Vec<u32> {
|
||||
vec![self.length + self.width,
|
||||
self.width + self.height,
|
||||
self.height + self.length]
|
||||
.iter()
|
||||
.map(|&x| 2 * x)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn volume(&self) -> u32 {
|
||||
self.length * self.width * self.height
|
||||
}
|
||||
fn volume(&self) -> u32 {
|
||||
self.length * self.width * self.height
|
||||
}
|
||||
|
||||
fn side_areas(&self) -> Vec<u32> {
|
||||
vec![self.length * self.width, self.width * self.height, self.height * self.length]
|
||||
}
|
||||
fn side_areas(&self) -> Vec<u32> {
|
||||
vec![self.length * self.width,
|
||||
self.width * self.height,
|
||||
self.height * self.length]
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_day02() {
|
||||
let mut present = Present::new("2x3x4");
|
||||
assert_eq!(52, present.surface_area());
|
||||
assert_eq!(6, present.slack());
|
||||
assert_eq!(58, present.wrapping_paper());
|
||||
assert_eq!(34, present.ribbon());
|
||||
let mut present = Present::new("2x3x4");
|
||||
assert_eq!(52, present.surface_area());
|
||||
assert_eq!(6, present.slack());
|
||||
assert_eq!(58, present.wrapping_paper());
|
||||
assert_eq!(34, present.ribbon());
|
||||
|
||||
present = Present::new("1x1x10");
|
||||
assert_eq!(42, present.surface_area());
|
||||
assert_eq!(1, present.slack());
|
||||
assert_eq!(43, present.wrapping_paper());
|
||||
assert_eq!(14, present.ribbon());
|
||||
present = Present::new("1x1x10");
|
||||
assert_eq!(42, present.surface_area());
|
||||
assert_eq!(1, present.slack());
|
||||
assert_eq!(43, present.wrapping_paper());
|
||||
assert_eq!(14, present.ribbon());
|
||||
}
|
||||
|
@ -1,146 +1,139 @@
|
||||
use std::cmp::Eq;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::ops::Add;
|
||||
use std::str::Chars;
|
||||
|
||||
pub fn solve(input: &str) -> i32 {
|
||||
let mut santa = String::new();
|
||||
let mut robo_santa = String::new();
|
||||
let mut iter = input.chars();
|
||||
|
||||
loop {
|
||||
match iter.next() {
|
||||
Some(c) => { santa.push(c) },
|
||||
None => break,
|
||||
}
|
||||
match iter.next() {
|
||||
Some(c) => { robo_santa.push(c) },
|
||||
None => break,
|
||||
}
|
||||
let mut santa = String::new();
|
||||
let mut robo_santa = String::new();
|
||||
let mut iter = input.chars();
|
||||
|
||||
loop {
|
||||
match iter.next() {
|
||||
Some(c) => santa.push(c),
|
||||
None => break,
|
||||
}
|
||||
match iter.next() {
|
||||
Some(c) => robo_santa.push(c),
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
let mut houses: HashMap<Point, u32> = HashMap::new();
|
||||
Santa::houses_visited(&santa, &mut houses);
|
||||
Santa::houses_visited(&robo_santa, &mut houses);
|
||||
houses.len() as i32
|
||||
let mut houses: HashMap<Point, u32> = HashMap::new();
|
||||
Santa::houses_visited(&santa, &mut houses);
|
||||
Santa::houses_visited(&robo_santa, &mut houses);
|
||||
houses.len() as i32
|
||||
}
|
||||
|
||||
struct Santa<'a> {
|
||||
location: Point,
|
||||
directions: Chars<'a>,
|
||||
location: Point,
|
||||
directions: Chars<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Santa<'a> {
|
||||
fn new(directions: &str) -> Santa {
|
||||
Santa {
|
||||
location: Point::origin(),
|
||||
directions: directions.chars(),
|
||||
}
|
||||
fn new(directions: &str) -> Santa {
|
||||
Santa {
|
||||
location: Point::origin(),
|
||||
directions: directions.chars(),
|
||||
}
|
||||
}
|
||||
|
||||
fn houses_visited(directions: &str, houses: &mut HashMap<Point, u32>) {
|
||||
let santa = Santa::new(directions);
|
||||
houses.insert(santa.location, 1);
|
||||
fn houses_visited(directions: &str, houses: &mut HashMap<Point, u32>) {
|
||||
let santa = Santa::new(directions);
|
||||
houses.insert(santa.location, 1);
|
||||
|
||||
for point in santa {
|
||||
*houses.entry(point).or_insert(0) += 1;
|
||||
}
|
||||
for point in santa {
|
||||
*houses.entry(point).or_insert(0) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Santa<'a> {
|
||||
type Item = Point;
|
||||
|
||||
fn next(&mut self) -> Option<Point> {
|
||||
let offset = match self.directions.next() {
|
||||
Some('^') => Point { x: 0, y: 1 },
|
||||
Some('v') => Point { x: 0, y: -1 },
|
||||
Some('>') => Point { x: 1, y: 0 },
|
||||
Some('<') => Point { x: -1, y: 0 },
|
||||
_ => return None,
|
||||
};
|
||||
self.location = self.location + offset;
|
||||
Some(self.location)
|
||||
}
|
||||
type Item = Point;
|
||||
|
||||
fn next(&mut self) -> Option<Point> {
|
||||
let offset = match self.directions.next() {
|
||||
Some('^') => Point { x: 0, y: 1 },
|
||||
Some('v') => Point { x: 0, y: -1 },
|
||||
Some('>') => Point { x: 1, y: 0 },
|
||||
Some('<') => Point { x: -1, y: 0 },
|
||||
_ => return None,
|
||||
};
|
||||
self.location = self.location + offset;
|
||||
Some(self.location)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_one() {
|
||||
let directions = ">";
|
||||
let santa = Santa::new(directions);
|
||||
|
||||
let points = santa.collect::<Vec<Point>>();
|
||||
let expected = vec![Point { x: 1, y: 0 }];
|
||||
assert_eq!(expected, points);
|
||||
|
||||
let mut houses: HashMap<Point, u32> = HashMap::new();
|
||||
Santa::houses_visited(directions, &mut houses);
|
||||
assert_eq!(2, houses.len());
|
||||
assert_eq!(&1, houses.get(&Point::origin()).unwrap());
|
||||
assert_eq!(&1, houses.get(&Point { x: 1, y: 0 }).unwrap());
|
||||
let directions = ">";
|
||||
let santa = Santa::new(directions);
|
||||
|
||||
let points = santa.collect::<Vec<Point>>();
|
||||
let expected = vec![Point { x: 1, y: 0 }];
|
||||
assert_eq!(expected, points);
|
||||
|
||||
let mut houses: HashMap<Point, u32> = HashMap::new();
|
||||
Santa::houses_visited(directions, &mut houses);
|
||||
assert_eq!(2, houses.len());
|
||||
assert_eq!(&1, houses.get(&Point::origin()).unwrap());
|
||||
assert_eq!(&1, houses.get(&Point { x: 1, y: 0 }).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_two() {
|
||||
let directions = "^>v<";
|
||||
let directions = "^>v<";
|
||||
|
||||
let mut houses: HashMap<Point, u32> = HashMap::new();
|
||||
Santa::houses_visited(directions, &mut houses);
|
||||
assert_eq!(4, houses.len());
|
||||
assert_eq!(&2, houses.get(&Point::origin()).unwrap());
|
||||
assert_eq!(&1, houses.get(&Point { x: 1, y: 0 }).unwrap());
|
||||
let mut houses: HashMap<Point, u32> = HashMap::new();
|
||||
Santa::houses_visited(directions, &mut houses);
|
||||
assert_eq!(4, houses.len());
|
||||
assert_eq!(&2, houses.get(&Point::origin()).unwrap());
|
||||
assert_eq!(&1, houses.get(&Point { x: 1, y: 0 }).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_three() {
|
||||
let directions = "^v^v^v^v^v";
|
||||
let directions = "^v^v^v^v^v";
|
||||
|
||||
let mut houses: HashMap<Point, u32> = HashMap::new();
|
||||
Santa::houses_visited(directions, &mut houses);
|
||||
assert_eq!(2, houses.len());
|
||||
assert_eq!(&6, houses.get(&Point::origin()).unwrap());
|
||||
assert_eq!(&5, houses.get(&Point { x: 0, y: 1 }).unwrap());
|
||||
let mut houses: HashMap<Point, u32> = HashMap::new();
|
||||
Santa::houses_visited(directions, &mut houses);
|
||||
assert_eq!(2, houses.len());
|
||||
assert_eq!(&6, houses.get(&Point::origin()).unwrap());
|
||||
assert_eq!(&5, houses.get(&Point { x: 0, y: 1 }).unwrap());
|
||||
}
|
||||
|
||||
#[derive(Clone,Copy,Debug,Eq,Hash)]
|
||||
#[derive(Clone,Copy,Debug,Eq,Hash,PartialEq)]
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
fn origin() -> Point {
|
||||
Point { x: 0, y: 0 }
|
||||
}
|
||||
fn origin() -> Point {
|
||||
Point { x: 0, y: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Point {
|
||||
type Output = Point;
|
||||
type Output = Point;
|
||||
|
||||
fn add(self, other: Point) -> Point {
|
||||
Point {
|
||||
x: self.x + other.x,
|
||||
y: self.y + other.y,
|
||||
}
|
||||
fn add(self, other: Point) -> Point {
|
||||
Point {
|
||||
x: self.x + other.x,
|
||||
y: self.y + other.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Point {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "({}, {})", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Point {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.x == other.x && self.y == other.y
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "({}, {})", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_point() {
|
||||
let point = Point { x: 10, y: -10 };
|
||||
let offset = Point { x: -10, y: 10 };
|
||||
assert_eq!(Point::origin(), point + offset);
|
||||
let point = Point { x: 10, y: -10 };
|
||||
let offset = Point { x: -10, y: 10 };
|
||||
assert_eq!(Point::origin(), point + offset);
|
||||
}
|
||||
|
@ -1,60 +1,72 @@
|
||||
#[test]
|
||||
fn test_day_08() {
|
||||
assert_eq!(4, solve(r#""""#));
|
||||
assert_eq!(4, solve(r#""abc""#));
|
||||
assert_eq!(6, solve(r#""aaa\"aaa""#));
|
||||
assert_eq!(5, solve(r#""\x27""#));
|
||||
assert_eq!(5, solve(r#""\xfa""#));
|
||||
assert_eq!(4, solve(r#""""#));
|
||||
assert_eq!(4, solve(r#""abc""#));
|
||||
assert_eq!(6, solve(r#""aaa\"aaa""#));
|
||||
assert_eq!(5, solve(r#""\x27""#));
|
||||
assert_eq!(5, solve(r#""\xfa""#));
|
||||
}
|
||||
|
||||
pub fn solve(input: &str) -> usize {
|
||||
input.lines().fold(0, |sum, s| sum + encode(s).chars().count() - s.len())
|
||||
input.lines().fold(0, |sum, s| sum + encode(s).chars().count() - s.len())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode() {
|
||||
assert_eq!("", decode(r#""""#));
|
||||
assert_eq!("abc", decode(r#""abc""#));
|
||||
assert_eq!("aaa\"aaa", decode(r#""aaa\"aaa""#));
|
||||
assert_eq!("'", decode(r#""\x27""#));
|
||||
assert_eq!(1, decode(r#""\xfa""#).chars().count());
|
||||
assert_eq!("", decode(r#""""#));
|
||||
assert_eq!("abc", decode(r#""abc""#));
|
||||
assert_eq!("aaa\"aaa", decode(r#""aaa\"aaa""#));
|
||||
assert_eq!("'", decode(r#""\x27""#));
|
||||
assert_eq!(1, decode(r#""\xfa""#).chars().count());
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn decode(string: &str) -> String {
|
||||
let mut out = "".to_owned();
|
||||
let mut out = "".to_owned();
|
||||
|
||||
let mut chars = string.chars().map(|c| Some(c)).collect::<Vec<_>>();
|
||||
chars.append(&mut vec![None, None, None]);
|
||||
let mut it = chars.windows(4);
|
||||
loop {
|
||||
match it.next() {
|
||||
Some([Some('"'), None, None, None]) => break,
|
||||
Some([Some('"'), _, _, _]) => {},
|
||||
Some([Some('\\'), Some('\\'), _, _]) => { it.next(); out.push('\\'); },
|
||||
Some([Some('\\'), Some('"'), _, _]) => { it.next(); out.push('"'); },
|
||||
Some([Some('\\'), Some('x'), Some(a), Some(b)]) => {
|
||||
it.next(); it.next(); it.next();
|
||||
let c = (a.to_digit(16).unwrap_or(0) << 4) + (b.to_digit(16).unwrap_or(0));
|
||||
out.push(c as u8 as char);
|
||||
},
|
||||
Some([Some(c), _, _, _]) => { out.push(c); },
|
||||
Some(x) => panic!("{:?}", x),
|
||||
None => panic!(""),
|
||||
};
|
||||
}
|
||||
out
|
||||
let mut chars = string.chars().map(Some).collect::<Vec<_>>();
|
||||
chars.append(&mut vec![None, None, None]);
|
||||
let mut it = chars.windows(4);
|
||||
loop {
|
||||
match it.next() {
|
||||
Some(&[Some('"'), None, None, None]) => break,
|
||||
Some(&[Some('"'), _, _, _]) => {}
|
||||
Some(&[Some('\\'), Some('\\'), _, _]) => {
|
||||
it.next();
|
||||
out.push('\\');
|
||||
}
|
||||
Some(&[Some('\\'), Some('"'), _, _]) => {
|
||||
it.next();
|
||||
out.push('"');
|
||||
}
|
||||
Some(&[Some('\\'), Some('x'), Some(a), Some(b)]) => {
|
||||
it.next();
|
||||
it.next();
|
||||
it.next();
|
||||
let c = (a.to_digit(16).unwrap_or(0) << 4) +
|
||||
(b.to_digit(16).unwrap_or(0));
|
||||
out.push(c as u8 as char);
|
||||
}
|
||||
Some(&[Some(c), _, _, _]) => {
|
||||
out.push(c);
|
||||
}
|
||||
Some(x) => panic!("{:?}", x),
|
||||
None => panic!(""),
|
||||
};
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_encode() {
|
||||
assert_eq!(r#""\"\"""#, encode(r#""""#));
|
||||
assert_eq!(r#""\"abc\"""#, encode(r#""abc""#));
|
||||
assert_eq!(r#""\"aaa\\\"aaa\"""#, encode(r#""aaa\"aaa""#));
|
||||
assert_eq!(r#""\"\\x27\"""#, encode(r#""\x27""#));
|
||||
assert_eq!(r#""\"\\xfa\"""#, encode(r#""\xfa""#));
|
||||
assert_eq!(r#""\"\"""#, encode(r#""""#));
|
||||
assert_eq!(r#""\"abc\"""#, encode(r#""abc""#));
|
||||
assert_eq!(r#""\"aaa\\\"aaa\"""#, encode(r#""aaa\"aaa""#));
|
||||
assert_eq!(r#""\"\\x27\"""#, encode(r#""\x27""#));
|
||||
assert_eq!(r#""\"\\xfa\"""#, encode(r#""\xfa""#));
|
||||
}
|
||||
|
||||
fn encode(string: &str) -> String {
|
||||
format!(r#""{}""#, string.replace(r#"\"#, r#"\\"#).replace(r#"""#, r#"\""#))
|
||||
format!(r#""{}""#,
|
||||
string.replace(r#"\"#, r#"\\"#).replace(r#"""#, r#"\""#))
|
||||
}
|
||||
|
@ -1,112 +1,114 @@
|
||||
use std::collections::{HashMap,HashSet};
|
||||
use std::hash::{Hash,Hasher};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use permutohedron::Heap;
|
||||
|
||||
#[test]
|
||||
fn test_day_09() {
|
||||
let input = "London to Dublin = 464
|
||||
let input = "London to Dublin = 464
|
||||
London to Belfast = 518
|
||||
Dublin to Belfast = 141";
|
||||
let day = Day09::new(input);
|
||||
|
||||
assert_eq!(464,
|
||||
day.distances[&LocationPair(Location("Dublin"),
|
||||
Location("London"))]);
|
||||
assert_eq!(464,
|
||||
day.distances[&LocationPair(Location("London"),
|
||||
Location("Dublin"))]);
|
||||
|
||||
let route = day.route(vec![Location("Dublin"),
|
||||
Dublin to \
|
||||
Belfast = 141";
|
||||
let day = Day09::new(input);
|
||||
|
||||
assert_eq!(464,
|
||||
day.distances[&LocationPair(Location("Dublin"),
|
||||
Location("London"))]);
|
||||
assert_eq!(464,
|
||||
day.distances[&LocationPair(Location("London"),
|
||||
Location("Dublin"))]);
|
||||
|
||||
let route = day.route(vec![Location("Dublin"),
|
||||
Location("London"),
|
||||
Location("Belfast")]);
|
||||
assert_eq!(982, route.distance);
|
||||
assert_eq!(982, route.distance);
|
||||
|
||||
assert_eq!(6, day.routes().len());
|
||||
assert_eq!(6, day.routes().len());
|
||||
|
||||
assert_eq!(982, solve(input));
|
||||
assert_eq!(982, solve(input));
|
||||
}
|
||||
|
||||
pub fn solve(input: &str) -> usize {
|
||||
let day = Day09::new(input);
|
||||
day.routes().iter().map(|r| r.distance).max().unwrap()
|
||||
let day = Day09::new(input);
|
||||
day.routes().iter().map(|r| r.distance).max().unwrap()
|
||||
}
|
||||
|
||||
struct Day09<'a> {
|
||||
locations: HashSet<Location<'a>>,
|
||||
distances: HashMap<LocationPair<'a>, usize>,
|
||||
locations: HashSet<Location<'a>>,
|
||||
distances: HashMap<LocationPair<'a>, usize>,
|
||||
}
|
||||
|
||||
impl<'a> Day09<'a> {
|
||||
fn new(input: &str) -> Day09 {
|
||||
let mut locations = HashSet::new();
|
||||
let mut distances = HashMap::new();
|
||||
|
||||
for line in input.lines() {
|
||||
let mut split_eq = line.split(" = ");
|
||||
let mut split_to = split_eq.next().unwrap().split(" to ");
|
||||
let a = Location(split_to.next().unwrap());
|
||||
let b = Location(split_to.last().unwrap());
|
||||
let distance = split_eq.last().unwrap().parse::<usize>().unwrap();
|
||||
|
||||
locations.insert(a);
|
||||
locations.insert(b);
|
||||
distances.insert(LocationPair(a, b), distance);
|
||||
}
|
||||
|
||||
Day09 { locations: locations, distances: distances }
|
||||
fn new(input: &str) -> Day09 {
|
||||
let mut locations = HashSet::new();
|
||||
let mut distances = HashMap::new();
|
||||
|
||||
for line in input.lines() {
|
||||
let mut split_eq = line.split(" = ");
|
||||
let mut split_to = split_eq.next().unwrap().split(" to ");
|
||||
let a = Location(split_to.next().unwrap());
|
||||
let b = Location(split_to.last().unwrap());
|
||||
let distance = split_eq.last().unwrap().parse::<usize>().unwrap();
|
||||
|
||||
locations.insert(a);
|
||||
locations.insert(b);
|
||||
distances.insert(LocationPair(a, b), distance);
|
||||
}
|
||||
|
||||
fn routes(&self) -> Vec<Route> {
|
||||
let mut locations = self.locations.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<Location>>();
|
||||
let heap = Heap::new(&mut locations);
|
||||
heap.map(|p| self.route(p)).collect()
|
||||
Day09 {
|
||||
locations: locations,
|
||||
distances: distances,
|
||||
}
|
||||
|
||||
fn route(&self, locations: Vec<Location<'a>>) -> Route {
|
||||
let distance = locations.windows(2)
|
||||
.map(|w| self.distances[&LocationPair(w[0], w[1])])
|
||||
.fold(0, |sum, dist| sum + dist);
|
||||
Route { locations: locations, distance: distance }
|
||||
}
|
||||
|
||||
fn routes(&self) -> Vec<Route> {
|
||||
let mut locations = self.locations
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<Location>>();
|
||||
let heap = Heap::new(&mut locations);
|
||||
heap.map(|p| self.route(p)).collect()
|
||||
}
|
||||
|
||||
fn route(&self, locations: Vec<Location<'a>>) -> Route {
|
||||
let distance = locations.windows(2)
|
||||
.map(|w| self.distances[&LocationPair(w[0], w[1])])
|
||||
.fold(0, |sum, dist| sum + dist);
|
||||
Route {
|
||||
locations: locations,
|
||||
distance: distance,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Route<'a> {
|
||||
locations: Vec<Location<'a>>,
|
||||
distance: usize,
|
||||
locations: Vec<Location<'a>>,
|
||||
distance: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone,Copy,Debug,Eq,PartialEq,PartialOrd,Ord)]
|
||||
#[derive(Clone,Copy,Debug,Eq,Hash,PartialEq,PartialOrd,Ord)]
|
||||
struct Location<'a>(&'a str);
|
||||
|
||||
impl<'a> Hash for Location<'a> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug,Eq)]
|
||||
struct LocationPair<'a>(Location<'a>, Location<'a>);
|
||||
|
||||
impl<'a> PartialEq for LocationPair<'a> {
|
||||
fn eq(&self, other: &LocationPair) -> bool {
|
||||
let mut a = vec![&self.0, &self.1];
|
||||
a.sort();
|
||||
fn eq(&self, other: &LocationPair) -> bool {
|
||||
let mut a = vec![&self.0, &self.1];
|
||||
a.sort();
|
||||
|
||||
let mut b = vec![&other.0, &other.1];
|
||||
b.sort();
|
||||
let mut b = vec![&other.0, &other.1];
|
||||
b.sort();
|
||||
|
||||
a == b
|
||||
}
|
||||
a == b
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Hash for LocationPair<'a> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let mut locations = vec![&self.0, &self.1];
|
||||
locations.sort();
|
||||
locations.hash(state);
|
||||
}
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let mut locations = vec![&self.0, &self.1];
|
||||
locations.sort();
|
||||
locations.hash(state);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in new issue