2021 day8/rust: add solutions
This commit is contained in:
parent
6b9ff21a5a
commit
aa464884fe
7 changed files with 280 additions and 0 deletions
15
2021/day8/day8_rs/Cargo.toml
Normal file
15
2021/day8/day8_rs/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "day8_rs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3.5"
|
||||
|
||||
[[bench]]
|
||||
name = "unscramble"
|
||||
harness = false
|
13
2021/day8/day8_rs/src/lib.rs
Normal file
13
2021/day8/day8_rs/src/lib.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
#![warn(clippy::pedantic)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct LineResult {
|
||||
pub unique_digits: usize,
|
||||
pub number: usize,
|
||||
}
|
||||
|
||||
pub mod v1;
|
||||
pub mod v2;
|
||||
pub mod v3;
|
||||
pub mod v4;
|
23
2021/day8/day8_rs/src/main.rs
Normal file
23
2021/day8/day8_rs/src/main.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
#![warn(clippy::pedantic)]
|
||||
use day8_rs::{v3::unscramble, LineResult};
|
||||
use std::io::{stdin, BufRead};
|
||||
|
||||
fn main() {
|
||||
let result = stdin()
|
||||
.lock()
|
||||
.lines()
|
||||
.map(|s| unscramble(&s.unwrap()))
|
||||
.fold(
|
||||
LineResult {
|
||||
unique_digits: 0,
|
||||
number: 0,
|
||||
},
|
||||
|a, b| LineResult {
|
||||
unique_digits: a.unique_digits + b.unique_digits,
|
||||
number: a.number + b.number,
|
||||
},
|
||||
);
|
||||
|
||||
println!("{}", result.unique_digits);
|
||||
println!("{}", result.number);
|
||||
}
|
51
2021/day8/day8_rs/src/v1.rs
Normal file
51
2021/day8/day8_rs/src/v1.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::LineResult;
|
||||
|
||||
#[inline]
|
||||
fn lookup(n: usize) -> usize {
|
||||
match n {
|
||||
17 => 1,
|
||||
25 => 7,
|
||||
30 => 4,
|
||||
34 => 2,
|
||||
37 => 5,
|
||||
39 => 3,
|
||||
41 => 6,
|
||||
42 => 0,
|
||||
49 => 8,
|
||||
45 => 9,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn unscramble(line: &str) -> LineResult {
|
||||
let mut parts = line.split('|');
|
||||
let input = parts.next().unwrap();
|
||||
|
||||
let mut counts: HashMap<_, usize> = HashMap::new();
|
||||
for c in input.chars() {
|
||||
*counts.entry(c).or_default() += 1;
|
||||
}
|
||||
|
||||
let digits: Vec<_> = parts
|
||||
.next()
|
||||
.unwrap()
|
||||
.trim()
|
||||
.split(' ')
|
||||
.map(|s| s.chars().map(|c| counts[&c]).sum())
|
||||
.map(lookup)
|
||||
.collect();
|
||||
|
||||
LineResult {
|
||||
unique_digits: digits.iter().filter(|d| [1, 4, 7, 8].contains(d)).count(),
|
||||
number: digits
|
||||
.iter()
|
||||
.map(|&d| char::from_digit(d as u32, 10).unwrap())
|
||||
.collect::<String>()
|
||||
.parse()
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
52
2021/day8/day8_rs/src/v2.rs
Normal file
52
2021/day8/day8_rs/src/v2.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use crate::LineResult;
|
||||
|
||||
const FREQ_TABLE: [usize; 50] = {
|
||||
let mut tab = [0; 50];
|
||||
tab[17] = 1;
|
||||
tab[25] = 7;
|
||||
tab[30] = 4;
|
||||
tab[34] = 2;
|
||||
tab[37] = 5;
|
||||
tab[39] = 3;
|
||||
tab[41] = 6;
|
||||
tab[42] = 0;
|
||||
tab[45] = 9;
|
||||
tab[49] = 8;
|
||||
tab
|
||||
};
|
||||
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn unscramble(line: &str) -> LineResult {
|
||||
let mut parts = line.split('|');
|
||||
let input = parts.next().unwrap();
|
||||
|
||||
let mut counts = [0; 7];
|
||||
for c in input.bytes() {
|
||||
if (b'a'..=b'g').contains(&c) {
|
||||
counts[c as usize - b'a' as usize] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let digits: Vec<_> = parts
|
||||
.next()
|
||||
.unwrap()
|
||||
.trim()
|
||||
.split(' ')
|
||||
.map(|s| s.bytes().map(|c| counts[c as usize - b'a' as usize]).sum())
|
||||
.map(|n: usize| FREQ_TABLE[n])
|
||||
.collect();
|
||||
|
||||
LineResult {
|
||||
unique_digits: digits.iter().filter(|d| [1, 4, 7, 8].contains(d)).count(),
|
||||
number: digits
|
||||
.iter()
|
||||
.rev()
|
||||
.scan(1, |mul, &d| {
|
||||
let ret = Some(d * *mul);
|
||||
*mul *= 10;
|
||||
ret
|
||||
})
|
||||
.sum(),
|
||||
}
|
||||
}
|
63
2021/day8/day8_rs/src/v3.rs
Normal file
63
2021/day8/day8_rs/src/v3.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use crate::LineResult;
|
||||
|
||||
const FREQ_TABLE: [usize; 256] = {
|
||||
let mut tab = [0; 256];
|
||||
tab[17] = 1;
|
||||
tab[25] = 7;
|
||||
tab[30] = 4;
|
||||
tab[34] = 2;
|
||||
tab[37] = 5;
|
||||
tab[39] = 3;
|
||||
tab[41] = 6;
|
||||
tab[42] = 0;
|
||||
tab[45] = 9;
|
||||
tab[49] = 8;
|
||||
tab
|
||||
};
|
||||
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn unscramble(line: &str) -> LineResult {
|
||||
let mut bytes = line.bytes();
|
||||
|
||||
let mut counts = [0; 7];
|
||||
loop {
|
||||
match bytes.next().unwrap() {
|
||||
c @ b'a'..=b'g' => {
|
||||
counts[c as usize - b'a' as usize] += 1;
|
||||
}
|
||||
b'|' => break,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
bytes.next();
|
||||
|
||||
let mut freq = 0;
|
||||
let mut unique_digits = 0;
|
||||
let mut number = 0;
|
||||
loop {
|
||||
let c = bytes.next();
|
||||
match c {
|
||||
Some(b' ') | None => {
|
||||
let digit = FREQ_TABLE[freq & 0xff];
|
||||
if [1, 4, 7, 8].contains(&digit) {
|
||||
unique_digits += 1;
|
||||
}
|
||||
number = number * 10 + digit;
|
||||
freq = 0;
|
||||
if c.is_none() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Some(c) => {
|
||||
freq += counts[c as usize - b'a' as usize];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LineResult {
|
||||
unique_digits,
|
||||
number,
|
||||
}
|
||||
}
|
63
2021/day8/day8_rs/src/v4.rs
Normal file
63
2021/day8/day8_rs/src/v4.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use crate::LineResult;
|
||||
|
||||
const FREQ_TABLE: [usize; 256] = {
|
||||
let mut tab = [0; 256];
|
||||
tab[17] = 1;
|
||||
tab[25] = 7;
|
||||
tab[30] = 4;
|
||||
tab[34] = 2;
|
||||
tab[37] = 5;
|
||||
tab[39] = 3;
|
||||
tab[41] = 6;
|
||||
tab[42] = 0;
|
||||
tab[45] = 9;
|
||||
tab[49] = 8;
|
||||
tab
|
||||
};
|
||||
|
||||
#[must_use]
|
||||
#[inline]
|
||||
pub fn unscramble(line: &str) -> LineResult {
|
||||
let mut bytes = line.bytes();
|
||||
|
||||
let mut counts = [0; 7];
|
||||
loop {
|
||||
match bytes.next().unwrap() {
|
||||
c @ b'a'..=b'g' => {
|
||||
*unsafe { counts.get_unchecked_mut(c as usize - b'a' as usize) } += 1;
|
||||
}
|
||||
b'|' => break,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
bytes.next();
|
||||
|
||||
let mut freq = 0;
|
||||
let mut unique_digits = 0;
|
||||
let mut number = 0;
|
||||
loop {
|
||||
let c = bytes.next();
|
||||
match c {
|
||||
Some(b' ') | None => {
|
||||
let digit = FREQ_TABLE[freq & 0xff];
|
||||
if [1, 4, 7, 8].contains(&digit) {
|
||||
unique_digits += 1;
|
||||
}
|
||||
number = number * 10 + digit;
|
||||
freq = 0;
|
||||
if c.is_none() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Some(c) => {
|
||||
freq += unsafe { counts.get_unchecked(c as usize - b'a' as usize) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LineResult {
|
||||
unique_digits,
|
||||
number,
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue