[2017][rust][4.x]
change kynzkxukvorlplpsoquorpmzukyxpylw
commit d0b76d3a6706e2f0699d3f31419a542fe083c107
author Alpha Chen <alpha.chen@gmail.com>
date
parent xunrwqxn
diff --git a/2017/rust/src/.day_04.rs.rustfmt b/2017/rust/src/.day_04.rs.rustfmt
new file mode 100644
index 0000000..3f68736
--- /dev/null
+++ b/2017/rust/src/.day_04.rs.rustfmt
@@ -0,0 +1,29 @@
+use std::collections::HashSet;
+use failure::Error;
+
+pub fn solve(input: &str) -> Result<String, Error> {
+    Ok(input
+        .trim()
+        .lines()
+        .map(|line| Passphrase { words: line.into() })
+        .filter(Passphrase::is_valid)
+        .count()
+        .to_string())
+}
+
+struct Passphrase {
+    words: String,
+}
+
+impl Passphrase {
+    fn is_valid(&self) -> bool {
+        let mut words = HashSet::new();
+        return !self.words.split_whitespace().any(|word| {
+            if words.contains(word) {
+                return true;
+            }
+            words.insert(word);
+            return false;
+        })
+    }
+}
diff --git a/2017/rust/src/day_03.rs b/2017/rust/src/day_03.rs
index 20f05a7..8c59d81 100644
--- a/2017/rust/src/day_03.rs
+++ b/2017/rust/src/day_03.rs
@@ -2,6 +2,7 @@ use std::collections::HashMap;
 use std::iter;
 use failure::*;
 
+#[allow(dead_code)]
 pub fn solve(input: &str) -> Result<String, Error> {
     let input: usize = input.trim().parse()?;
 
@@ -23,13 +24,14 @@ pub fn solve(input: &str) -> Result<String, Error> {
         })
         .find(|value| value > &input)
         .map(|value| value.to_string())
-        .ok_or_else(|| format_err!(""))
+        .ok_or_else(|| err_msg(""))
 }
 
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 struct Coord(isize, isize);
 
 impl Coord {
+    #[allow(dead_code)]
     fn neighbors(&self) -> Vec<Coord> {
         vec![
             [-1, 1],
@@ -54,10 +56,12 @@ enum Dir {
     Down,
 }
 
+#[allow(dead_code)]
 lazy_static! {
     static ref DIRS: Vec<Dir> = vec![Dir::Right, Dir::Up, Dir::Left, Dir::Down];
 }
 
+#[allow(dead_code)]
 fn spiral() -> impl Iterator<Item = Coord> {
     (1..)
         .flat_map(|x| iter::repeat(x).take(2))
diff --git a/2017/rust/src/day_04.rs b/2017/rust/src/day_04.rs
new file mode 100644
index 0000000..df96579
--- /dev/null
+++ b/2017/rust/src/day_04.rs
@@ -0,0 +1,36 @@
+use std::collections::HashSet;
+use failure::Error;
+
+pub fn solve(input: &str) -> Result<String, Error> {
+    Ok(input
+        .trim()
+        .lines()
+        .map(|line| Passphrase { words: line.into() })
+        .filter(Passphrase::is_valid)
+        .count()
+        .to_string())
+}
+
+struct Passphrase {
+    words: String,
+}
+
+impl Passphrase {
+    fn is_valid(&self) -> bool {
+        let mut words = HashSet::new();
+        return !self.words
+            .split_whitespace()
+            .map(|word| {
+                let mut chars: Vec<String> = word.chars().map(|x| x.to_string()).collect();
+                chars.sort();
+                chars.as_slice().join("")
+            })
+            .any(|word| {
+                if words.contains(&word) {
+                    return true;
+                }
+                words.insert(word);
+                return false;
+            });
+    }
+}
diff --git a/2017/rust/src/main.rs b/2017/rust/src/main.rs
index 522e2c0..a2983c8 100644
--- a/2017/rust/src/main.rs
+++ b/2017/rust/src/main.rs
@@ -11,6 +11,7 @@ use failure::Error;
 mod day_01;
 mod day_02;
 mod day_03;
+mod day_04;
 
 fn main() {
     if let Err(e) = run() {
@@ -22,7 +23,7 @@ fn run() -> Result<(), Error> {
     let mut input = String::new();
     io::stdin().read_to_string(&mut input)?;
 
-    let solution = day_03::solve(&input)?;
+    let solution = day_04::solve(&input)?;
     println!("{}", solution);
 
     Ok(())