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