Refactor day 4 & 5
parent
551a322cc2
commit
acbb0123ac
|
@ -1,26 +0,0 @@
|
||||||
use crate::utils;
|
|
||||||
|
|
||||||
pub fn answer(lines : &str) -> u32 {
|
|
||||||
let ( mut left, mut right ) : ( Vec<u32>, Vec<u32> ) = lines
|
|
||||||
.split("\n")
|
|
||||||
.filter_map(parse_line)
|
|
||||||
.unzip();
|
|
||||||
|
|
||||||
left.sort_unstable();
|
|
||||||
right.sort_unstable();
|
|
||||||
|
|
||||||
left.iter()
|
|
||||||
.zip(right.iter())
|
|
||||||
.map(|(x, y)| abs_diff(&x, &y))
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn abs_diff(l : &u32, r : &u32) -> u32 {
|
|
||||||
if l >= r { l - r } else { r - l }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_line(s : &str) -> Option<( u32, u32 )> {
|
|
||||||
let (left, right) = s.trim().split_once(" ")?;
|
|
||||||
|
|
||||||
Some(( utils::str_to_u32(left)?, utils::str_to_u32(right)? ))
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
use crate::utils;
|
|
||||||
|
|
||||||
pub fn answer(s : &str) -> u32 {
|
|
||||||
let ( left, right ) : ( Vec<u32>, Vec<u32> ) = s
|
|
||||||
.split("\n")
|
|
||||||
.filter_map(parse_line)
|
|
||||||
.unzip();
|
|
||||||
|
|
||||||
left.iter()
|
|
||||||
.map(|x| right.iter().filter(|y| x == *y).count() as u32 * x)
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_line(s : &str) -> Option<( u32, u32 )> {
|
|
||||||
let (left, right) = s.trim().split_once(" ")?;
|
|
||||||
|
|
||||||
Some(( utils::str_to_u32(left)?, utils::str_to_u32(right)? ))
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
use crate::utils;
|
|
||||||
|
|
||||||
pub fn answer(text : &str) -> usize {
|
|
||||||
text.split("\n")
|
|
||||||
.map(parse_line)
|
|
||||||
.filter(is_safe_line)
|
|
||||||
.count()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_safe_line(v : &Vec<i32>) -> bool {
|
|
||||||
let diff : Vec<i32> = v
|
|
||||||
.windows(2)
|
|
||||||
.filter_map(|v| Some(v.get(0)? - v.get(1)?))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let all_increasing : bool = diff.iter().all(|&x| x < 0);
|
|
||||||
let all_decreasing : bool = diff.iter().all(|&x| x > 0);
|
|
||||||
let all_bounded_ok : bool = diff.iter().all(|&x| x.abs() <= 3);
|
|
||||||
|
|
||||||
all_bounded_ok && (all_increasing || all_decreasing)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_line(s : &str) -> Vec<i32> {
|
|
||||||
s.split(" ").filter_map(utils::str_to_i32).collect()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
use crate::utils;
|
|
||||||
|
|
||||||
pub fn answer(text : &str) -> usize {
|
|
||||||
text.split("\n")
|
|
||||||
.map(parse_line)
|
|
||||||
.filter(is_dampened_safe_line)
|
|
||||||
.count()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_dampened_safe_line(v : &Vec<i32>) -> bool {
|
|
||||||
if is_safe_line(v) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 0..v.len() {
|
|
||||||
let mut cv = v.to_vec();
|
|
||||||
cv.remove(i);
|
|
||||||
|
|
||||||
if is_safe_line(&cv) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_safe_line(v : &Vec<i32>) -> bool {
|
|
||||||
let diff : Vec<i32> = v
|
|
||||||
.windows(2)
|
|
||||||
.filter_map(|v| Some(v.get(0)? - v.get(1)?))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let all_increasing : bool = diff.iter().all(|&x| x < 0);
|
|
||||||
let all_decreasing : bool = diff.iter().all(|&x| x > 0);
|
|
||||||
let all_bounded_ok : bool = diff.iter().all(|&x| x.abs() <= 3);
|
|
||||||
|
|
||||||
all_bounded_ok && (all_increasing || all_decreasing)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_line(s : &str) -> Vec<i32> {
|
|
||||||
s.split(" ").filter_map(utils::str_to_i32).collect()
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
use crate::utils;
|
|
||||||
use regex::Regex;
|
|
||||||
|
|
||||||
pub fn answer(text : &str) -> u32 {
|
|
||||||
Regex::new(r"mul\((\d{1,3}),(\d{1,3})\)")
|
|
||||||
.unwrap()
|
|
||||||
.captures_iter(text)
|
|
||||||
.map(|c| c.extract())
|
|
||||||
.filter_map(|(_, [l1, l2])| Some((utils::str_to_u32(l1)?, utils::str_to_u32(l2)?)))
|
|
||||||
.map(|(x, y)| x * y)
|
|
||||||
.sum()
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
use crate::utils;
|
|
||||||
use regex::Regex;
|
|
||||||
|
|
||||||
pub fn answer(text : &str) -> u32 {
|
|
||||||
match text.split_once("don't()") {
|
|
||||||
Some((head, tail)) => {
|
|
||||||
multiplication_sum(head) + tail.split("don't()").map(take_valid).sum::<u32>()
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
multiplication_sum(text)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn take_valid(s : &str) -> u32 {
|
|
||||||
match s.split_once("do()") {
|
|
||||||
Some((_, valid)) => multiplication_sum(valid),
|
|
||||||
None => 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn multiplication_sum(s : &str) -> u32 {
|
|
||||||
let re = Regex::new(r"mul\((\d{1,3}),(\d{1,3})\)").unwrap();
|
|
||||||
|
|
||||||
re.captures_iter(s)
|
|
||||||
.map(|c| c.extract())
|
|
||||||
.filter_map(|(_, [l1, l2])| Some((utils::str_to_u32(l1)?, utils::str_to_u32(l2)?)))
|
|
||||||
.map(|(x, y)| x * y)
|
|
||||||
.sum()
|
|
||||||
}
|
|
|
@ -1,2 +1,87 @@
|
||||||
pub mod part_1;
|
use crate::utils;
|
||||||
pub mod part_2;
|
|
||||||
|
pub fn answer(text : String) -> ( u16, u16 ) {
|
||||||
|
let grid : Vec<Vec<char>> = from_string(text);
|
||||||
|
|
||||||
|
let rows = grid.len();
|
||||||
|
let cols = grid[0].len();
|
||||||
|
|
||||||
|
( find_xmas(&grid, rows as isize, cols as isize), find_x_mas(&grid, rows, cols) )
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_x_mas(grid : &Vec<Vec<char>>, rows : usize, cols : usize) -> u16 {
|
||||||
|
let mut total : u16 = 0;
|
||||||
|
|
||||||
|
for y in 1..rows-1 {
|
||||||
|
for x in 1..cols-1 {
|
||||||
|
if grid[y][x] == 'A' {
|
||||||
|
total = total + inspect_x_mas_location(&grid, x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
total
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_xmas(grid : &Vec<Vec<char>>, rows : isize, cols : isize) -> u16 {
|
||||||
|
let mut total : u16 = 0;
|
||||||
|
|
||||||
|
for y in 0..rows {
|
||||||
|
for x in 0..cols {
|
||||||
|
if grid[y as usize][x as usize] == 'X' {
|
||||||
|
total = total + inspect_xmas_location(&grid, x, y, rows, cols)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
total
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_string(s : String) -> Vec<Vec<char>> {
|
||||||
|
s.split("\n").map(|s| s.chars().collect()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inspect_x_mas_location(grid : &Vec<Vec<char>>, x : usize, y : usize) -> u16 {
|
||||||
|
let c1 = grid[y-1][x-1];
|
||||||
|
let c2 = grid[y-1][x+1];
|
||||||
|
let c3 = grid[y+1][x-1];
|
||||||
|
let c4 = grid[y+1][x+1];
|
||||||
|
|
||||||
|
let horizontal = c1 == c2 && c3 == c4 && c1 != c3;
|
||||||
|
let vertical = c1 == c3 && c2 == c4 && c1 != c2;
|
||||||
|
let letters_match = (c1 == 'M' && c4 == 'S') || (c1 == 'S' && c4 == 'M');
|
||||||
|
|
||||||
|
if letters_match && (horizontal || vertical) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inspect_xmas_location(grid : &Vec<Vec<char>>, x : isize, y : isize, rows : isize, cols : isize) -> u16 {
|
||||||
|
let mut total : u16 = 0;
|
||||||
|
|
||||||
|
for dx in -1..=1 {
|
||||||
|
for dy in -1..=1 {
|
||||||
|
if dx == 0 && dy == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (s_x, s_y) = ( x + 3 * dx, y + 3 * dy );
|
||||||
|
|
||||||
|
if s_x < 0 || s_x >= rows || s_y < 0 || s_y >= cols {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let m = grid[(y + 1 * dy) as usize][(x + 1 * dx) as usize];
|
||||||
|
let a = grid[(y + 2 * dy) as usize][(x + 2 * dx) as usize];
|
||||||
|
let s = grid[(y + 3 * dy) as usize][(x + 3 * dx) as usize];
|
||||||
|
|
||||||
|
if m == 'M' && a == 'A' && s == 'S' {
|
||||||
|
total = total + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
total
|
||||||
|
}
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
pub fn answer(s : &str) -> u32 {
|
|
||||||
let grid : Vec<Vec<char>> = s.split("\n")
|
|
||||||
.map(|s| s.chars().collect())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let rows : i32 = grid.len().try_into().unwrap();
|
|
||||||
let cols : i32 = grid[0].len().try_into().unwrap();
|
|
||||||
let mut total : u32 = 0;
|
|
||||||
|
|
||||||
for y in 0..rows {
|
|
||||||
for x in 0..cols {
|
|
||||||
if grid[y as usize][x as usize] == 'X' {
|
|
||||||
total = total + inspect_location(&grid, x, y, rows, cols)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
total
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inspect_location(grid : &Vec<Vec<char>>, x : i32, y : i32, rows : i32, cols : i32) -> u32 {
|
|
||||||
let mut total = 0;
|
|
||||||
|
|
||||||
for dx in -1..=1 {
|
|
||||||
for dy in -1..=1 {
|
|
||||||
if dx == 0 && dy == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (s_x, s_y) = ( x + 3 * dx, y + 3 * dy );
|
|
||||||
|
|
||||||
if s_x < 0 || s_x >= rows || s_y < 0 || s_y >= cols {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let m = grid[(y + 1 * dy) as usize][(x + 1 * dx) as usize];
|
|
||||||
let a = grid[(y + 2 * dy) as usize][(x + 2 * dx) as usize];
|
|
||||||
let s = grid[(y + 3 * dy) as usize][(x + 3 * dx) as usize];
|
|
||||||
|
|
||||||
if m == 'M' && a == 'A' && s == 'S' {
|
|
||||||
total = total + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
total
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
pub fn answer(s : &str) -> u32 {
|
|
||||||
let grid : Vec<Vec<char>> = s.split("\n")
|
|
||||||
.map(|s| s.chars().collect())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let rows = grid.len();
|
|
||||||
let cols = grid[0].len();
|
|
||||||
let mut total : u32 = 0;
|
|
||||||
|
|
||||||
for y in 1..rows-1 {
|
|
||||||
for x in 1..cols-1 {
|
|
||||||
if grid[y as usize][x as usize] == 'A' {
|
|
||||||
total = total + inspect_location(&grid, x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
total
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inspect_location(grid : &Vec<Vec<char>>, x : usize, y : usize) -> u32 {
|
|
||||||
let c1 = grid[y-1][x-1];
|
|
||||||
let c2 = grid[y-1][x+1];
|
|
||||||
let c3 = grid[y+1][x-1];
|
|
||||||
let c4 = grid[y+1][x+1];
|
|
||||||
|
|
||||||
let horizontal = c1 == c2 && c3 == c4 && c1 != c3;
|
|
||||||
let vertical = c1 == c3 && c2 == c4 && c1 != c2;
|
|
||||||
let letters_match = (c1 == 'M' && c4 == 'S') || (c1 == 'S' && c4 == 'M');
|
|
||||||
|
|
||||||
if letters_match && (horizontal || vertical) {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +1,93 @@
|
||||||
pub mod part_1;
|
use crate::utils;
|
||||||
pub mod part_2;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
type HandBook = Vec<u8>;
|
||||||
|
type RuleSet = HashSet<(u8, u8)>;
|
||||||
|
|
||||||
|
pub fn answer(text : String) -> ( u16, u16 ) {
|
||||||
|
let ( rules, handbooks ) : ( RuleSet, Vec<HandBook> ) = parse_input(text);
|
||||||
|
let ( sorted, unsorted ) : ( Vec<_>, Vec<_> ) = handbooks
|
||||||
|
.iter()
|
||||||
|
.partition(|hb| follows_rules(hb, &rules));
|
||||||
|
|
||||||
|
( sorted.iter().map(|hb| sorted_middle_value(hb) as u16).sum()
|
||||||
|
, unsorted.iter().map(|hb| unsorted_middle_value(hb, &rules)).sum()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn follows_rules(handbook : &HandBook, rules : &RuleSet) -> bool {
|
||||||
|
handbook.windows(2).all(|rule| {
|
||||||
|
match (rule.get(0), rule.get(1)) {
|
||||||
|
(Some(a), Some(b)) => {
|
||||||
|
rules.contains(&(*a, *b))
|
||||||
|
},
|
||||||
|
// Invalid situations
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_hand_line(s : &str) -> Option<Vec<u8>> {
|
||||||
|
let v : Vec<u8> = s.split(",").filter_map(utils::str_to_u8).collect();
|
||||||
|
|
||||||
|
if v.len() == 0 { None } else { Some(v) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_input(s : String) -> (RuleSet, Vec<HandBook>) {
|
||||||
|
let (r, h) = s.split_once("\n\n").unwrap_or(("", ""));
|
||||||
|
|
||||||
|
( r.split("\n").filter_map(parse_rule_line).collect()
|
||||||
|
, h.split("\n").filter_map(parse_hand_line).collect()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_rule_line(s : &str) -> Option<(u8, u8)> {
|
||||||
|
let (l, r) = s.split_once("|")?;
|
||||||
|
|
||||||
|
Some(( utils::str_to_u8(l)?, utils::str_to_u8(r)? ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unsorted_middle_value(handbook : &HandBook, rules : &RuleSet) -> u16 {
|
||||||
|
let (head, tail) = handbook.split_first().unwrap();
|
||||||
|
|
||||||
|
let mut cursor : u8 = *head;
|
||||||
|
let mut num_lower : u8 = 0;
|
||||||
|
let mut num_higher : u8 = 0;
|
||||||
|
let mut lower : Vec<u8> = Vec::new();
|
||||||
|
let mut higher : Vec<u8> = Vec::new();
|
||||||
|
let mut stack : Vec<u8> = Vec::from(tail);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// Classify numbers based on their order
|
||||||
|
while let Some(n) = stack.pop() {
|
||||||
|
if rules.contains(&( cursor, n )) {
|
||||||
|
higher.push(n);
|
||||||
|
} else {
|
||||||
|
lower.push(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we've found the correct number
|
||||||
|
let low = num_lower + lower.len() as u8;
|
||||||
|
let high = num_higher + higher.len() as u8;
|
||||||
|
if low == high {
|
||||||
|
return cursor.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, rearrange the variables for the next step
|
||||||
|
if low < high {
|
||||||
|
(num_lower, lower) = (low + 1, Vec::new());
|
||||||
|
(stack, higher) = (higher, Vec::new());
|
||||||
|
} else {
|
||||||
|
(num_higher, higher) = (high + 1, Vec::new());
|
||||||
|
(stack, lower) = (lower, Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick the next value
|
||||||
|
cursor = stack.pop().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sorted_middle_value(handbook : &HandBook) -> u8 {
|
||||||
|
handbook[handbook.len() / 2]
|
||||||
|
}
|
|
@ -1,55 +0,0 @@
|
||||||
use crate::utils;
|
|
||||||
|
|
||||||
type HandBook = Vec<u32>;
|
|
||||||
type RuleSet = Vec<(u32, u32)>;
|
|
||||||
|
|
||||||
pub fn answer(s : &str) -> u32 {
|
|
||||||
let ( rules, handbooks ) = parse_input(s);
|
|
||||||
|
|
||||||
handbooks.iter()
|
|
||||||
.filter(|hb| follows_rules(hb, &rules))
|
|
||||||
.map(middle_value)
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn follows_rules(handbook : &HandBook, rules : &RuleSet) -> bool {
|
|
||||||
rules.iter().all(|rule| follows_rule(handbook, rule))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn follows_rule(handbook : &HandBook, (first, second) : &(u32, u32)) -> bool {
|
|
||||||
let mut encountered_second : bool = false;
|
|
||||||
|
|
||||||
for num in handbook.iter() {
|
|
||||||
if num == first {
|
|
||||||
return !encountered_second;
|
|
||||||
} else if num == second {
|
|
||||||
encountered_second = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn middle_value(handbook : &HandBook) -> u32 {
|
|
||||||
handbook[handbook.len() / 2]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_hand_line(s : &str) -> Option<Vec<u32>> {
|
|
||||||
let v : Vec<u32> = s.split(",").filter_map(utils::str_to_u32).collect();
|
|
||||||
|
|
||||||
if v.len() == 0 { None } else { Some(v) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_input(s : &str) -> (RuleSet, Vec<HandBook>) {
|
|
||||||
let (r, h) = s.split_once("\n\n").unwrap_or(("", ""));
|
|
||||||
|
|
||||||
( r.split("\n").filter_map(parse_rule_line).collect()
|
|
||||||
, h.split("\n").filter_map(parse_hand_line).collect()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_rule_line(s : &str) -> Option<(u32, u32)> {
|
|
||||||
let (l, r) = s.split_once("|")?;
|
|
||||||
|
|
||||||
Some(( utils::str_to_u32(l)?, utils::str_to_u32(r)? ))
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
use crate::utils;
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
|
|
||||||
type HandBook = Vec<u32>;
|
|
||||||
type RuleSet = Vec<(u32, u32)>;
|
|
||||||
|
|
||||||
pub fn answer(s : &str) -> u32 {
|
|
||||||
let ( rules, mut handbooks ) = parse_input(s);
|
|
||||||
|
|
||||||
handbooks.iter_mut()
|
|
||||||
.filter(|hb| !follows_rules(hb, &rules))
|
|
||||||
.map(|hb| { reorder_pages(hb, &rules); middle_value(hb) })
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn page_cmp(a : &u32, b : &u32, rules : &RuleSet) -> Ordering {
|
|
||||||
for (r1, r2) in rules.iter() {
|
|
||||||
if r1 == a && r2 == b {
|
|
||||||
return Ordering::Less;
|
|
||||||
} else if r1 == b && r2 == a {
|
|
||||||
return Ordering::Greater;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ordering::Equal
|
|
||||||
}
|
|
||||||
|
|
||||||
fn follows_rules(handbook : &HandBook, rules : &RuleSet) -> bool {
|
|
||||||
rules.iter().all(|rule| follows_rule(handbook, rule))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn follows_rule(handbook : &HandBook, (first, second) : &(u32, u32)) -> bool {
|
|
||||||
let mut encountered_second : bool = false;
|
|
||||||
|
|
||||||
for num in handbook.iter() {
|
|
||||||
if num == first {
|
|
||||||
return !encountered_second;
|
|
||||||
} else if num == second {
|
|
||||||
encountered_second = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn middle_value(handbook : &HandBook) -> u32 {
|
|
||||||
handbook[handbook.len() / 2]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_hand_line(s : &str) -> Option<Vec<u32>> {
|
|
||||||
let v : Vec<u32> = s.split(",").filter_map(utils::str_to_u32).collect();
|
|
||||||
|
|
||||||
if v.len() == 0 { None } else { Some(v) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_input(s : &str) -> (RuleSet, Vec<HandBook>) {
|
|
||||||
let (r, h) = s.split_once("\n\n").unwrap_or(("", ""));
|
|
||||||
|
|
||||||
( r.split("\n").filter_map(parse_rule_line).collect()
|
|
||||||
, h.split("\n").filter_map(parse_hand_line).collect()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_rule_line(s : &str) -> Option<(u32, u32)> {
|
|
||||||
let (l, r) = s.split_once("|")?;
|
|
||||||
|
|
||||||
Some(( utils::str_to_u32(l)?, utils::str_to_u32(r)? ))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reorder_pages(handbook : &mut HandBook, rules : &RuleSet) {
|
|
||||||
handbook.sort_unstable_by(|a, b| page_cmp(a, b, rules));
|
|
||||||
}
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -1,6 +1,8 @@
|
||||||
mod day_01;
|
mod day_01;
|
||||||
mod day_02;
|
mod day_02;
|
||||||
mod day_03;
|
mod day_03;
|
||||||
|
mod day_04;
|
||||||
|
mod day_05;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -29,3 +31,17 @@ pub fn day_03() -> DailyOutput {
|
||||||
|
|
||||||
( p1 as u128, p2 as u128, d )
|
( p1 as u128, p2 as u128, d )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn day_04() -> DailyOutput {
|
||||||
|
let s : String = read_from_file("inputs/04.txt");
|
||||||
|
let (p1, p2, d) = diagnostics::benchmark(s, day_04::answer);
|
||||||
|
|
||||||
|
( p1 as u128, p2 as u128, d )
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn day_05() -> DailyOutput {
|
||||||
|
let s : String = read_from_file("inputs/05.txt");
|
||||||
|
let (p1, p2, d) = diagnostics::benchmark(s, day_05::answer);
|
||||||
|
|
||||||
|
( p1 as u128, p2 as u128, d )
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ fn main() {
|
||||||
aoc.insert(1, aoc_2024::day_01());
|
aoc.insert(1, aoc_2024::day_01());
|
||||||
aoc.insert(2, aoc_2024::day_02());
|
aoc.insert(2, aoc_2024::day_02());
|
||||||
aoc.insert(3, aoc_2024::day_03());
|
aoc.insert(3, aoc_2024::day_03());
|
||||||
|
aoc.insert(4, aoc_2024::day_04());
|
||||||
|
aoc.insert(5, aoc_2024::day_05());
|
||||||
|
|
||||||
aoc.show_diagnostics();
|
aoc.show_diagnostics();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,11 +39,11 @@ impl AdventOfCode {
|
||||||
.map(|(day, result)| {
|
.map(|(day, result)| {
|
||||||
match result {
|
match result {
|
||||||
Some(r) => {
|
Some(r) => {
|
||||||
println!("{}", r.to_string(day, MAX_MS_ON_SCREEN));
|
println!("{}", r.to_string(day + 1, MAX_MS_ON_SCREEN));
|
||||||
r.duration.as_millis()
|
r.duration.as_millis()
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
println!("{}", empty_diagnostic(day));
|
println!("{}", empty_diagnostic(day + 1));
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue