Add 2024 Quest 1
This commit is contained in:
parent
8a49bcb900
commit
097a98f919
10 changed files with 152 additions and 0 deletions
1
2024/day01_The_Battle_for_the_Farmlands/.gitignore
vendored
Normal file
1
2024/day01_The_Battle_for_the_Farmlands/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
6
2024/day01_The_Battle_for_the_Farmlands/Cargo.toml
Normal file
6
2024/day01_The_Battle_for_the_Farmlands/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "day01_the_battle_for_the_farmlands"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
49
2024/day01_The_Battle_for_the_Farmlands/challenge.txt
Normal file
49
2024/day01_The_Battle_for_the_Farmlands/challenge.txt
Normal file
|
@ -0,0 +1,49 @@
|
|||
Part I
|
||||
|
||||
The green farmlands of Algorithmia are in constant danger from creatures hiding in the dark. It would be wise to include some fun in the mission, so the first challenge of the tournament is protecting the important crops from destruction.
|
||||
Each brave knight is given a specific piece of land to protect, but the job isn't just about fighting magical creatures. The battle requires using healing potions, which must be planned ahead of time. The Council of Wizards, who are always observing and judging, will evaluate competitors based on the use of healing potions.
|
||||
The goal is to defeat all enemies while using the fewest number of potions possible. Therefore, your potion plan must be executed with accuracy and insight. Luckily, the kingdom's smartest spies have gathered a list of incoming creatures for each area. You also know exactly how many potions are needed for each type of creature:
|
||||
Ancient Ant (A): Not very dangerous. Can be managed without using any potions.
|
||||
Badass Beetle (B): A big and strong bug that requires 1 potion to defeat.
|
||||
Creepy Cockroach (C): Fast and aggressive! This creature requires 3 potions to defeat it.
|
||||
With this knowledge, you must order the exact number of potions that need to be made for your mission.
|
||||
Example based on the following notes:
|
||||
ABBAC
|
||||
Each creature is shown by a single letter, leading to this sequence of battles:
|
||||
No potions are needed for the first A (Ancient Ant).
|
||||
1 potion is needed for the first B (Badass Beetle).
|
||||
1 potion is needed for the second B (Badass Beetle).
|
||||
No potions are needed for the next A (Ancient Ant).
|
||||
3 potions are needed for the last monster, C (Creepy Cockroach).
|
||||
In total, you need to order: 0 + 1 + 1 + 0 + 3 = 5 potions.
|
||||
What is the exact number of potions that need to be prepared for your battle?
|
||||
|
||||
Part II
|
||||
|
||||
Round two begins! A new area awaits, bringing with it a new list of foes, and a familiar but formidable opponent:
|
||||
Diabolical Dragonfly (D): A fast and tricky enemy, hard to hit. This creature requires 5 potions to defeat it.
|
||||
This time, however, the battles become more challenging. According to the kingdom's spies, the enemies sometimes join forces in pairs, making them tougher to defeat.
|
||||
When two monsters pair up, you will need one more potion per creature than in a one-on-one fight.
|
||||
Your list remains a single line of creatures, but now you must interpret it in pairs. The x symbol shows an empty spot where no monster appears, so for these pairs your calculations should follow the same rules as for individual battles.
|
||||
Example based on the following notes:
|
||||
AxBCDDCAxD
|
||||
After splitting into pairs, the battle sequence looks like this:
|
||||
Ax BC DD CA xD
|
||||
The Ax pair requires no potions because a single Ancient Ant remains weak as before.
|
||||
The BC pair requires 6 potions which is 2 for the Badass Beetle and 4 for the Creepy Cockroach because they are attacking together.
|
||||
The DD pair requires 12 potions which is 6 per Diabolical Dragonfly instead of the usual 5 since they are attacking together.
|
||||
The CA pair requires 5 potions which is 4 for the Creepy Cockroach and 1 for the Ancient Ant.
|
||||
The xD pair requires 5 potions because no additional potion is needed for a single Diabolical Dragonfly.
|
||||
In total, you must order: 0 + 6 + 12 + 5 + 5 = 28 potions.
|
||||
What is the exact number of potions you need to order for round two?
|
||||
|
||||
Part III
|
||||
|
||||
The final round is here, and, as expected, it is the most challenging of all! Although no new enemies have appeared, they have grown wiser and realized their strength in numbers.
|
||||
In this ultimate challenge, you will not just face pairs, but also groups of three! For these tough battles, you will need 2 extra potions per creature compared to fighting them one-on-one.
|
||||
Example based on the following notes:
|
||||
xBxAAABCDxCC
|
||||
Once the battles are split into their respective groups, they will unfold as follows:
|
||||
xBx AAA BCD xCC
|
||||
In total, you must order: 1 + 6 + 15 + 8 = 30 potions.
|
||||
What is the exact number of potions you need to order for the final round?
|
90
2024/day01_The_Battle_for_the_Farmlands/src/lib.rs
Normal file
90
2024/day01_The_Battle_for_the_Farmlands/src/lib.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
use core::fmt::Display;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ParseError {
|
||||
ParseCharError(char)
|
||||
}
|
||||
|
||||
impl Display for ParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::ParseCharError(e) => write!(f, "Unable to parse into creature: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
enum Creature{ Ant, Beetle, Cockroach, Dragonfly, None }
|
||||
|
||||
impl TryFrom<char> for Creature {
|
||||
type Error = ParseError;
|
||||
|
||||
fn try_from(value: char) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
'A' => Ok(Self::Ant),
|
||||
'B' => Ok(Self::Beetle),
|
||||
'C' => Ok(Self::Cockroach),
|
||||
'D' => Ok(Self::Dragonfly),
|
||||
'x' => Ok(Self::None),
|
||||
e => Err(Self::Error::ParseCharError(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Creature {
|
||||
fn required_potions(&self) -> usize {
|
||||
match self {
|
||||
Self::Ant | Self::None => 0,
|
||||
Self::Beetle => 1,
|
||||
Self::Cockroach => 3,
|
||||
Self::Dragonfly => 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn required_potions_for_group(pair: &[Creature]) -> usize {
|
||||
pair.iter().map(|c| c.required_potions()).sum::<usize>() +
|
||||
match pair.iter().filter(|c| c != &&Creature::None).count() {
|
||||
3 => 6,
|
||||
2 => 2,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(input: &str, part: usize) -> Result<usize, ParseError> {
|
||||
let items: Vec<_> = input.lines().next().unwrap_or_default().chars().map(Creature::try_from).collect::<Result<Vec<_>, _>>()?;
|
||||
match part {
|
||||
1 => Ok(items.iter().map(|c| c.required_potions()).sum()),
|
||||
2 => Ok(items.chunks(2).map(required_potions_for_group).sum()),
|
||||
3 => Ok(items.chunks(3).map(required_potions_for_group).sum()),
|
||||
_ => panic!("Illegal part number"),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
fn read_file(name: &str) -> String {
|
||||
read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sample() {
|
||||
let expected = [5, 28, 30];
|
||||
for part in 1..=3 {
|
||||
let sample_input = read_file(&format!("tests/sample{part}"));
|
||||
assert_eq!(run(&sample_input, part), Ok(expected[part-1]));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_challenge() {
|
||||
let expected = [1310, 5582, 27825];
|
||||
for part in 1..=3 {
|
||||
let challenge_input = read_file(&format!("tests/challenge{part}"));
|
||||
assert_eq!(run(&challenge_input, part), Ok(expected[part-1]));
|
||||
}
|
||||
}
|
||||
}
|
1
2024/day01_The_Battle_for_the_Farmlands/tests/challenge1
Normal file
1
2024/day01_The_Battle_for_the_Farmlands/tests/challenge1
Normal file
|
@ -0,0 +1 @@
|
|||
CBCCACCBCCCBBBBCBBCBAABABABBABCBCCABBAAABCABABCBBAACBCCBACAABBAABACCBCAABCCACCCABABCCCCCBBAACACABAAABCCCACAABAAAACCABCAABCACBCBBABCABBCBBCBABACBAABCBBACBABBBBACCACACABCBCBABCBABABBACCCBCBBABCACAACBCAAAACBCCCCBBACCCCACABABACBAABCBCBBBCBAACBCBAAABBBABBABBACBAABCBABCCACAAACBBABAACBCBCCBBCCCACBBCAACBBCBAABBBBBBCCBBCAABBCCCBACCBCBCCBAAAABBCABBABCCBBAAAAAAAABAAAAAAACBACBAAABBBCCCCABCABBBCBACCACABBBCABCBAABBBCCACCCBBAABCBCBABCCCCBCBBBCACBAABCAABCAAAABACACBBAAABBCBBBACBBABCBBACAABABACABCBBBBCBABACBBACCCCAAAABACBAACBCAACCCBCCCBCBCAABCCAAAABBBBBBCCBBAABAABBBBBAACCCCCAABABABCACAABBBACBBBACACACAAABABBACCACBBCACCBCABCCCCCBBCAABCBCABACCBCAABCBCCABACBBABBACABBBACABBBBBBBACACCCBACCCBAACCCAABABBCBBCBBBABCACCBABBBBBBACCCABCABABCCCBBBBAACABBBBBCACCCCACAAAAACACBAAAAAABABBBCCCBACCBAACACBCAACBBCAABACCCABCAACACCCBABCCCAABCCBCABABCBCCCBCCAAACBBCBACCACCAACBABAAABACABBAAACBCCABBABCBCCCBABCCBCBBABBAACACACBAACACBBBBCBCAACCBCCABBAACAACBBBABCABABABAAABBBCBACACAABBBACBCCBCCAAABCABABBCBCBCACBCACCBCABBBBABACBBACCBBAAA
|
1
2024/day01_The_Battle_for_the_Farmlands/tests/challenge2
Normal file
1
2024/day01_The_Battle_for_the_Farmlands/tests/challenge2
Normal file
|
@ -0,0 +1 @@
|
|||
BBBBBDAACAAABAxCABDBDDCBxCACxAADADCAABACCxDCCBDACBCxDACDADACCCxAxBDACBBACxDDABCAADAxABABAADBACCBBBACAACCDCBCDDBDBDDCADBACCCACAxCDAxDCCABBDDDCCDCCCCDCDABADAABADACACCBBDBxBCCBCBBABDAACAACACCxxDAxDCCBCDDBxAADADBBDBADBCCDBABCAAABDDxDxxDDBACCACADCCBDxCABxBCBABxDCABDCDADxxxBBBABBDCCACABxDDBACxBCCCCBAxBCxBADBAAAADCDxBCxAxxCDCBxBDAxBABDxBBCBCCxCBABBDDCDACCDABABDDABCACxDxAACDCBBADCBBDDCCDAAxBxCABCDCADxxCDDCxBDCCDCBDACCCABCDxADBxBDAACCDCBCBCCDxCAxCBAABAAxDxxCDADACDCAACCDCDABxCDCAABCBACABABDDxAABAxBADABADAxCBACCACxDxAADABCBBACDCAABCDBBDBACAAACCBDBBAxBDBBBBBDDBCCBCDCDCDCABDBDBCDxCxABDDCDDCADDCACDCBBCADBCDBxBAADCDAADBxCDDDBCACBCDACCDDxCDDCCDBxACBCBAAxAxDDDADADxDBADCDAxBCxBCxADDCDADCDAADDCADCBCDCBBBACAAACBDACBAxxDAAxAADCCADxBAABAxAACxABDDAxDCDDxBBCBxDBDxCDxDCCCxACDABCCCADDCCDDBxABDBBADAxABAABxACDxCDCBDxBDxABADDACDCCCDCBACABACADDDAxADDBADBBBDCACAxACABxADDDxADDCAxCADADADxBCDDDxCDCCDCBABBBDCBBBxBCxDDxxxBCADAAABACCxABBCDCACBDBAxDBADCADxxBCDCBBBCBACADBCxCDBDCDADxABCDADABBCBCDBBADDBBxBCxBxCBAAxxAABACBDAADAxBxCCBBADxABDCBDCAAxBCDCBCDCABCBBxDCBCBxDBxCACAxAxCCBBBDBBxCDAAxABDDxxxxCBCBADCACDADCABCACBCCxxBxxBDCABDBCACDDBDCADDBxCDCCCBCDDADBDADCACBxxADDDAAxCAADACAADAAACCDDxDABACAxDxBBCCDxBADBBDDAACDCCAABCxDCDBBCCADDDAAADDDBBBCxBDDBCxAAABAACDABBxDxDCDxBxAABxABxCBBxDCCDDCABxBDCDCDDDBCACCDxDBAxxBBABDBxBBDCDCABACBABBACBxDDDBCCBDCDBxDDABAxDDCCBADAADxACDBACxBxCxDCBCBDBBBCBDAAACDABDCBCCxDCCADADCDBBCADBDCACCxBBDxBABBxCBADDBxCCBCCDCBBDCBAAAADCCCAADDACDCADDCCACCACBCABCADBCBBxBBDADADDABACDABAABCBBCBAAABACDCDCCDxCDDDAxBxDxDBBBDBxxBDBBxAxDDCBCBAxBBADCDxCCAACDABCxADDxDCBDAADCBBACCxCDBBCDBAACAABBABACACAAxBBBDAxxDDDCCADCCCCBDDBBBADxCAACCxBBDxDCABBDDxCAADDDAACBDAAAADDCBDxBBDDCCBABBxAxCBBBxCBCxBACDBCDABDDDBBADBCDDABCBBCCABBBBDxDBABxAxxBACADCBCAADAACAxBCxDxACADBADxBCDDDADAACCBxBCCBDxDBCACACBxBDACCDAABBAxADCACAxCBACBxDACDBxDBDBDBBBACDBDBDCBCCACCADDBACBCDCDCAAADxAxxBCDCBACBAAxxCABDBDxCBCADBCCDCDACDBCAADDDxBDDCCABBDxxxDAABxBCxBDADBDBDDAACAxBDCBDCADAACxDAxCCDACABADCCDCADBADBABCDxBCCDxBCACADABACDBCBAABxABABADCACBADxB
|
1
2024/day01_The_Battle_for_the_Farmlands/tests/challenge3
Normal file
1
2024/day01_The_Battle_for_the_Farmlands/tests/challenge3
Normal file
File diff suppressed because one or more lines are too long
1
2024/day01_The_Battle_for_the_Farmlands/tests/sample1
Normal file
1
2024/day01_The_Battle_for_the_Farmlands/tests/sample1
Normal file
|
@ -0,0 +1 @@
|
|||
ABBAC
|
1
2024/day01_The_Battle_for_the_Farmlands/tests/sample2
Normal file
1
2024/day01_The_Battle_for_the_Farmlands/tests/sample2
Normal file
|
@ -0,0 +1 @@
|
|||
AxBCDDCAxD
|
1
2024/day01_The_Battle_for_the_Farmlands/tests/sample3
Normal file
1
2024/day01_The_Battle_for_the_Farmlands/tests/sample3
Normal file
|
@ -0,0 +1 @@
|
|||
xBxAAABCDxCC
|
Loading…
Add table
Add a link
Reference in a new issue