corneil
{corneil-realName}
Github: AlexisTM
Twitter: @AlexisPaques
Mastodon: @AlexisTM@fosstodon.org
corneil |
I am a Robotics Engineer working mainly in C++, Python & Javascript.
I started the AoC 2021 in RockStar but didn’t have the bravery to go all the way through it.
Today, I want to learn Rust so created few projects and will do this AoC with it. This would definitely have avoided Ping CVE in FreeBSD.
To start up with rust, you can install the toolchain with Rustup, then compile & run with:
cargo run --release
main.rs
use std::fs;
fn main() {
let input = fs::read_to_string("input.txt")
.expect("Should have been able to read the file");
println!("Oh, I didn't see you there {}", input);
}
main.rs
use std::fs;
fn main() {
let input = fs::read_to_string("input.txt")
.expect("Should have been able to read the file");
let elves_data = input.split("\n\n");
let mut calories = Vec::<u64>::new();
for elf in elves_data {
let val: u64 = elf.split("\n")
.map(|s| s.trim())
.filter(|s| !s.is_empty())
.map(|s| -> u64 {s.parse().unwrap()})
.fold(0u64, |acc, b| acc + b);
calories.push(val);
}
println!("{}", calories.iter().max().unwrap());
// Top 3
calories.sort();
let sum: u64 = calories.iter().rev().take(3).sum();
println!("{}", sum);
}
This was solved in two step: Assign a value for each possible input (9 in total), then just sum them using a fold over the iteration.
main.rs # input
let quick_conversion_p2: HashMap<&str, u64> = [
("A X", 3),
("A Y", 4),
("A Z", 8),
("B X", 1),
("B Y", 5),
("B Z", 9),
("C X", 2),
("C Y", 6),
("C Z", 7),
]
.iter()
.cloned()
.collect();
let p1 = solve(&input, &quick_conversion_p1);
let p2 = solve(&input, &quick_conversion_p2);
The solution becomes trivial with this methodology
main.rs # solution
fn solve(input: &String, quick_conversion: &HashMap<&str, u64>) -> u64 {
let result: u64 = input
.lines()
.map(|s| s.trim())
.filter(|s| !s.is_empty())
.fold(0u64, |acc, b| acc + quick_conversion[b]);
return result;
}
Today’s problem is solved in few steps: - Split the input in the slices to compare - Find the common char in those slices - Convert the letters to numbers - Accumulate the numbers
find the common letters between 2 or 3 slices
fn common_char(start: &str, end: &str) -> Option<char> {
start.chars().filter(|c| end.contains(*c)).nth(0)
}
fn common_chars(b1: &str, b2: &str, b3: &str) -> Option<char> {
b1.chars().filter(|c| b2.contains(*c)).filter(|c| b3.contains(*c)).nth(0)
}
Convert chars to numbers
fn accumulate_letters(acc: u64, val: Option<char>) -> u64 {
if let Some(val) = val {
if val <= 'Z' {
return acc + 27 + (val as u8 - 'A' as u8) as u64;
} else {
return acc + 1 + (val as u8 - 'a' as u8) as u64;
}
} else {
println!("Empty result, can't be used!");
return acc;
}
}
Solution 1
let part1: u64 = input
.lines()
.map(|f| common_char(&f[0..f.len() / 2], &f[f.len() / 2..]))
.fold(0, accumulate_letters);
Solution 2
let part2 = input.lines().chunks(3).into_iter().map(|chunk| {
let values: Vec<&str> = chunk.collect();
common_chars(values[0], values[1], values[2])
}).fold(0u64, accumulate_letters);
Both problems are identical today, just the condition for summing is different.
First convert the string into an array of string slices.
Convert the slices to int, expecting 4 of them. (it will panic on unwrap if we don’t have 4)
Apply the condition of the problem, return 1 for success
Sum
Solution 1
let part1: u32 = input
.lines()
.map(|f| f.split(|f| f == ',' || f == '-'))
.map(|mut f| {
(
(
f.next().unwrap().parse::<u32>().unwrap(),
f.next().unwrap().parse::<u32>().unwrap(),
),
(
f.next().unwrap().parse::<u32>().unwrap(),
f.next().unwrap().parse::<u32>().unwrap(),
),
)
})
.map(|(elf1, elf2)| {
if (elf1.0 <= elf2.0 && elf2.1 <= elf1.1) || (elf2.0 <= elf1.0 && elf1.1 <= elf2.1) {
return 1;
}
return 0;
})
.sum();
Solution 2
.map(|(elf1, elf2)| {
if (elf1.0 <= elf2.0 && elf2.0 <= elf1.1) || (elf2.0 <= elf1.0 && elf1.0 <= elf2.1) {
return 1;
}
return 0;
})