day09 modules
This commit is contained in:
parent
decff21434
commit
d45577b935
3 changed files with 82 additions and 76 deletions
13
src/day09/errors.rs
Normal file
13
src/day09/errors.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Errors {
|
||||
#[error("invalid input")]
|
||||
InvalidInput,
|
||||
}
|
||||
|
||||
impl From<std::num::ParseIntError> for Errors {
|
||||
fn from(_: std::num::ParseIntError) -> Self {
|
||||
Errors::InvalidInput
|
||||
}
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
use anyhow::Result;
|
||||
use std::convert::TryFrom;
|
||||
use thiserror::Error;
|
||||
|
||||
pub mod xmas_decoder;
|
||||
pub mod errors;
|
||||
|
||||
static INPUT: &str = include_str!("../../input09");
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let decoder = XMASDecoder::try_from(INPUT)?;
|
||||
let decoder = xmas_decoder::XMASDecoder::try_from(INPUT)?;
|
||||
|
||||
let missing = decoder.decode().expect("did not find a solution");
|
||||
println!("missing: {}", missing);
|
||||
|
@ -19,77 +21,3 @@ fn main() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub struct XMASDecoder {
|
||||
input: Vec<i64>,
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for XMASDecoder {
|
||||
type Error = Errors;
|
||||
|
||||
fn try_from(input: &str) -> Result<Self, Self::Error> {
|
||||
let input = input
|
||||
.split_ascii_whitespace()
|
||||
.map(|line| line.trim().parse::<i64>())
|
||||
.collect::<std::result::Result<Vec<i64>, _>>()?;
|
||||
Ok(Self { input })
|
||||
}
|
||||
}
|
||||
|
||||
impl XMASDecoder {
|
||||
pub fn find_continues(&self, target: i64) -> Option<&[i64]> {
|
||||
for offset in 0..self.input.len() {
|
||||
let slice = &self.input[offset..self.input.len()];
|
||||
if let Some(found) = Self::find_sum_slice(slice, target) {
|
||||
return Some(found);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn find_sum_slice(slice: &[i64], target: i64) -> Option<&[i64]> {
|
||||
let mut offset = 0;
|
||||
let mut sum = 0;
|
||||
for i in slice {
|
||||
offset += 1;
|
||||
sum += *i;
|
||||
if sum == target {
|
||||
return Some(&slice[0..offset]);
|
||||
} else if sum > target {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn decode(&self) -> Option<i64> {
|
||||
self.input
|
||||
.windows(26)
|
||||
.into_iter()
|
||||
.filter_map(Self::validate_slice)
|
||||
.next()
|
||||
}
|
||||
|
||||
fn validate_slice(window: &[i64]) -> Option<i64> {
|
||||
let (target, slice) = window.split_last().unwrap();
|
||||
for (offset, a) in slice.iter().enumerate() {
|
||||
for b in slice[offset + 1..slice.len()].iter() {
|
||||
if a + b == *target {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(*target)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Errors {
|
||||
#[error("invalid input")]
|
||||
InvalidInput,
|
||||
}
|
||||
|
||||
impl From<std::num::ParseIntError> for Errors {
|
||||
fn from(_: std::num::ParseIntError) -> Self {
|
||||
Errors::InvalidInput
|
||||
}
|
||||
}
|
||||
|
|
65
src/day09/xmas_decoder.rs
Normal file
65
src/day09/xmas_decoder.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use std::convert::TryFrom;
|
||||
use super::errors;
|
||||
|
||||
pub struct XMASDecoder {
|
||||
input: Vec<i64>,
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for XMASDecoder {
|
||||
type Error = errors::Errors;
|
||||
|
||||
fn try_from(input: &str) -> Result<Self, Self::Error> {
|
||||
let input = input
|
||||
.split_ascii_whitespace()
|
||||
.map(|line| line.trim().parse::<i64>())
|
||||
.collect::<std::result::Result<Vec<i64>, _>>()?;
|
||||
Ok(Self { input })
|
||||
}
|
||||
}
|
||||
|
||||
impl XMASDecoder {
|
||||
pub fn find_continues(&self, target: i64) -> Option<&[i64]> {
|
||||
for offset in 0..self.input.len() {
|
||||
let slice = &self.input[offset..self.input.len()];
|
||||
if let Some(found) = Self::find_sum_slice(slice, target) {
|
||||
return Some(found);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn find_sum_slice(slice: &[i64], target: i64) -> Option<&[i64]> {
|
||||
let mut offset = 0;
|
||||
let mut sum = 0;
|
||||
for i in slice {
|
||||
offset += 1;
|
||||
sum += *i;
|
||||
if sum == target {
|
||||
return Some(&slice[0..offset]);
|
||||
} else if sum > target {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn decode(&self) -> Option<i64> {
|
||||
self.input
|
||||
.windows(26)
|
||||
.into_iter()
|
||||
.filter_map(Self::validate_slice)
|
||||
.next()
|
||||
}
|
||||
|
||||
fn validate_slice(window: &[i64]) -> Option<i64> {
|
||||
let (target, slice) = window.split_last().unwrap();
|
||||
for (offset, a) in slice.iter().enumerate() {
|
||||
for b in slice[offset + 1..slice.len()].iter() {
|
||||
if a + b == *target {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(*target)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue