2021 day8/rust: add solutions

This commit is contained in:
Xiretza 2021-12-08 20:15:42 +01:00
parent 6b9ff21a5a
commit aa464884fe
7 changed files with 280 additions and 0 deletions

View 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

View 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;

View 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);
}

View 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(),
}
}

View 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(),
}
}

View 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,
}
}

View 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,
}
}