2019 cleanup: Introduced proper Error types for most days up until day 14
This commit is contained in:
parent
9c8f23161a
commit
2851f7c80d
11 changed files with 150 additions and 85 deletions
|
@ -1,16 +1,22 @@
|
|||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let first = input.lines().map(|line| line.parse::<usize>().unwrap() / 3 -2).sum();
|
||||
use std::num::ParseIntError;
|
||||
|
||||
pub fn run(input: &str) -> Result<(usize, usize), ParseIntError> {
|
||||
let first = input.lines().map(|line| line.parse::<usize>().map(|i| i/3-2)).sum::<Result<usize, _>>()?;
|
||||
let second = input.lines().map(|line| {
|
||||
let weight = line.parse::<usize>().unwrap();
|
||||
let parsed = line.parse::<usize>();
|
||||
if let Ok(weight) = parsed {
|
||||
let mut total = (weight/3).saturating_sub(2);
|
||||
let mut next = (total/3).saturating_sub(2);
|
||||
while next > 0 {
|
||||
total += next;
|
||||
next = (next/3).saturating_sub(2);
|
||||
}
|
||||
total
|
||||
}).sum::<usize>();
|
||||
(first, second)
|
||||
Ok(total)
|
||||
} else {
|
||||
parsed
|
||||
}
|
||||
}).sum::<Result<usize, _>>()?;
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -25,12 +31,12 @@ mod tests {
|
|||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (34241, 51316));
|
||||
assert_eq!(run(&sample_input), Ok((34241, 51316)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (3363033, 5041680));
|
||||
assert_eq!(run(&challenge_input), Ok((3363033, 5041680)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use std::num::ParseIntError;
|
||||
|
||||
use intcode_processor::intcode_processor::Cpu;
|
||||
|
||||
pub fn run(input: &str) -> (isize, isize) {
|
||||
let memory = input.split(',').map(|s| s.parse::<isize>().unwrap()).collect();
|
||||
let cpu = Cpu::with_memory(memory);
|
||||
pub fn run(input: &str) -> Result<(isize, isize), ParseIntError> {
|
||||
let cpu = Cpu::try_with_memory_from_str(input)?;
|
||||
let mut cpu_1 = cpu.clone();
|
||||
cpu_1.set(1, 12);
|
||||
cpu_1.set(2, 2);
|
||||
|
@ -21,7 +22,7 @@ pub fn run(input: &str) -> (isize, isize) {
|
|||
}
|
||||
}
|
||||
}
|
||||
(first, second)
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -36,12 +37,12 @@ mod tests {
|
|||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (3500, 213));
|
||||
assert_eq!(run(&sample_input), Ok((3500, 213)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (3760627, 7195));
|
||||
assert_eq!(run(&challenge_input), Ok((3760627, 7195)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let range: Vec<_> = input.split('-').map(|n| n.parse::<usize>().unwrap()).collect();
|
||||
use std::num::ParseIntError;
|
||||
|
||||
pub fn run(input: &str) -> Result<(usize, usize), ParseIntError> {
|
||||
let range: Vec<_> = input.split('-').map(|n| n.parse::<usize>()).collect::<Result<Vec<_>, _>>()?;
|
||||
let valid_1: Vec<_> = (range[0]..=range[1]).filter(is_valid_1).collect();
|
||||
let first = valid_1.len();
|
||||
let second = valid_1.into_iter().filter(is_valid_2).count();
|
||||
(first, second)
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
fn is_valid_1(password: &usize) -> bool {
|
||||
|
@ -55,12 +57,12 @@ mod tests {
|
|||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (36, 14));
|
||||
assert_eq!(run(&sample_input), Ok((36, 14)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (921, 603));
|
||||
assert_eq!(run(&challenge_input), Ok((921, 603)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use std::num::ParseIntError;
|
||||
|
||||
use intcode_processor::intcode_processor::{Cpu, OutputState};
|
||||
|
||||
pub fn run(input: &str) -> (isize, isize) {
|
||||
let mut cpu = Cpu::with_memory(input.split(',').map(|s| s.parse::<isize>().unwrap()).collect());
|
||||
pub fn run(input: &str) -> Result<(isize, isize), ParseIntError> {
|
||||
let mut cpu = Cpu::try_with_memory_from_str(input)?;
|
||||
let mut cpu_2 = cpu.clone();
|
||||
|
||||
cpu.set_input(1);
|
||||
|
@ -9,7 +11,7 @@ pub fn run(input: &str) -> (isize, isize) {
|
|||
cpu_2.set_input(5);
|
||||
let second = run_diagnostics(&mut cpu_2);
|
||||
|
||||
(first, second)
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
fn run_diagnostics(cpu: &mut Cpu) -> isize {
|
||||
|
@ -36,6 +38,6 @@ mod tests {
|
|||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (9025675, 11981754));
|
||||
assert_eq!(run(&challenge_input), Ok((9025675, 11981754)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,28 +6,31 @@ struct Orbit {
|
|||
center_id: usize,
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let graph: Vec<_> = graph_from(input);
|
||||
pub fn run(input: &str) -> Result<(usize, usize), String> {
|
||||
let graph: Vec<_> = graph_from(input)?;
|
||||
let first = count_direct_and_indirect_orbits(&graph);
|
||||
let common_orbit = get_common_center(&graph, 1, 2);
|
||||
|
||||
let second = distance(&graph, common_orbit, 1) + distance(&graph, common_orbit, 2) - 2;
|
||||
(first, second)
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
fn graph_from(map: &str) -> Vec<Orbit> {
|
||||
fn graph_from(map: &str) -> Result<Vec<Orbit>, String> {
|
||||
let mut bodies = HashMap::from([("COM", 0), ("YOU", 1), ("SAN", 2)]);
|
||||
let mut graph: Vec<Orbit> = Vec::new();
|
||||
for line in map.lines() {
|
||||
let (center, trabant) = line.split_once(')').unwrap();
|
||||
if let Some((center, trabant)) = line.split_once(')') {
|
||||
let mut bodies_len = bodies.len();
|
||||
let center_id = *bodies.entry(center).or_insert(bodies_len);
|
||||
bodies_len = bodies.len();
|
||||
let trabant_id = *bodies.entry(trabant).or_insert(bodies_len);
|
||||
graph.push(Orbit { center_id, trabant_id } );
|
||||
} else {
|
||||
return Err(format!("Malformed input: '{line}' doesn't contain a ')'."));
|
||||
}
|
||||
}
|
||||
graph.sort();
|
||||
graph
|
||||
Ok(graph)
|
||||
}
|
||||
|
||||
fn count_direct_and_indirect_orbits(graph: &[Orbit]) -> usize {
|
||||
|
@ -94,12 +97,12 @@ mod tests {
|
|||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (54, 4));
|
||||
assert_eq!(run(&sample_input), Ok((54, 4)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (417916, 523));
|
||||
assert_eq!(run(&challenge_input), Ok((417916, 523)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use std::{sync::{mpsc, Arc}, thread, collections::VecDeque};
|
||||
use std::{sync::{mpsc, Arc}, thread, collections::VecDeque, num::ParseIntError};
|
||||
|
||||
use intcode_processor::intcode_processor::{Cpu, OutputState};
|
||||
|
||||
pub fn run(input: &str) -> (isize, isize) {
|
||||
let template = Cpu::try_with_memory_from_str(input).unwrap();
|
||||
pub fn run(input: &str) -> Result<(isize, isize), ParseIntError> {
|
||||
let template = Cpu::try_with_memory_from_str(input)?;
|
||||
let mut first = 0;
|
||||
for perm in get_permutations(&(0..5).collect()) {
|
||||
let mut output = 0;
|
||||
|
@ -82,7 +82,7 @@ pub fn run(input: &str) -> (isize, isize) {
|
|||
}
|
||||
second = second.max(*output.lock().unwrap());
|
||||
}
|
||||
(first, second)
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
fn get_permutations(numbers: &Vec<isize>) -> Vec<Vec<isize>> {
|
||||
|
@ -116,19 +116,19 @@ mod tests {
|
|||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
// The second part of the output is not verified, but that's what my solution produces.
|
||||
assert_eq!(run(&sample_input), (65210, 76543));
|
||||
assert_eq!(run(&sample_input), Ok((65210, 76543)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample_2() {
|
||||
let sample_input = read_file("tests/sample_input_2");
|
||||
// The first part of the output is not verified, but that's what my solution produces.
|
||||
assert_eq!(run(&sample_input), (0, 18216));
|
||||
assert_eq!(run(&sample_input), Ok((0, 18216)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (46248, 54163586));
|
||||
assert_eq!(run(&challenge_input), Ok((46248, 54163586)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use std::num::ParseIntError;
|
||||
|
||||
use intcode_processor::intcode_processor::{Cpu, OutputState};
|
||||
|
||||
pub fn run(input: &str) -> (isize, isize) {
|
||||
let mut cpu = Cpu::try_with_memory_from_str(input).unwrap();
|
||||
pub fn run(input: &str) -> Result<(isize, isize), ParseIntError> {
|
||||
let mut cpu = Cpu::try_with_memory_from_str(input)?;
|
||||
let mut cpu_2 = cpu.clone();
|
||||
cpu.set_input(1);
|
||||
let first = match cpu.run() {
|
||||
|
@ -13,7 +15,7 @@ pub fn run(input: &str) -> (isize, isize) {
|
|||
OutputState::DiagnosticCode(d) => d,
|
||||
e => panic!("Unexpected return code: {e:?}"),
|
||||
};
|
||||
(first, second)
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -28,6 +30,6 @@ mod tests {
|
|||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (2316632620, 78869));
|
||||
assert_eq!(run(&challenge_input), Ok((2316632620, 78869)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::HashMap, isize};
|
||||
use std::{collections::HashMap, isize, num::ParseIntError};
|
||||
use intcode_processor::intcode_processor::{Cpu, OutputState};
|
||||
|
||||
enum Direction { Up, Left, Down, Right }
|
||||
|
@ -39,8 +39,8 @@ impl Direction {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, String) {
|
||||
let mut cpu_1 = Cpu::try_with_memory_from_str(input).unwrap();
|
||||
pub fn run(input: &str) -> Result<(usize, String), ParseIntError> {
|
||||
let mut cpu_1 = Cpu::try_with_memory_from_str(input)?;
|
||||
let mut cpu_2 = cpu_1.clone();
|
||||
let mut panels_1 = HashMap::new();
|
||||
let mut panels_2 = HashMap::from([((0, 0), 1)]);
|
||||
|
@ -48,7 +48,7 @@ pub fn run(input: &str) -> (usize, String) {
|
|||
paint(&mut cpu_2, &mut panels_2);
|
||||
let first = panels_1.len();
|
||||
let second = print(&panels_2);
|
||||
(first, second)
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
fn paint(cpu: &mut Cpu, panels: &mut HashMap<(isize, isize), isize>) {
|
||||
|
@ -100,6 +100,6 @@ mod tests {
|
|||
# # # # # # # # # # # # #
|
||||
#### #### #### ### # # ## # # # #
|
||||
"#;
|
||||
assert_eq!(run(&challenge_input), (2539, expected[1..].to_string()));
|
||||
assert_eq!(run(&challenge_input), Ok((2539, expected[1..].to_string())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use core::fmt;
|
||||
use std::{iter::Sum, ops::AddAssign, num::ParseIntError};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
|
@ -37,6 +38,27 @@ impl Coordinate {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ParseMoonError {
|
||||
ParseIntError(std::num::ParseIntError),
|
||||
InvalidCoordinates(usize),
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for ParseMoonError {
|
||||
fn from(value: ParseIntError) -> Self {
|
||||
Self::ParseIntError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseMoonError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::ParseIntError(v) => write!(f, "Error parsing coordinates: {v}"),
|
||||
Self::InvalidCoordinates(n) => write!(f, "Error reading the coordinates list. It contains {n} components instead of 7."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
struct Moon {
|
||||
position: Coordinate,
|
||||
|
@ -44,11 +66,13 @@ struct Moon {
|
|||
}
|
||||
|
||||
impl TryFrom<&str> for Moon {
|
||||
type Error = ParseIntError;
|
||||
type Error = ParseMoonError;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
let components: Vec<_> = value.split(&['=', ',', '>']).collect();
|
||||
assert_eq!(components.len(), 7);
|
||||
if components.len() != 7 {
|
||||
return Err(ParseMoonError::InvalidCoordinates(components.len()));
|
||||
}
|
||||
let x = components[1].parse()?;
|
||||
let y = components[3].parse()?;
|
||||
let z = components[5].parse()?;
|
||||
|
@ -82,8 +106,9 @@ impl LunarSystem {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
let moons: Vec<Moon> = input.lines().map(Moon::try_from).collect::<Result<Vec<Moon>, _>>().unwrap();
|
||||
pub fn run(input: &str) -> Result<(usize, usize), ParseMoonError> {
|
||||
let moons: Vec<Moon> = input.lines().map(Moon::try_from).collect::<Result<Vec<Moon>, _>>()?;
|
||||
//.unwrap_or_else(|err| panic!("Error parsing input into moons: {err}"));
|
||||
let mut system = LunarSystem { moons: moons.to_vec(), };
|
||||
for _ in 0..1000 {
|
||||
system.step_motion();
|
||||
|
@ -114,7 +139,7 @@ pub fn run(input: &str) -> (usize, usize) {
|
|||
}
|
||||
}
|
||||
let second = scm(periods[0], scm(periods[1], periods[2]));
|
||||
(first, second)
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
fn scm(lhs: usize, rhs: usize) -> usize {
|
||||
|
@ -142,12 +167,12 @@ mod tests {
|
|||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (14645, 4686774924));
|
||||
assert_eq!(run(&sample_input), Ok((14645, 4686774924)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (7687, 334945516288044));
|
||||
assert_eq!(run(&challenge_input), Ok((7687, 334945516288044)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<x=-8, y=-10, z=0>
|
||||
<x=-8, y=-10, z=O>
|
||||
<x=5, y=5, z=10>
|
||||
<x=2, y=-7, z=3>
|
||||
<x=9, y=-8, z=-3>
|
||||
|
|
|
@ -1,4 +1,25 @@
|
|||
use std::collections::{HashMap, VecDeque};
|
||||
use std::{collections::{HashMap, VecDeque}, fmt::Display, num::ParseIntError};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ParseError {
|
||||
ParseIntError(std::num::ParseIntError),
|
||||
LineMalformed(String),
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for ParseError {
|
||||
fn from(value: ParseIntError) -> Self {
|
||||
Self::ParseIntError(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::ParseIntError(e) => write!(f, "Unable to parse into integer: {e}"),
|
||||
Self::LineMalformed(v) => write!(f, "Line is malformed: {v}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Chemical = usize;
|
||||
|
||||
|
@ -13,7 +34,7 @@ struct Reaction {
|
|||
}
|
||||
|
||||
impl Reaction {
|
||||
fn from(line: &str, chemicals: &mut Vec<String>) -> Self {
|
||||
fn try_from(line: &str, chemicals: &mut Vec<String>) -> Result<Self, ParseError> {
|
||||
let mut get_chemical = |name: &str| -> usize {
|
||||
if let Some(idx) = chemicals.iter().position(|c| c == &name.to_string()) {
|
||||
idx
|
||||
|
@ -22,34 +43,37 @@ impl Reaction {
|
|||
chemicals.len()-1
|
||||
}
|
||||
};
|
||||
let (in_str, out_str) = line.split_once(" => ").unwrap();
|
||||
if let Some((in_str, out_str)) = line.split_once(" => ") {
|
||||
let in_components: Vec<_> = in_str.split(&[' ', ',']).chain([""].into_iter()).collect();
|
||||
assert_eq!(in_components.len()%3, 0);
|
||||
let out_components: Vec<_> = out_str.split(' ').collect();
|
||||
assert_eq!(out_components.len(), 2);
|
||||
let output = Reagent {
|
||||
id: get_chemical(out_components[1]),
|
||||
amount: out_components[0].parse().unwrap(),
|
||||
amount: out_components[0].parse()?,
|
||||
};
|
||||
|
||||
let input = in_components.chunks(3).map(|c| Reagent { id: get_chemical(c[1]), amount: c[0].parse::<usize>().unwrap(), }).collect();
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
input,
|
||||
output,
|
||||
})
|
||||
} else {
|
||||
Err(ParseError::LineMalformed(line.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str) -> (usize, usize) {
|
||||
pub fn run(input: &str) -> Result<(usize, usize), ParseError> {
|
||||
let mut chemicals = Vec::new();
|
||||
let reactions: Vec<_> = input.lines().map(|line| Reaction::from(line, &mut chemicals)).collect();
|
||||
let reactions: Vec<_> = input.lines().map(|line| Reaction::try_from(line, &mut chemicals)).collect::<Result<Vec<_>, _>>()?;
|
||||
let fuel = chemicals.iter().position(|chem| chem == &String::from("FUEL")).unwrap();
|
||||
let ore = chemicals.iter().position(|chem| chem == &String::from("ORE")).unwrap();
|
||||
// dbg!(&chemicals);
|
||||
let first = break_down(&reactions, fuel, ore, 1);
|
||||
let second = bisection_find(1_000_000_000_000/first, 10_000_000_000_000/first, &reactions, fuel, ore, 1_000_000_000_000);
|
||||
(first, second)
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
fn bisection_find(lower: usize, upper: usize, reactions: &[Reaction], target: usize, raw: usize, stock: usize) -> usize {
|
||||
|
@ -109,12 +133,12 @@ mod tests {
|
|||
#[test]
|
||||
fn test_sample() {
|
||||
let sample_input = read_file("tests/sample_input");
|
||||
assert_eq!(run(&sample_input), (2210736, 460664));
|
||||
assert_eq!(run(&sample_input), Ok((2210736, 460664)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let challenge_input = read_file("tests/challenge_input");
|
||||
assert_eq!(run(&challenge_input), (1582325, 2267486));
|
||||
assert_eq!(run(&challenge_input), Ok((1582325, 2267486)));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue