day16, part 1
This commit is contained in:
147
src/fft.rs
Normal file
147
src/fft.rs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
|
||||||
|
const BASE_SEQUENCE: [i64; 4] = [0, 1, 0, -1];
|
||||||
|
|
||||||
|
struct SequenceIterator {
|
||||||
|
i: usize,
|
||||||
|
j: usize,
|
||||||
|
jmax: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SequenceIterator {
|
||||||
|
fn new(digit: usize) -> SequenceIterator {
|
||||||
|
SequenceIterator {
|
||||||
|
i: 0,
|
||||||
|
j: 0,
|
||||||
|
jmax: digit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for SequenceIterator {
|
||||||
|
type Item = i64;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<i64> {
|
||||||
|
// advance first, because we wanted to skip the first digit.
|
||||||
|
self.j += 1;
|
||||||
|
if self.j == self.jmax {
|
||||||
|
self.j = 0;
|
||||||
|
self.i += 1;
|
||||||
|
if self.i == BASE_SEQUENCE.len() {
|
||||||
|
self.i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(BASE_SEQUENCE[self.i] as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sequence_check() {
|
||||||
|
let seq1 = SequenceIterator::new(1);
|
||||||
|
assert_eq!(vec![1, 0, -1, 0, 1, 0, -1, 0], seq1.take(8).collect::<Vec<i64>>());
|
||||||
|
let seq2 = SequenceIterator::new(2);
|
||||||
|
assert_eq!(vec![0, 1, 1, 0, 0, -1, -1, 0], seq2.take(8).collect::<Vec<i64>>());
|
||||||
|
let seq4 = SequenceIterator::new(4);
|
||||||
|
assert_eq!(vec![0, 0, 0, 1, 1, 1, 1, 0], seq4.take(8).collect::<Vec<i64>>());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NumStr {
|
||||||
|
vals: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NumStr {
|
||||||
|
fn new(s: &str) -> NumStr {
|
||||||
|
let mut vals = Vec::with_capacity(s.len());
|
||||||
|
|
||||||
|
for c in s.chars() {
|
||||||
|
vals.push(c.to_digit(10).expect("Found non-digit?!") as u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
NumStr{ vals }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_round(&mut self) {
|
||||||
|
let orig = self.vals.clone();
|
||||||
|
let mut i = 1;
|
||||||
|
|
||||||
|
while i <= self.vals.len() {
|
||||||
|
let mulseq = SequenceIterator::new(i);
|
||||||
|
let mut total = 0;
|
||||||
|
|
||||||
|
for (digit, mul) in orig.iter().zip(mulseq) {
|
||||||
|
total += (*digit as i64) * mul;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vals[i-1] = (total.abs() % 10) as u8;
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_rounds(&mut self, num: usize) {
|
||||||
|
for _ in 0..num {
|
||||||
|
self.apply_round();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_string(&self, chars: usize) -> String {
|
||||||
|
let mut res = String::new();
|
||||||
|
|
||||||
|
for d in self.vals.iter().take(chars) {
|
||||||
|
let c = match d {
|
||||||
|
0 => '0',
|
||||||
|
1 => '1',
|
||||||
|
2 => '2',
|
||||||
|
3 => '3',
|
||||||
|
4 => '4',
|
||||||
|
5 => '5',
|
||||||
|
6 => '6',
|
||||||
|
7 => '7',
|
||||||
|
8 => '8',
|
||||||
|
9 => '9',
|
||||||
|
_ => panic!("digit not a digit"),
|
||||||
|
};
|
||||||
|
res.push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic_apply() {
|
||||||
|
let mut base = NumStr::new("12345678");
|
||||||
|
base.apply_round();
|
||||||
|
assert_eq!("48226158", &base.to_string(8));
|
||||||
|
base.apply_round();
|
||||||
|
assert_eq!("34040438", &base.to_string(8));
|
||||||
|
base.apply_round();
|
||||||
|
assert_eq!("03415518", &base.to_string(8));
|
||||||
|
base.apply_round();
|
||||||
|
assert_eq!("01029498", &base.to_string(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn examples() {
|
||||||
|
let mut example1 = NumStr::new("80871224585914546619083218645595");
|
||||||
|
example1.apply_rounds(100);
|
||||||
|
assert_eq!("24176176", &example1.to_string(8));
|
||||||
|
let mut example2 = NumStr::new("19617804207202209144916044189917");
|
||||||
|
example2.apply_rounds(100);
|
||||||
|
assert_eq!("73745418", &example2.to_string(8));
|
||||||
|
let mut example3 = NumStr::new("69317163492948606335995924319873");
|
||||||
|
example3.apply_rounds(100);
|
||||||
|
assert_eq!("52432133", &example3.to_string(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn day16() {
|
||||||
|
let day16_contents = fs::read("inputs/day16").expect("Couldn't open day14 problem");
|
||||||
|
let day16_str = str::from_utf8(&day16_contents).expect("Couldn't decode day14 problem");
|
||||||
|
let mut day16 = NumStr::new(&day16_str.trim());
|
||||||
|
day16.apply_rounds(100);
|
||||||
|
assert_eq!("63794407", &day16.to_string(8));
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ mod arcade;
|
|||||||
mod args;
|
mod args;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod chemistry;
|
mod chemistry;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod fft;
|
||||||
mod fuel;
|
mod fuel;
|
||||||
mod image;
|
mod image;
|
||||||
mod machine;
|
mod machine;
|
||||||
|
|||||||
Reference in New Issue
Block a user