Skip to content

Commit

Permalink
Added solution for 2018-08
Browse files Browse the repository at this point in the history
  • Loading branch information
opcode0x90 committed Dec 25, 2018
1 parent f613483 commit b075dda
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 0 deletions.
24 changes: 24 additions & 0 deletions 2018-08/opcode0x90/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "opcode0x90"
version = "0.1.0"
authors = ["opcode0x90 <[email protected]>"]
edition = "2018"

[lib]
name = "aoc"
path = "src/lib.rs"
bench = false

[[bin]]
name = "aoc"
path = "src/main.rs"
bench = false

[[bench]]
name = "bench"
harness = false

[dependencies]

[dev-dependencies]
criterion = "0.2"
35 changes: 35 additions & 0 deletions 2018-08/opcode0x90/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
2018-08
=======

Solution for [Advent of Code](https://adventofcode.com/2018) day 8.

Compiling and Running
---------------------

1. Install [Rust](https://www.rust-lang.org/en-US/install.html).
2. `cargo run --release`

Result
------

```sh
$ cargo run --release
part1: 46781
part2: 21405
```

Benchmark
---------

```
$ cargo bench -- --save-baseline 1
part1 time: [19.429 us 19.913 us 20.471 us]
Found 6 outliers among 100 measurements (6.00%)
2 (2.00%) high mild
4 (4.00%) high severe
part2 time: [5.1786 us 5.2295 us 5.2837 us]
Found 3 outliers among 100 measurements (3.00%)
2 (2.00%) high mild
1 (1.00%) high severe
```
23 changes: 23 additions & 0 deletions 2018-08/opcode0x90/benches/bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::fs::File;

use aoc::*;
use criterion::{criterion_group, criterion_main, Criterion};

fn bench_part1(c: &mut Criterion) {
c.bench_function("part1", |b| {
let f = File::open("input.txt").expect("input.txt not found!");
let input = get_input(f).unwrap();
b.iter(|| part1(&input))
});
}

fn bench_part2(c: &mut Criterion) {
c.bench_function("part2", |b| {
let f = File::open("input.txt").expect("input.txt not found!");
let input = get_input(f).unwrap();
b.iter(|| part2(&input))
});
}

criterion_group!(benches, bench_part1, bench_part2);
criterion_main!(benches);
1 change: 1 addition & 0 deletions 2018-08/opcode0x90/input.txt

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions 2018-08/opcode0x90/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use std::error::Error;
use std::io::{BufRead, BufReader, Read};

#[derive(Debug, Default, Hash, Eq, PartialEq)]
pub struct License {
children: Vec<License>,
metadata: Vec<usize>,
}

pub fn part1(input: &License) -> usize {
// recursively fold the tree
fn checksum(license: &License) -> usize {
let a = license.metadata.iter().sum::<usize>();
let b = license.children.iter().map(checksum).sum::<usize>();
a + b
}
checksum(input)
}

pub fn part2(input: &License) -> usize {
// recursively fold the tree
fn checksum(license: &License) -> usize {
// do we have children?
if license.children.is_empty() {
// value is the sum of its metadata entries
license.metadata.iter().sum::<usize>()
} else {
// value is the sum of the values of the child nodes referenced
// by the metadata entries
license
.metadata
.iter()
.map(|&i| -> usize {
// our vector is zero-indexed
let i = i - 1;

// if a referenced child node does not exist, skip it
if let Some(child) = license.children.get(i) {
// compute the value of child node
checksum(child)
} else {
0
}
})
.sum::<usize>()
}
}
checksum(input)
}

pub fn get_input(f: impl Read) -> Result<License, Box<dyn Error>> {
// parse input from input.txt
let input = BufReader::new(f)
.split(b' ')
.map(|line| -> Result<usize, Box<dyn Error>> {
// collect the chars into UTF-8, then parse into integer
Ok(String::from_utf8(line?)?.trim().parse::<usize>()?)
})
.collect::<Result<Vec<_>, _>>()?;

fn extract_license(it: &mut impl Iterator<Item = usize>) -> License {
let mut license = License::default();

if let (Some(n_children), Some(n_metadata)) = (it.next(), it.next()) {
// parse all child nodes
for _ in 0..n_children {
// recursively extract the child nodes
license.children.push(extract_license(it));
}
// extract the rest of metadata
license.metadata.extend(it.take(n_metadata));
}
license
}

Ok(extract_license(&mut input.into_iter()))
}

#[cfg(test)]
mod tests {
use super::*;

const DATA: &str = r#"2 3 0 3 10 11 12 1 1 0 1 99 2 1 1 2"#;

#[test]
fn test_part1() {
let input = get_input(DATA.as_bytes()).expect("unable to parse input");
assert_eq!(138, part1(&input));
}

#[test]
fn test_part2() {
let input = get_input(DATA.as_bytes()).expect("unable to parse input");
assert_eq!(66, part2(&input));
}
}
17 changes: 17 additions & 0 deletions 2018-08/opcode0x90/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use std::fs::File;

use aoc::*;

fn main() -> Result<(), Box<dyn std::error::Error>> {
// read data from input.txt
let f = File::open("input.txt").expect("input.txt not found!");
let input = get_input(f)?;

let part1 = part1(&input);
println!("part1: {}", part1);

let part2 = part2(&input);
println!("part2: {}", part2);

Ok(())
}

0 comments on commit b075dda

Please sign in to comment.