From d9c69654e9afca6273f7d6e69ec3974883ee4af1 Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Sun, 18 Sep 2016 15:41:28 -0700 Subject: [PATCH] [rust] Update Rust, run Clippy --- ruby/day_09.rb | 58 +++++++------- rust/Cargo.lock | 17 ++++ rust/input/day_09.txt | 56 ++++++------- rust/src/day_02.rs | 96 +++++++++++++---------- rust/src/day_03.rs | 177 ++++++++++++++++++++---------------------- rust/src/day_05.rs | 43 +++++----- rust/src/day_07.rs | 157 ++++++++++++++++++++----------------- rust/src/day_08.rs | 88 ++++++++++++--------- rust/src/day_09.rs | 144 +++++++++++++++++----------------- 9 files changed, 442 insertions(+), 394 deletions(-) diff --git a/ruby/day_09.rb b/ruby/day_09.rb index 0f3bf51..af9ed3f 100644 --- a/ruby/day_09.rb +++ b/ruby/day_09.rb @@ -1,4 +1,4 @@ -require "letters" +# require "letters" distances = Hash.new {|h,k| h[k] = {} } DATA.read.scan(/^(.*) to (.*) = (.*)$/).each do |from, to, distance| distance = distance.to_i @@ -8,31 +8,31 @@ end locations = distances.keys puts locations.permutation.map {|p| p.each_cons(2).map {|a,b| distances[a][b] }.inject(&:+) }.max __END__ -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 diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 79bb4e2..c2e2a06 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -127,3 +127,20 @@ name = "winapi-build" version = "0.1.1" 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" diff --git a/rust/input/day_09.txt b/rust/input/day_09.txt index df5432f..38d4369 100644 --- a/rust/input/day_09.txt +++ b/rust/input/day_09.txt @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/rust/src/day_02.rs b/rust/src/day_02.rs index bba4e38..c8f3824 100644 --- a/rust/src/day_02.rs +++ b/rust/src/day_02.rs @@ -1,65 +1,75 @@ pub fn solve(input: &str) -> i32 { - let presents = input.split("\n").map(|line| Present::new(line)).collect::>(); - presents.iter().fold(0u32, |acc, present| acc + present.ribbon()) as i32 + let presents = + input.split('\n').map(|line| Present::new(line)).collect::>(); + 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::().unwrap()) - .collect::>(); - Present { length: dimensions[0], width: dimensions[1], height: dimensions[2] } + fn new(input: &str) -> Self { + let dimensions = input.split('x') + .map(|d| d.parse::().unwrap()) + .collect::>(); + 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 { - vec![self.length + self.width, - self.width + self.height, - self.height + self.length ].iter().map(|&x| 2 * x).collect() - } + fn perimeters(&self) -> Vec { + 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 { - vec![self.length * self.width, self.width * self.height, self.height * self.length] - } + fn side_areas(&self) -> Vec { + 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()); } diff --git a/rust/src/day_03.rs b/rust/src/day_03.rs index 8c720f6..f04ecae 100644 --- a/rust/src/day_03.rs +++ b/rust/src/day_03.rs @@ -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 = HashMap::new(); - Santa::houses_visited(&santa, &mut houses); - Santa::houses_visited(&robo_santa, &mut houses); - houses.len() as i32 + let mut houses: HashMap = 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) { - let santa = Santa::new(directions); - houses.insert(santa.location, 1); + fn houses_visited(directions: &str, houses: &mut HashMap) { + 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 { - 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 { + 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::>(); - let expected = vec![Point { x: 1, y: 0 }]; - assert_eq!(expected, points); - - let mut houses: HashMap = 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::>(); + let expected = vec![Point { x: 1, y: 0 }]; + assert_eq!(expected, points); + + let mut houses: HashMap = 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 = 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 = 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 = 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 = 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); } diff --git a/rust/src/day_05.rs b/rust/src/day_05.rs index 760842e..23a2d97 100644 --- a/rust/src/day_05.rs +++ b/rust/src/day_05.rs @@ -3,42 +3,41 @@ use regex::Regex; 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 { - has_pair_of_two_letters(string) && - has_letter_sandwich(string) +fn is_nice(string: &str) -> bool { + has_pair_of_two_letters(string) && has_letter_sandwich(string) } -fn has_three_vowels(string: &String) -> bool { - let three_vowels = Regex::new(r"[aeiou].*[aeiou].*[aeiou]").unwrap(); - three_vowels.is_match(string) +fn has_three_vowels(string: &str) -> bool { + let three_vowels = Regex::new(r"[aeiou].*[aeiou].*[aeiou]").unwrap(); + three_vowels.is_match(string) } -fn has_double_letters(string: &String) -> bool { - string.as_bytes().windows(2).any(|win| win[0] == win[1]) +fn has_double_letters(string: &str) -> bool { + string.as_bytes().windows(2).any(|win| win[0] == win[1]) } -fn has_no_substrings(string: &String) -> bool { - !vec!["ab", "cd", "pq", "xy"].iter().any(|&s| string.contains(s)) +fn has_no_substrings(string: &str) -> bool { + !vec!["ab", "cd", "pq", "xy"].iter().any(|&s| string.contains(s)) } -fn has_pair_of_two_letters(string: &String) -> bool { - string.as_bytes().windows(2).any(|win| { - let s = String::from_utf8(win.to_vec()).unwrap(); - string.split(&s).count() > 2 - }) +fn has_pair_of_two_letters(string: &str) -> bool { + string.as_bytes().windows(2).any(|win| { + let s = String::from_utf8(win.to_vec()).unwrap(); + string.split(&s).count() > 2 + }) } -fn has_letter_sandwich(string: &String) -> bool { - string.as_bytes().windows(3).any(|win| win[0] == win[2]) +fn has_letter_sandwich(string: &str) -> bool { + string.as_bytes().windows(3).any(|win| win[0] == win[2]) } #[test] fn test_nice() { - assert!( is_nice(&"qjhvhtzxzqqjkmpb".to_string())); - assert!( is_nice(&"xxyxx ".to_string())); - assert!(!is_nice(&"uurcxstgmygtbstg ".to_string())); - assert!(!is_nice(&"ieodomkazucvgmuy ".to_string())); + assert!(is_nice(&"qjhvhtzxzqqjkmpb".to_string())); + assert!(is_nice(&"xxyxx ".to_string())); + assert!(!is_nice(&"uurcxstgmygtbstg ".to_string())); + assert!(!is_nice(&"ieodomkazucvgmuy ".to_string())); } diff --git a/rust/src/day_07.rs b/rust/src/day_07.rs index 97425b2..eee690c 100644 --- a/rust/src/day_07.rs +++ b/rust/src/day_07.rs @@ -2,79 +2,88 @@ use std::collections::HashMap; #[test] fn test_day_07() { - let input = "123 -> x + let input = "123 -> x 456 -> y x AND y -> d x OR y -> e x LSHIFT 2 -> f -y RSHIFT 2 -> g +y \ + RSHIFT 2 -> g NOT x -> h NOT y -> i"; - assert_eq!(72, solve(input, "d")); - assert_eq!(507, solve(input, "e")); - assert_eq!(492, solve(input, "f")); - assert_eq!(114, solve(input, "g")); - assert_eq!(65412, solve(input, "h")); - assert_eq!(65079, solve(input, "i")); - assert_eq!(123, solve(input, "x")); - assert_eq!(456, solve(input, "y")); + assert_eq!(72, solve(input, "d")); + assert_eq!(507, solve(input, "e")); + assert_eq!(492, solve(input, "f")); + assert_eq!(114, solve(input, "g")); + assert_eq!(65412, solve(input, "h")); + assert_eq!(65079, solve(input, "i")); + assert_eq!(123, solve(input, "x")); + assert_eq!(456, solve(input, "y")); } pub fn solve(input: &str, wire_id: &str) -> u16 { - let mut circuit = Circuit::new(input); - circuit.connections.insert(Wire("b"), Signal::Value(3176)); - circuit.signal_on(wire_id) + let mut circuit = Circuit::new(input); + circuit.connections.insert(Wire("b"), Signal::Value(3176)); + circuit.signal_on(wire_id) } #[test] 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::Wire(Wire("x")), circuit.connections[&Wire("y")]); - assert_eq!(Signal::Gate(Gate::Not(Wire("x"))), circuit.connections[&Wire("h")]); + assert_eq!(Signal::Value(123), circuit.connections[&Wire("x")]); + assert_eq!(Signal::Wire(Wire("x")), circuit.connections[&Wire("y")]); + 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("y")); - assert_eq!(65412, circuit.signal_on("h")); - assert_eq!(123, circuit.signal_on("i")); + assert_eq!(123, circuit.signal_on("x")); + assert_eq!(123, circuit.signal_on("y")); + assert_eq!(65412, circuit.signal_on("h")); + assert_eq!(123, circuit.signal_on("i")); } struct Circuit<'a> { - connections: HashMap, Signal<'a>>, + connections: HashMap, Signal<'a>>, } impl<'a> Circuit<'a> { - fn new(input: &str) -> Circuit { - let mut connections = HashMap::new(); - for line in input.lines() - .map(|line| line.split(" -> ").collect::>()) { - let wire = Wire(line.last().expect("wire")); - let signal = Signal::new(line.first().expect("line").split(" ").collect()); - connections.insert(wire, signal); - } - - Circuit { connections: connections } + fn new(input: &str) -> Circuit { + let mut connections = HashMap::new(); + for line in input.lines() + .map(|line| line.split(" -> ").collect::>()) { + let wire = Wire(line.last().expect("wire")); + let signal = + Signal::new(line.first().expect("line").split(' ').collect()); + connections.insert(wire, signal); } - // TODO This should probably return a Result...? - // 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); - let value = match self.connections.get(&wire).cloned() - .unwrap_or_else(|| Signal::Value(wire_id.parse::().unwrap())) { - Signal::Value(value) => return value, - Signal::Wire(Wire(input_wire_id)) => self.signal_on(input_wire_id), - Signal::Gate(Gate::And(Wire(a), Wire(b))) => self.signal_on(a) & self.signal_on(b), - 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 - } + Circuit { connections: connections } + } + + // TODO This should probably return a Result...? + // 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); + let value = match self.connections + .get(&wire) + .cloned() + .unwrap_or_else(|| Signal::Value(wire_id.parse::().unwrap())) { + Signal::Value(value) => return value, + Signal::Wire(Wire(input_wire_id)) => self.signal_on(input_wire_id), + Signal::Gate(Gate::And(Wire(a), Wire(b))) => { + self.signal_on(a) & self.signal_on(b) + } + 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)] @@ -82,35 +91,41 @@ struct Wire<'a>(&'a str); #[derive(Clone,Debug,PartialEq)] enum Signal<'a> { - Gate(Gate<'a>), - Wire(Wire<'a>), - Value(u16), + Gate(Gate<'a>), + Wire(Wire<'a>), + Value(u16), } impl<'a> Signal<'a> { - fn new(input: Vec<&str>) -> Signal { - match &input[..] { - [a, "AND", b] => Signal::Gate(Gate::And(Wire(a), Wire(b))), - ["NOT", a] => Signal::Gate(Gate::Not(Wire(a))), - [a, "OR", b] => Signal::Gate(Gate::Or(Wire(a), Wire(b))), - [a, "LSHIFT", b] => Signal::Gate(Gate::LeftShift(Wire(a), b.parse::().expect("lshift"))), - [a, "RSHIFT", b] => Signal::Gate(Gate::RightShift(Wire(a), b.parse::().expect("rshift"))), - [value] => { - match value.parse::() { - Ok(value) => Signal::Value(value), - Err(_) => Signal::Wire(Wire(value)), - } - } - _ => panic!("Unrecognized input: {:?}", input), + fn new(input: Vec<&str>) -> Signal { + match input[..] { + [a, "AND", b] => Signal::Gate(Gate::And(Wire(a), Wire(b))), + ["NOT", a] => Signal::Gate(Gate::Not(Wire(a))), + [a, "OR", b] => Signal::Gate(Gate::Or(Wire(a), Wire(b))), + [a, "LSHIFT", b] => { + Signal::Gate(Gate::LeftShift(Wire(a), + b.parse::().expect("lshift"))) + } + [a, "RSHIFT", b] => { + Signal::Gate(Gate::RightShift(Wire(a), + b.parse::().expect("rshift"))) + } + [value] => { + match value.parse::() { + Ok(value) => Signal::Value(value), + Err(_) => Signal::Wire(Wire(value)), } + } + _ => panic!("Unrecognized input: {:?}", input), } + } } #[derive(Clone,Debug,PartialEq)] enum Gate<'a> { - And(Wire<'a>, Wire<'a>), - LeftShift(Wire<'a>, u16), - Not(Wire<'a>), - Or(Wire<'a>, Wire<'a>), - RightShift(Wire<'a>, u16), + And(Wire<'a>, Wire<'a>), + LeftShift(Wire<'a>, u16), + Not(Wire<'a>), + Or(Wire<'a>, Wire<'a>), + RightShift(Wire<'a>, u16), } diff --git a/rust/src/day_08.rs b/rust/src/day_08.rs index 73fa154..6fda47a 100644 --- a/rust/src/day_08.rs +++ b/rust/src/day_08.rs @@ -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::>(); - 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::>(); + 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#"\""#)) } diff --git a/rust/src/day_09.rs b/rust/src/day_09.rs index ebddb1c..e7915a9 100644 --- a/rust/src/day_09.rs +++ b/rust/src/day_09.rs @@ -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>, - distances: HashMap, usize>, + locations: HashSet>, + distances: HashMap, 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::().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::().unwrap(); + + locations.insert(a); + locations.insert(b); + distances.insert(LocationPair(a, b), distance); } - fn routes(&self) -> Vec { - let mut locations = self.locations.iter() - .cloned() - .collect::>(); - let heap = Heap::new(&mut locations); - heap.map(|p| self.route(p)).collect() + Day09 { + locations: locations, + distances: distances, } - - fn route(&self, locations: Vec>) -> 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 { + let mut locations = self.locations + .iter() + .cloned() + .collect::>(); + let heap = Heap::new(&mut locations); + heap.map(|p| self.route(p)).collect() + } + + fn route(&self, locations: Vec>) -> 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>, - distance: usize, + locations: Vec>, + 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(&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(&self, state: &mut H) { - let mut locations = vec![&self.0, &self.1]; - locations.sort(); - locations.hash(state); - } + fn hash(&self, state: &mut H) { + let mut locations = vec![&self.0, &self.1]; + locations.sort(); + locations.hash(state); + } }