2015/08-10, 2015/12-13, started on 2015/14

This commit is contained in:
2017-12-05 08:01:57 +01:00
parent b6a89a7ab6
commit 6fc08571bf
20 changed files with 1072 additions and 156 deletions

397
2015/12/src/main.rs Normal file
View File

@@ -0,0 +1,397 @@
use std::io::{self, Read};
use std::iter::Iterator;
use std::borrow::Cow;
#[derive(Clone, PartialEq, Debug)]
enum Token<'a> {
ObjectStart,
ObjectEnd,
ArrayStart,
ArrayEnd,
Number(i64),
String(Cow<'a, str>),
}
#[derive(Clone, PartialEq, Debug)]
enum State {
Unknown,
InObject,
InArray,
Number(usize),
String(usize),
}
struct Parser<'a> {
state: Vec<State>,
input: &'a str,
index: usize,
}
impl<'a> Parser<'a> {
fn new(input: &'a str) -> Self {
Parser {
state: Vec::new(),
input: input,
index: 0,
}
}
}
impl<'a> Iterator for Parser<'a> {
type Item = Token<'a>;
fn next(&mut self) -> Option<Token<'a>> {
if self.index >= self.input.len() {
return None;
}
let mut iter = self.input.chars().skip(self.index);
let mut next = iter.next();
while let Some(ch) = next {
let state = self.state.last().unwrap_or(&State::Unknown).clone();
match (state, ch) {
// Unknown.
(State::Unknown, '-') => {
self.state.push(State::Number(self.index));
self.index += 1;
next = iter.next();
}
(State::Unknown, '0'...'9') => {
self.state.push(State::Number(self.index));
self.index += 1;
next = iter.next();
}
(State::Unknown, '"') => {
self.state.push(State::String(self.index + 1));
self.index += 1;
next = iter.next();
}
(State::Unknown, '{') => {
self.state.push(State::InObject);
self.index += 1;
return Some(Token::ObjectStart);
}
(State::Unknown, '[') => {
self.state.push(State::InArray);
self.index += 1;
return Some(Token::ArrayStart);
}
// Number.
(State::Number(_), '0'...'9') => {
self.index += 1;
next = iter.next();
}
(State::Number(start), _) => {
self.state.pop();
return Some(Token::Number(
self.input[start..self.index].parse::<i64>().unwrap(),
));
}
// String.
(State::String(start), '"') => {
self.state.pop();
self.index += 1;
return Some(Token::String(self.input[start..self.index - 1].into()));
}
(State::String(_), _) => {
self.index += 1;
next = iter.next();
}
// Object.
(State::InObject, '"') => {
self.state.push(State::String(self.index + 1));
self.index += 1;
next = iter.next();
}
(State::InObject, '-') => {
self.state.push(State::Number(self.index));
self.index += 1;
next = iter.next();
}
(State::InObject, '0'...'9') => {
self.state.push(State::Number(self.index));
self.index += 1;
next = iter.next();
}
(State::InObject, '{') => {
self.state.push(State::InObject);
self.index += 1;
return Some(Token::ObjectStart);
}
(State::InObject, '[') => {
self.state.push(State::InArray);
self.index += 1;
return Some(Token::ArrayStart);
}
(State::InObject, '}') => {
self.state.pop();
self.index += 1;
return Some(Token::ObjectEnd);
}
// Array.
(State::InArray, '"') => {
self.state.push(State::String(self.index + 1));
self.index += 1;
next = iter.next();
}
(State::InArray, '-') => {
self.state.push(State::Number(self.index));
self.index += 1;
next = iter.next();
}
(State::InArray, '0'...'9') => {
self.state.push(State::Number(self.index));
self.index += 1;
next = iter.next();
}
(State::InArray, '{') => {
self.state.push(State::InObject);
self.index += 1;
return Some(Token::ObjectStart);
}
(State::InArray, '[') => {
self.state.push(State::InArray);
self.index += 1;
return Some(Token::ArrayStart);
}
(State::InArray, ']') => {
self.state.pop();
self.index += 1;
return Some(Token::ArrayEnd);
}
// Everything else.
(_, _) => {
self.index += 1;
next = iter.next();
}
}
}
None
}
}
#[derive(Debug)]
struct Stack {
sum: i64,
in_object: bool,
expect_key: bool,
discard: bool,
}
fn main() {
let mut input = String::new();
io::stdin()
.read_to_string(&mut input)
.expect("faild to read input");
let mut total = 0;
let mut stack = Vec::new();
stack.push(Stack {
sum: 0,
in_object: false,
expect_key: false,
discard: false,
});
for line in input.lines() {
for value in Parser::new(line) {
match value {
Token::String(ref string) => {
let this = stack.last_mut().unwrap();
if this.in_object {
if this.expect_key {
this.expect_key = false;
} else if string == "red" {
this.expect_key = true;
this.discard = true;
}
}
}
Token::Number(number) => {
let this = stack.last_mut().unwrap();
if this.in_object {
this.expect_key = true;
}
this.sum += number;
}
Token::ObjectStart => {
stack.push(Stack {
sum: 0,
in_object: true,
expect_key: true,
discard: false,
});
}
Token::ObjectEnd => {
let this = stack.pop().unwrap();
if !this.discard {
let entry = stack.last_mut().unwrap();
entry.sum += this.sum;
}
}
Token::ArrayStart => {
stack.push(Stack {
sum: 0,
in_object: false,
expect_key: false,
discard: false,
});
}
Token::ArrayEnd => {
let that = stack.pop().unwrap();
let this = stack.last_mut().unwrap();
this.sum += that.sum;
if this.in_object {
this.expect_key = true;
}
}
}
}
let this = stack.last_mut().unwrap();
total += this.sum;
}
println!("total={}", total);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example_01() {
let mut parser = Parser::new(r#"[1,2,3]"#);
assert_eq!(parser.next(), Some(Token::ArrayStart));
assert_eq!(parser.next(), Some(Token::Number(1)));
assert_eq!(parser.next(), Some(Token::Number(2)));
assert_eq!(parser.next(), Some(Token::Number(3)));
assert_eq!(parser.next(), Some(Token::ArrayEnd));
assert_eq!(parser.next(), None);
}
#[test]
fn example_02() {
let mut parser = Parser::new(r#"{"a":2,"b":4}"#);
assert_eq!(parser.next(), Some(Token::ObjectStart));
assert_eq!(parser.next(), Some(Token::String("a".into())));
assert_eq!(parser.next(), Some(Token::Number(2)));
assert_eq!(parser.next(), Some(Token::String("b".into())));
assert_eq!(parser.next(), Some(Token::Number(4)));
assert_eq!(parser.next(), Some(Token::ObjectEnd));
assert_eq!(parser.next(), None);
}
#[test]
fn example_03() {
let mut parser = Parser::new(r#"[[[3]]]"#);
assert_eq!(parser.next(), Some(Token::ArrayStart));
assert_eq!(parser.next(), Some(Token::ArrayStart));
assert_eq!(parser.next(), Some(Token::ArrayStart));
assert_eq!(parser.next(), Some(Token::Number(3)));
assert_eq!(parser.next(), Some(Token::ArrayEnd));
assert_eq!(parser.next(), Some(Token::ArrayEnd));
assert_eq!(parser.next(), Some(Token::ArrayEnd));
assert_eq!(parser.next(), None);
}
#[test]
fn example_04() {
let mut parser = Parser::new(r#"{"a":{"b":4},"c":-1}"#);
assert_eq!(parser.next(), Some(Token::ObjectStart));
assert_eq!(parser.next(), Some(Token::String("a".into())));
assert_eq!(parser.next(), Some(Token::ObjectStart));
assert_eq!(parser.next(), Some(Token::String("b".into())));
assert_eq!(parser.next(), Some(Token::Number(4)));
assert_eq!(parser.next(), Some(Token::ObjectEnd));
assert_eq!(parser.next(), Some(Token::String("c".into())));
assert_eq!(parser.next(), Some(Token::Number(-1)));
assert_eq!(parser.next(), Some(Token::ObjectEnd));
assert_eq!(parser.next(), None);
}
#[test]
fn example_05() {
let mut parser = Parser::new(r#"{"a":[-1,1]}"#);
assert_eq!(parser.next(), Some(Token::ObjectStart));
assert_eq!(parser.next(), Some(Token::String("a".into())));
assert_eq!(parser.next(), Some(Token::ArrayStart));
assert_eq!(parser.next(), Some(Token::Number(-1)));
assert_eq!(parser.next(), Some(Token::Number(1)));
assert_eq!(parser.next(), Some(Token::ArrayEnd));
assert_eq!(parser.next(), Some(Token::ObjectEnd));
assert_eq!(parser.next(), None);
}
#[test]
fn example_06() {
let mut parser = Parser::new(r#"[-1,{"a":1}]"#);
assert_eq!(parser.next(), Some(Token::ArrayStart));
assert_eq!(parser.next(), Some(Token::Number(-1)));
assert_eq!(parser.next(), Some(Token::ObjectStart));
assert_eq!(parser.next(), Some(Token::String("a".into())));
assert_eq!(parser.next(), Some(Token::Number(1)));
assert_eq!(parser.next(), Some(Token::ObjectEnd));
assert_eq!(parser.next(), Some(Token::ArrayEnd));
assert_eq!(parser.next(), None);
}
}