[2018][rust][04] parsing!
change pvwowkkotrulouykpwyszptzstnmnxwy
commit 81d1256ca34af3cf377602c1576da9c95a9ef410
author Alpha Chen <alpha.chen@gmail.com>
date
parent nsqyzywz
diff --git a/2018/rust/Cargo.lock b/2018/rust/Cargo.lock
index 0d00eb6..1da7712 100644
--- a/2018/rust/Cargo.lock
+++ b/2018/rust/Cargo.lock
@@ -2,6 +2,8 @@
 name = "advent_of_code_2018"
 version = "0.1.0"
 dependencies = [
+ "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -13,11 +15,51 @@ dependencies = [
  "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "arrayref"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "block-buffer"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "byte-tools"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "cfg-if"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "digest"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fake-simd"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "generic-array"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "lazy_static"
 version = "1.2.0"
@@ -28,6 +70,11 @@ name = "libc"
 version = "0.2.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "maplit"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "memchr"
 version = "2.1.1"
@@ -38,6 +85,61 @@ dependencies = [
  "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "pest"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_generator 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest_meta 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "0.4.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "regex"
 version = "1.1.0"
@@ -58,6 +160,27 @@ dependencies = [
  "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "sha-1"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syn"
+version = "0.14.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "thread_local"
 version = "0.3.6"
@@ -66,11 +189,26 @@ dependencies = [
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "typenum"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "ucd-util"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "unicode-xid"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "utf8-ranges"
 version = "1.0.2"
@@ -83,13 +221,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
 "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
+"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
+"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
+"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
 "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
+"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
+"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
+"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
 "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
 "checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
+"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
 "checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
+"checksum pest 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a677051ad923732bb5c70f2d45f8985a96e3eee2e2bff86697e3b11b0c3fcfde"
+"checksum pest_derive 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b76f477146419bc539a63f4ef40e902166cb43b3e51cecc71d9136fd12c567e7"
+"checksum pest_generator 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebee4e9680be4fd162e6f3394ae4192a6b60b1e4d17d845e631f0c68d1a3386"
+"checksum pest_meta 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f6d5f6f0e6082578c86af197d780dc38328e3f768cec06aac9bc46d714e8221"
+"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
+"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
 "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
 "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
+"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
+"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
+"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
+"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77"
 "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
+"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
 "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
 "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
diff --git a/2018/rust/Cargo.toml b/2018/rust/Cargo.toml
index 724709c..40a1311 100644
--- a/2018/rust/Cargo.toml
+++ b/2018/rust/Cargo.toml
@@ -5,4 +5,6 @@ authors = ["Alpha Chen <alpha.chen@gmail.com>"]
 edition = "2018"
 
 [dependencies]
+pest = "2.0"
+pest_derive = "2.0"
 regex = "1"
diff --git a/2018/rust/src/bin/day_04.rs b/2018/rust/src/bin/day_04.rs
new file mode 100644
index 0000000..d29bd0a
--- /dev/null
+++ b/2018/rust/src/bin/day_04.rs
@@ -0,0 +1,120 @@
+use std::error::Error;
+use std::io::{self, Read};
+use std::ops::Range;
+
+use pest::iterators::Pair;
+use pest::Parser;
+use pest_derive::Parser;
+
+fn main() -> Result<(), Box<Error>> {
+    let mut input = String::new();
+    io::stdin().read_to_string(&mut input)?;
+
+    let output = solve(&input)?;
+    println!("{}", output);
+
+    Ok(())
+}
+
+fn solve(input: &str) -> Result<String, Box<Error>> {
+    Ok("".into())
+}
+
+fn parse_sleep_range(pair: Pair<Rule>) -> Range<usize> {
+    let mut sleep_range = pair.into_inner();
+    let falls_asleep: usize = parse_minute(sleep_range.next().unwrap());
+    let wakes_up: usize = parse_minute(sleep_range.next().unwrap());
+    (falls_asleep..wakes_up)
+}
+
+fn parse_minute(pair: Pair<Rule>) -> usize {
+    pair.into_inner().next().unwrap().as_str().parse().unwrap()
+}
+
+#[derive(Debug)]
+struct Record {
+    guard_id: String,
+    sleep_ranges: Vec<Range<usize>>,
+}
+
+impl Record {
+    fn parse(s: &str) -> Result<Vec<Record>, Box<Error>> {
+        let mut records: Vec<_> = s.lines().collect();
+        records.sort();
+        let input = records.join("\n");
+
+        let mut parsed = RecordsParser::parse(Rule::records, &input)?;
+        let records: Vec<Record> = parsed
+            .next()
+            .unwrap()
+            .into_inner()
+            .flat_map(|record| match record.as_rule() {
+                Rule::record => Some(record.into()),
+                Rule::EOI => None,
+                _ => unreachable!(),
+            })
+            .collect();
+
+        Ok(records)
+    }
+}
+
+#[test]
+fn test_parsing() {
+    let input = r"
+[1518-11-01 00:00] Guard #10 begins shift
+[1518-11-01 00:05] falls asleep
+[1518-11-01 00:25] wakes up
+[1518-11-01 00:30] falls asleep
+[1518-11-01 00:55] wakes up
+[1518-11-01 23:58] Guard #99 begins shift
+[1518-11-02 00:40] falls asleep
+[1518-11-02 00:50] wakes up
+[1518-11-03 00:05] Guard #10 begins shift
+[1518-11-03 00:24] falls asleep
+[1518-11-03 00:29] wakes up
+[1518-11-04 00:02] Guard #99 begins shift
+[1518-11-04 00:36] falls asleep
+[1518-11-04 00:46] wakes up
+[1518-11-05 00:03] Guard #99 begins shift
+[1518-11-05 00:45] falls asleep
+[1518-11-05 00:55] wakes up
+    "
+    .trim();
+
+    let records = Record::parse(input).unwrap();
+    assert_eq!(records.len(), 5);
+    let record = &records[0];
+    assert_eq!(record.guard_id, "10");
+    assert_eq!(record.sleep_ranges, vec![(5..25), (30..55)]);
+}
+
+impl<'a> From<Pair<'a, Rule>> for Record {
+    fn from(pair: Pair<Rule>) -> Self {
+        let mut record = pair.into_inner();
+        let guard_id = record
+            .next()
+            .unwrap()
+            .into_inner()
+            .nth(1) // skip the minute
+            .unwrap()
+            .as_str()
+            .into();
+        let sleep_ranges: Vec<_> = record
+            .next()
+            .unwrap()
+            .into_inner()
+            .map(parse_sleep_range)
+            .collect();
+
+        Record {
+            guard_id,
+            sleep_ranges,
+        }
+    }
+}
+
+#[derive(Parser)]
+#[grammar = "day_04.pest"]
+#[allow(dead_code)]
+struct RecordsParser;
diff --git a/2018/rust/src/day_04.pest b/2018/rust/src/day_04.pest
new file mode 100644
index 0000000..d77d5c0
--- /dev/null
+++ b/2018/rust/src/day_04.pest
@@ -0,0 +1,21 @@
+records = { SOI ~ record* ~ EOI }
+record = { begins_shift ~ sleep_ranges }
+
+begins_shift = { date ~ " Guard #" ~ guard_id ~ " begins shift" ~ eol }
+guard_id = { digit+ }
+sleep_ranges = { sleep_range* }
+sleep_range = { falls_asleep ~ wakes_up }
+
+falls_asleep = { date ~ " falls asleep" ~ eol }
+wakes_up = { date ~ " wakes up" ~ eol }
+
+date = _{ "[" ~ year ~ "-" ~ month ~ "-" ~ day ~ " " ~ hour ~ ":" ~ minute ~ "]" }
+
+year = _{ digit{4} }
+month = _{ digit{2} }
+day = _{ digit{2} }
+hour = _{ digit{2} }
+minute = { digit{2} }
+
+digit = _{ '0'..'9' }
+eol = _{ "\n" | EOI }