Add Rust & Python day 5

main
Bram 2024-12-07 06:41:52 +00:00
parent ee4e8eccfb
commit 4dba9ee6bf
9 changed files with 1612 additions and 0 deletions

1371
inputs/05.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,3 +6,5 @@ import src.day_03.part_1
import src.day_03.part_2
import src.day_04.part_1
import src.day_04.part_2
import src.day_05.part_1
import src.day_05.part_2

2
src/day_05/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod part_1;
pub mod part_2;

41
src/day_05/part_1.py Normal file
View File

@ -0,0 +1,41 @@
def main():
rules_raw, handbooks_raw = open('inputs/05.txt').read().split("\n\n")
rules = []
for rule in rules_raw.strip().split('\n'):
l, r = rule.split('|')
rules.append((int(l), int(r)))
handbooks = []
for handbook in handbooks_raw.strip().split('\n'):
handbooks.append([ int(h) for h in handbook.split(',') ])
total = 0
for handbook in handbooks:
if follows_rules(handbook, rules):
total += middle_number(handbook)
print(f"Day 05 part 1: {total}")
def follows_rule(handbook, rule):
try:
first = handbook.index(rule[0])
second = handbook.index(rule[1])
except ValueError:
return True
else:
return first < second
def follows_rules(handbook, rules):
for rule in rules:
if not follows_rule(handbook, rule):
return False
else:
return True
def middle_number(items):
return items[len(items) // 2]
# if __name__ == '__main__':
main()

55
src/day_05/part_1.rs Normal file
View File

@ -0,0 +1,55 @@
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)? ))
}

61
src/day_05/part_2.py Normal file
View File

@ -0,0 +1,61 @@
def main():
rules_raw, handbooks_raw = open('inputs/05.txt').read().split("\n\n")
rules = []
for rule in rules_raw.strip().split('\n'):
l, r = rule.split('|')
rules.append((int(l), int(r)))
handbooks = []
for handbook in handbooks_raw.strip().split('\n'):
handbooks.append([ int(h) for h in handbook.split(',') ])
total = 0
for handbook in handbooks:
if not follows_rules(handbook, rules):
reorder(handbook, rules)
total += middle_number(handbook)
print(f"Day 05 part 2: {total}")
def follows_rule(handbook, rule):
try:
first = handbook.index(rule[0])
second = handbook.index(rule[1])
except ValueError:
return True
else:
return first < second
def follows_rules(handbook, rules):
for rule in rules:
if not follows_rule(handbook, rule):
return False
else:
return True
def middle_number(items):
return items[len(items) // 2]
def reorder(handbook, rules):
# Use bubble sort method
all_match = False
while not all_match:
all_match = True
for rule in rules:
try:
i1 = handbook.index(rule[0])
i2 = handbook.index(rule[1])
except ValueError:
pass
else:
# If the order is wrong, swap the two
if i1 > i2:
handbook[i1], handbook[i2] = handbook[i2], handbook[i1]
all_match = False
# if __name__ == '__main__':
main()

72
src/day_05/part_2.rs Normal file
View File

@ -0,0 +1,72 @@
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));
}

View File

@ -3,6 +3,7 @@ mod day_01;
mod day_02;
mod day_03;
mod day_04;
mod day_05;
pub fn day_01() {
let s : String = utils::read_from_file("inputs/01.txt");
@ -27,3 +28,9 @@ pub fn day_04() {
println!("Day 04 part 1: {}", day_04::part_1::answer(s.as_str()));
println!("Day 04 part 2: {}", day_04::part_2::answer(s.as_str()));
}
pub fn day_05() {
let s : String = utils::read_from_file("inputs/05.txt");
println!("Day 05 part 1: {}", day_05::part_1::answer(s.as_str()));
println!("Day 05 part 2: {}", day_05::part_2::answer(s.as_str()));
}

View File

@ -3,4 +3,5 @@ fn main() {
aoc_2024::day_02();
aoc_2024::day_03();
aoc_2024::day_04();
aoc_2024::day_05();
}