[2017][rust][3.x]
change xunrwqxnkxlpwnzywnkrnlxlxlqrwxnt
commit ffca59306c831969073a9e4d7f697f18c6782345
author Alpha Chen <alpha.chen@gmail.com>
date
parent ywontuqm
diff --git a/2017/rust/Cargo.lock b/2017/rust/Cargo.lock
index ab5c52d..1808e55 100644
--- a/2017/rust/Cargo.lock
+++ b/2017/rust/Cargo.lock
@@ -3,6 +3,7 @@ name = "advent_of_code_2017"
 version = "0.1.0"
 dependencies = [
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -75,6 +76,11 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "lazy_static"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "libc"
 version = "0.2.34"
@@ -141,6 +147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
 "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
 "checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
 "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
diff --git a/2017/rust/Cargo.toml b/2017/rust/Cargo.toml
index 9f0a3e9..91a9f32 100644
--- a/2017/rust/Cargo.toml
+++ b/2017/rust/Cargo.toml
@@ -5,3 +5,4 @@ authors = ["Alpha Chen <alpha.chen@gmail.com>"]
 
 [dependencies]
 failure = "0.1"
+lazy_static = "1.0"
diff --git a/2017/rust/src/day_01.rs b/2017/rust/src/day_01.rs
index fdd0cd2..b526084 100644
--- a/2017/rust/src/day_01.rs
+++ b/2017/rust/src/day_01.rs
@@ -13,15 +13,13 @@ pub fn solve(input: &str) -> Result<String, Error> {
     let offset = input.len() / 2;
 
     let offset_iter = input.iter().cycle().skip(offset);
-    Ok(
-        input
-            .iter()
-            .zip(offset_iter)
-            .filter(|&a| a.0 == a.1)
-            .map(|a| a.0)
-            .sum::<u32>()
-            .to_string(),
-    )
+    Ok(input
+        .iter()
+        .zip(offset_iter)
+        .filter(|&a| a.0 == a.1)
+        .map(|a| a.0)
+        .sum::<u32>()
+        .to_string())
 }
 
 #[test]
diff --git a/2017/rust/src/day_02.rs b/2017/rust/src/day_02.rs
index 8c0da5c..fda9222 100644
--- a/2017/rust/src/day_02.rs
+++ b/2017/rust/src/day_02.rs
@@ -1,19 +1,18 @@
 use failure::*;
 
+#[allow(dead_code)]
 pub fn solve(input: &str) -> Result<String, Error> {
-    Ok(
-        input
-            .trim()
-            .split('\n')
-            .map(|row| {
-                row.split('\t')
-                    .map(|x| x.parse::<usize>().unwrap())
-                    .collect::<Vec<_>>()
-            })
-            .map(|row| checksum(&row))
-            .sum::<usize>()
-            .to_string(),
-    )
+    Ok(input
+        .trim()
+        .split('\n')
+        .map(|row| {
+            row.split('\t')
+                .map(|x| x.parse::<usize>().unwrap())
+                .collect::<Vec<_>>()
+        })
+        .map(|row| checksum(&row))
+        .sum::<usize>()
+        .to_string())
 }
 
 fn checksum(row: &[usize]) -> usize {
@@ -24,9 +23,9 @@ fn checksum(row: &[usize]) -> usize {
 
     row.iter()
         .flat_map(|x| row.iter().map(|y| (x, y)).collect::<Vec<_>>())
-        .filter(|&(a,b)| a != b)
-        .filter(|&(&a,&b)| (a as f64) % (b as f64) == 0.0)
-        .map(|(&a,&b)| a / b)
+        .filter(|&(a, b)| a != b)
+        .filter(|&(&a, &b)| (a as f64) % (b as f64) == 0.0)
+        .map(|(&a, &b)| a / b)
         .next()
         .unwrap()
 }
diff --git a/2017/rust/src/day_03.rs b/2017/rust/src/day_03.rs
new file mode 100644
index 0000000..20f05a7
--- /dev/null
+++ b/2017/rust/src/day_03.rs
@@ -0,0 +1,86 @@
+use std::collections::HashMap;
+use std::iter;
+use failure::*;
+
+pub fn solve(input: &str) -> Result<String, Error> {
+    let input: usize = input.trim().parse()?;
+
+    // 1
+    // spiral()
+    //     .zip(1..)
+    //     .find(|&(_, i)| i == (square - 1))
+    //     .map(|(coord, _)| (coord.0 + coord.1).to_string())
+    //     .ok_or_else(|| format_err!(""))
+
+    // 2
+    let mut grid = HashMap::new();
+    grid.insert(Coord(0, 0), 1);
+    spiral()
+        .map(|coord| {
+            let sum = coord.neighbors().iter().filter_map(|x| grid.get(x)).sum();
+            grid.insert(coord, sum);
+            sum
+        })
+        .find(|value| value > &input)
+        .map(|value| value.to_string())
+        .ok_or_else(|| format_err!(""))
+}
+
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+struct Coord(isize, isize);
+
+impl Coord {
+    fn neighbors(&self) -> Vec<Coord> {
+        vec![
+            [-1, 1],
+            [0, 1],
+            [1, 1],
+            [-1, 0],
+            [1, 0],
+            [-1, -1],
+            [0, -1],
+            [1, -1],
+        ].iter()
+            .map(|delta| Coord(self.0 + delta[0], self.1 + delta[1]))
+            .collect()
+    }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+enum Dir {
+    Right,
+    Up,
+    Left,
+    Down,
+}
+
+lazy_static! {
+    static ref DIRS: Vec<Dir> = vec![Dir::Right, Dir::Up, Dir::Left, Dir::Down];
+}
+
+fn spiral() -> impl Iterator<Item = Coord> {
+    (1..)
+        .flat_map(|x| iter::repeat(x).take(2))
+        .zip(DIRS.iter().cycle())
+        .flat_map(|(steps, dir)| iter::repeat(dir).take(steps))
+        .scan(Coord(0, 0), |state, &dir| {
+            *state = match dir {
+                Dir::Right => Coord(state.0 + 1, state.1),
+                Dir::Up => Coord(state.0, state.1 + 1),
+                Dir::Left => Coord(state.0 - 1, state.1),
+                Dir::Down => Coord(state.0, state.1 - 1),
+            };
+            Some(*state)
+        })
+}
+
+#[test]
+fn test_coords() {
+    let mut spiral = spiral();
+    assert_eq!(spiral.next(), Some(Coord(1, 0)));
+    assert_eq!(spiral.next(), Some(Coord(1, 1)));
+    assert_eq!(spiral.next(), Some(Coord(0, 1)));
+    assert_eq!(spiral.next(), Some(Coord(-1, 1)));
+    assert_eq!(spiral.next(), Some(Coord(-1, 0)));
+    assert_eq!(spiral.next(), Some(Coord(-1, -1)));
+}
diff --git a/2017/rust/src/main.rs b/2017/rust/src/main.rs
index 1dc42c1..522e2c0 100644
--- a/2017/rust/src/main.rs
+++ b/2017/rust/src/main.rs
@@ -1,4 +1,8 @@
+#![feature(conservative_impl_trait)]
+
 extern crate failure;
+#[macro_use]
+extern crate lazy_static;
 
 use std::io::{self, Read};
 
@@ -6,6 +10,7 @@ use failure::Error;
 
 mod day_01;
 mod day_02;
+mod day_03;
 
 fn main() {
     if let Err(e) = run() {
@@ -17,7 +22,7 @@ fn run() -> Result<(), Error> {
     let mut input = String::new();
     io::stdin().read_to_string(&mut input)?;
 
-    let solution = day_02::solve(&input)?;
+    let solution = day_03::solve(&input)?;
     println!("{}", solution);
 
     Ok(())