Add 2024 Quest 1

This commit is contained in:
Chris Alge 2024-11-08 14:25:41 +01:00
parent 8a49bcb900
commit 097a98f919
10 changed files with 152 additions and 0 deletions

View file

@ -0,0 +1 @@
/target

View file

@ -0,0 +1,6 @@
[package]
name = "day01_the_battle_for_the_farmlands"
version = "0.1.0"
edition = "2021"
[dependencies]

View 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?

View 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]));
}
}
}

View file

@ -0,0 +1 @@
CBCCACCBCCCBBBBCBBCBAABABABBABCBCCABBAAABCABABCBBAACBCCBACAABBAABACCBCAABCCACCCABABCCCCCBBAACACABAAABCCCACAABAAAACCABCAABCACBCBBABCABBCBBCBABACBAABCBBACBABBBBACCACACABCBCBABCBABABBACCCBCBBABCACAACBCAAAACBCCCCBBACCCCACABABACBAABCBCBBBCBAACBCBAAABBBABBABBACBAABCBABCCACAAACBBABAACBCBCCBBCCCACBBCAACBBCBAABBBBBBCCBBCAABBCCCBACCBCBCCBAAAABBCABBABCCBBAAAAAAAABAAAAAAACBACBAAABBBCCCCABCABBBCBACCACABBBCABCBAABBBCCACCCBBAABCBCBABCCCCBCBBBCACBAABCAABCAAAABACACBBAAABBCBBBACBBABCBBACAABABACABCBBBBCBABACBBACCCCAAAABACBAACBCAACCCBCCCBCBCAABCCAAAABBBBBBCCBBAABAABBBBBAACCCCCAABABABCACAABBBACBBBACACACAAABABBACCACBBCACCBCABCCCCCBBCAABCBCABACCBCAABCBCCABACBBABBACABBBACABBBBBBBACACCCBACCCBAACCCAABABBCBBCBBBABCACCBABBBBBBACCCABCABABCCCBBBBAACABBBBBCACCCCACAAAAACACBAAAAAABABBBCCCBACCBAACACBCAACBBCAABACCCABCAACACCCBABCCCAABCCBCABABCBCCCBCCAAACBBCBACCACCAACBABAAABACABBAAACBCCABBABCBCCCBABCCBCBBABBAACACACBAACACBBBBCBCAACCBCCABBAACAACBBBABCABABABAAABBBCBACACAABBBACBCCBCCAAABCABABBCBCBCACBCACCBCABBBBABACBBACCBBAAA

View file

@ -0,0 +1 @@
BBBBBDAACAAABAxCABDBDDCBxCACxAADADCAABACCxDCCBDACBCxDACDADACCCxAxBDACBBACxDDABCAADAxABABAADBACCBBBACAACCDCBCDDBDBDDCADBACCCACAxCDAxDCCABBDDDCCDCCCCDCDABADAABADACACCBBDBxBCCBCBBABDAACAACACCxxDAxDCCBCDDBxAADADBBDBADBCCDBABCAAABDDxDxxDDBACCACADCCBDxCABxBCBABxDCABDCDADxxxBBBABBDCCACABxDDBACxBCCCCBAxBCxBADBAAAADCDxBCxAxxCDCBxBDAxBABDxBBCBCCxCBABBDDCDACCDABABDDABCACxDxAACDCBBADCBBDDCCDAAxBxCABCDCADxxCDDCxBDCCDCBDACCCABCDxADBxBDAACCDCBCBCCDxCAxCBAABAAxDxxCDADACDCAACCDCDABxCDCAABCBACABABDDxAABAxBADABADAxCBACCACxDxAADABCBBACDCAABCDBBDBACAAACCBDBBAxBDBBBBBDDBCCBCDCDCDCABDBDBCDxCxABDDCDDCADDCACDCBBCADBCDBxBAADCDAADBxCDDDBCACBCDACCDDxCDDCCDBxACBCBAAxAxDDDADADxDBADCDAxBCxBCxADDCDADCDAADDCADCBCDCBBBACAAACBDACBAxxDAAxAADCCADxBAABAxAACxABDDAxDCDDxBBCBxDBDxCDxDCCCxACDABCCCADDCCDDBxABDBBADAxABAABxACDxCDCBDxBDxABADDACDCCCDCBACABACADDDAxADDBADBBBDCACAxACABxADDDxADDCAxCADADADxBCDDDxCDCCDCBABBBDCBBBxBCxDDxxxBCADAAABACCxABBCDCACBDBAxDBADCADxxBCDCBBBCBACADBCxCDBDCDADxABCDADABBCBCDBBADDBBxBCxBxCBAAxxAABACBDAADAxBxCCBBADxABDCBDCAAxBCDCBCDCABCBBxDCBCBxDBxCACAxAxCCBBBDBBxCDAAxABDDxxxxCBCBADCACDADCABCACBCCxxBxxBDCABDBCACDDBDCADDBxCDCCCBCDDADBDADCACBxxADDDAAxCAADACAADAAACCDDxDABACAxDxBBCCDxBADBBDDAACDCCAABCxDCDBBCCADDDAAADDDBBBCxBDDBCxAAABAACDABBxDxDCDxBxAABxABxCBBxDCCDDCABxBDCDCDDDBCACCDxDBAxxBBABDBxBBDCDCABACBABBACBxDDDBCCBDCDBxDDABAxDDCCBADAADxACDBACxBxCxDCBCBDBBBCBDAAACDABDCBCCxDCCADADCDBBCADBDCACCxBBDxBABBxCBADDBxCCBCCDCBBDCBAAAADCCCAADDACDCADDCCACCACBCABCADBCBBxBBDADADDABACDABAABCBBCBAAABACDCDCCDxCDDDAxBxDxDBBBDBxxBDBBxAxDDCBCBAxBBADCDxCCAACDABCxADDxDCBDAADCBBACCxCDBBCDBAACAABBABACACAAxBBBDAxxDDDCCADCCCCBDDBBBADxCAACCxBBDxDCABBDDxCAADDDAACBDAAAADDCBDxBBDDCCBABBxAxCBBBxCBCxBACDBCDABDDDBBADBCDDABCBBCCABBBBDxDBABxAxxBACADCBCAADAACAxBCxDxACADBADxBCDDDADAACCBxBCCBDxDBCACACBxBDACCDAABBAxADCACAxCBACBxDACDBxDBDBDBBBACDBDBDCBCCACCADDBACBCDCDCAAADxAxxBCDCBACBAAxxCABDBDxCBCADBCCDCDACDBCAADDDxBDDCCABBDxxxDAABxBCxBDADBDBDDAACAxBDCBDCADAACxDAxCCDACABADCCDCADBADBABCDxBCCDxBCACADABACDBCBAABxABABADCACBADxB

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
ABBAC

View file

@ -0,0 +1 @@
AxBCDDCAxD

View file

@ -0,0 +1 @@
xBxAAABCDxCC