[rust] Update Rust, run Clippy

wip
Alpha Chen 8 years ago
parent 1697560761
commit d9c69654e9

@ -1,4 +1,4 @@
require "letters" # require "letters"
distances = Hash.new {|h,k| h[k] = {} } distances = Hash.new {|h,k| h[k] = {} }
DATA.read.scan(/^(.*) to (.*) = (.*)$/).each do |from, to, distance| DATA.read.scan(/^(.*) to (.*) = (.*)$/).each do |from, to, distance|
distance = distance.to_i distance = distance.to_i
@ -8,31 +8,31 @@ end
locations = distances.keys locations = distances.keys
puts locations.permutation.map {|p| p.each_cons(2).map {|a,b| distances[a][b] }.inject(&:+) }.max puts locations.permutation.map {|p| p.each_cons(2).map {|a,b| distances[a][b] }.inject(&:+) }.max
__END__ __END__
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

17
rust/Cargo.lock generated

@ -127,3 +127,20 @@ name = "winapi-build"
version = "0.1.1" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "307c92332867e586720c0222ee9d890bbe8431711efed8a1b06bc5b40fc66bd7"
"checksum aho-corasick 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f36f237c490deb976b38aca6369182dceb5a7af249aabf41c0ba5a964bac5ed"
"checksum gcc 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)" = "ca10e3e1f1c8278047da19b94dc17c4397861150d5fbcea052eedb1d9847d356"
"checksum kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b5e7edf375e6d26243bde172f1d5ed1446f4a766fc9b7006e1fd27258243f1"
"checksum libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
"checksum libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "10569e57695cc2c91ca4214357907649c9e242dc822c9ae623d0e0b0d68aa4d9"
"checksum memchr 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "dc66b0957bf6ae6590681ceac49b0df16823d43037d49aaf2ee658d483af30ab"
"checksum permutohedron 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "abf78a1e8b52782de92fc4f361362a62bcf5fd5718b5432b48cb381485740b83"
"checksum rand 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5eee40bdf3d293e1648490ab47e5471d9ab3e455e6b0bd48e558c454be4a015e"
"checksum regex 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e0940ad6bf8abf79e3210809a6a49e199fc8e00b7deafc0d9394157f56f5401e"
"checksum regex-syntax 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fcf1e805b0a23c845be2a303136d840a1511284727bc1f1fc32d079552ef901f"
"checksum rust-crypto 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "b8672a8eb8db93d0938972e391159ba66912b415285ee5cf0ebe732df9e53b70"
"checksum rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "1a48546a64cae47d06885e9bccadb99d0547d877a94c5167fa451ea33a484456"
"checksum time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "8c4aeaa1c95974f5763c3a5ac0db95a19793589bcea5d22e161b5587e3aad029"
"checksum winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dc3583688b861fcd83c2823d37cf2cd2446c233dd7ba3f97884d1a7302817537"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

@ -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);
} }

@ -3,42 +3,41 @@
use regex::Regex; use regex::Regex;
pub fn solve(input: &str) -> i32 { pub fn solve(input: &str) -> i32 {
input.lines().filter(|&s| is_nice(&s.to_string())).count() as i32 input.lines().filter(|&s| is_nice(&s.to_string())).count() as i32
} }
fn is_nice(string: &String) -> bool { fn is_nice(string: &str) -> bool {
has_pair_of_two_letters(string) && has_pair_of_two_letters(string) && has_letter_sandwich(string)
has_letter_sandwich(string)
} }
fn has_three_vowels(string: &String) -> bool { fn has_three_vowels(string: &str) -> bool {
let three_vowels = Regex::new(r"[aeiou].*[aeiou].*[aeiou]").unwrap(); let three_vowels = Regex::new(r"[aeiou].*[aeiou].*[aeiou]").unwrap();
three_vowels.is_match(string) three_vowels.is_match(string)
} }
fn has_double_letters(string: &String) -> bool { fn has_double_letters(string: &str) -> bool {
string.as_bytes().windows(2).any(|win| win[0] == win[1]) string.as_bytes().windows(2).any(|win| win[0] == win[1])
} }
fn has_no_substrings(string: &String) -> bool { fn has_no_substrings(string: &str) -> bool {
!vec!["ab", "cd", "pq", "xy"].iter().any(|&s| string.contains(s)) !vec!["ab", "cd", "pq", "xy"].iter().any(|&s| string.contains(s))
} }
fn has_pair_of_two_letters(string: &String) -> bool { fn has_pair_of_two_letters(string: &str) -> bool {
string.as_bytes().windows(2).any(|win| { string.as_bytes().windows(2).any(|win| {
let s = String::from_utf8(win.to_vec()).unwrap(); let s = String::from_utf8(win.to_vec()).unwrap();
string.split(&s).count() > 2 string.split(&s).count() > 2
}) })
} }
fn has_letter_sandwich(string: &String) -> bool { fn has_letter_sandwich(string: &str) -> bool {
string.as_bytes().windows(3).any(|win| win[0] == win[2]) string.as_bytes().windows(3).any(|win| win[0] == win[2])
} }
#[test] #[test]
fn test_nice() { fn test_nice() {
assert!( is_nice(&"qjhvhtzxzqqjkmpb".to_string())); assert!(is_nice(&"qjhvhtzxzqqjkmpb".to_string()));
assert!( is_nice(&"xxyxx ".to_string())); assert!(is_nice(&"xxyxx ".to_string()));
assert!(!is_nice(&"uurcxstgmygtbstg ".to_string())); assert!(!is_nice(&"uurcxstgmygtbstg ".to_string()));
assert!(!is_nice(&"ieodomkazucvgmuy ".to_string())); assert!(!is_nice(&"ieodomkazucvgmuy ".to_string()));
} }

@ -2,79 +2,88 @@ use std::collections::HashMap;
#[test] #[test]
fn test_day_07() { fn test_day_07() {
let input = "123 -> x let input = "123 -> x
456 -> y 456 -> y
x AND y -> d x AND y -> d
x OR y -> e x OR y -> e
x LSHIFT 2 -> f x LSHIFT 2 -> f
y RSHIFT 2 -> g y \
RSHIFT 2 -> g
NOT x -> h NOT x -> h
NOT y -> i"; NOT y -> i";
assert_eq!(72, solve(input, "d")); assert_eq!(72, solve(input, "d"));
assert_eq!(507, solve(input, "e")); assert_eq!(507, solve(input, "e"));
assert_eq!(492, solve(input, "f")); assert_eq!(492, solve(input, "f"));
assert_eq!(114, solve(input, "g")); assert_eq!(114, solve(input, "g"));
assert_eq!(65412, solve(input, "h")); assert_eq!(65412, solve(input, "h"));
assert_eq!(65079, solve(input, "i")); assert_eq!(65079, solve(input, "i"));
assert_eq!(123, solve(input, "x")); assert_eq!(123, solve(input, "x"));
assert_eq!(456, solve(input, "y")); assert_eq!(456, solve(input, "y"));
} }
pub fn solve(input: &str, wire_id: &str) -> u16 { pub fn solve(input: &str, wire_id: &str) -> u16 {
let mut circuit = Circuit::new(input); let mut circuit = Circuit::new(input);
circuit.connections.insert(Wire("b"), Signal::Value(3176)); circuit.connections.insert(Wire("b"), Signal::Value(3176));
circuit.signal_on(wire_id) circuit.signal_on(wire_id)
} }
#[test] #[test]
fn test_circuit() { fn test_circuit() {
let mut circuit = Circuit::new("123 -> x\nx -> y\nNOT x -> h\nx AND y -> i"); let mut circuit = Circuit::new("123 -> x\nx -> y\nNOT x -> h\nx AND y -> i");
assert_eq!(Signal::Value(123), circuit.connections[&Wire("x")]); assert_eq!(Signal::Value(123), circuit.connections[&Wire("x")]);
assert_eq!(Signal::Wire(Wire("x")), circuit.connections[&Wire("y")]); assert_eq!(Signal::Wire(Wire("x")), circuit.connections[&Wire("y")]);
assert_eq!(Signal::Gate(Gate::Not(Wire("x"))), circuit.connections[&Wire("h")]); assert_eq!(Signal::Gate(Gate::Not(Wire("x"))),
circuit.connections[&Wire("h")]);
assert_eq!(123, circuit.signal_on("x")); assert_eq!(123, circuit.signal_on("x"));
assert_eq!(123, circuit.signal_on("y")); assert_eq!(123, circuit.signal_on("y"));
assert_eq!(65412, circuit.signal_on("h")); assert_eq!(65412, circuit.signal_on("h"));
assert_eq!(123, circuit.signal_on("i")); assert_eq!(123, circuit.signal_on("i"));
} }
struct Circuit<'a> { struct Circuit<'a> {
connections: HashMap<Wire<'a>, Signal<'a>>, connections: HashMap<Wire<'a>, Signal<'a>>,
} }
impl<'a> Circuit<'a> { impl<'a> Circuit<'a> {
fn new(input: &str) -> Circuit { fn new(input: &str) -> Circuit {
let mut connections = HashMap::new(); let mut connections = HashMap::new();
for line in input.lines() for line in input.lines()
.map(|line| line.split(" -> ").collect::<Vec<_>>()) { .map(|line| line.split(" -> ").collect::<Vec<_>>()) {
let wire = Wire(line.last().expect("wire")); let wire = Wire(line.last().expect("wire"));
let signal = Signal::new(line.first().expect("line").split(" ").collect()); let signal =
connections.insert(wire, signal); Signal::new(line.first().expect("line").split(' ').collect());
} connections.insert(wire, signal);
Circuit { connections: connections }
} }
// TODO This should probably return a Result...? Circuit { connections: connections }
// TODO Is there a way for this to not be mutable? }
fn signal_on(&mut self, wire_id: &'a str) -> u16 {
let wire = Wire(wire_id); // TODO This should probably return a Result...?
let value = match self.connections.get(&wire).cloned() // TODO Is there a way for this to not be mutable?
.unwrap_or_else(|| Signal::Value(wire_id.parse::<u16>().unwrap())) { fn signal_on(&mut self, wire_id: &'a str) -> u16 {
Signal::Value(value) => return value, let wire = Wire(wire_id);
Signal::Wire(Wire(input_wire_id)) => self.signal_on(input_wire_id), let value = match self.connections
Signal::Gate(Gate::And(Wire(a), Wire(b))) => self.signal_on(a) & self.signal_on(b), .get(&wire)
Signal::Gate(Gate::LeftShift(Wire(a), i)) => self.signal_on(a) << i, .cloned()
Signal::Gate(Gate::Not(Wire(a))) => !self.signal_on(a), .unwrap_or_else(|| Signal::Value(wire_id.parse::<u16>().unwrap())) {
Signal::Gate(Gate::Or(Wire(a), Wire(b))) => self.signal_on(a) | self.signal_on(b), Signal::Value(value) => return value,
Signal::Gate(Gate::RightShift(Wire(a), i)) => self.signal_on(a) >> i, Signal::Wire(Wire(input_wire_id)) => self.signal_on(input_wire_id),
}; Signal::Gate(Gate::And(Wire(a), Wire(b))) => {
self.connections.insert(wire, Signal::Value(value)); self.signal_on(a) & self.signal_on(b)
value }
} Signal::Gate(Gate::LeftShift(Wire(a), i)) => self.signal_on(a) << i,
Signal::Gate(Gate::Not(Wire(a))) => !self.signal_on(a),
Signal::Gate(Gate::Or(Wire(a), Wire(b))) => {
self.signal_on(a) | self.signal_on(b)
}
Signal::Gate(Gate::RightShift(Wire(a), i)) => self.signal_on(a) >> i,
};
self.connections.insert(wire, Signal::Value(value));
value
}
} }
#[derive(Clone,Debug,Eq,Hash,PartialEq)] #[derive(Clone,Debug,Eq,Hash,PartialEq)]
@ -82,35 +91,41 @@ struct Wire<'a>(&'a str);
#[derive(Clone,Debug,PartialEq)] #[derive(Clone,Debug,PartialEq)]
enum Signal<'a> { enum Signal<'a> {
Gate(Gate<'a>), Gate(Gate<'a>),
Wire(Wire<'a>), Wire(Wire<'a>),
Value(u16), Value(u16),
} }
impl<'a> Signal<'a> { impl<'a> Signal<'a> {
fn new(input: Vec<&str>) -> Signal { fn new(input: Vec<&str>) -> Signal {
match &input[..] { match input[..] {
[a, "AND", b] => Signal::Gate(Gate::And(Wire(a), Wire(b))), [a, "AND", b] => Signal::Gate(Gate::And(Wire(a), Wire(b))),
["NOT", a] => Signal::Gate(Gate::Not(Wire(a))), ["NOT", a] => Signal::Gate(Gate::Not(Wire(a))),
[a, "OR", b] => Signal::Gate(Gate::Or(Wire(a), Wire(b))), [a, "OR", b] => Signal::Gate(Gate::Or(Wire(a), Wire(b))),
[a, "LSHIFT", b] => Signal::Gate(Gate::LeftShift(Wire(a), b.parse::<u16>().expect("lshift"))), [a, "LSHIFT", b] => {
[a, "RSHIFT", b] => Signal::Gate(Gate::RightShift(Wire(a), b.parse::<u16>().expect("rshift"))), Signal::Gate(Gate::LeftShift(Wire(a),
[value] => { b.parse::<u16>().expect("lshift")))
match value.parse::<u16>() { }
Ok(value) => Signal::Value(value), [a, "RSHIFT", b] => {
Err(_) => Signal::Wire(Wire(value)), Signal::Gate(Gate::RightShift(Wire(a),
} b.parse::<u16>().expect("rshift")))
} }
_ => panic!("Unrecognized input: {:?}", input), [value] => {
match value.parse::<u16>() {
Ok(value) => Signal::Value(value),
Err(_) => Signal::Wire(Wire(value)),
} }
}
_ => panic!("Unrecognized input: {:?}", input),
} }
}
} }
#[derive(Clone,Debug,PartialEq)] #[derive(Clone,Debug,PartialEq)]
enum Gate<'a> { enum Gate<'a> {
And(Wire<'a>, Wire<'a>), And(Wire<'a>, Wire<'a>),
LeftShift(Wire<'a>, u16), LeftShift(Wire<'a>, u16),
Not(Wire<'a>), Not(Wire<'a>),
Or(Wire<'a>, Wire<'a>), Or(Wire<'a>, Wire<'a>),
RightShift(Wire<'a>, u16), RightShift(Wire<'a>, u16),
} }

@ -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…
Cancel
Save