Compare commits

..

4 Commits

Author SHA1 Message Date
8b4524912f day 7 2023-12-18 18:07:22 +01:00
6334f8f0a8 day 6 format fix 2023-12-13 16:11:13 +01:00
691b44d1e9 day 6 2023-12-13 16:10:14 +01:00
7e0d58a8ea day 5 part 2 2023-12-12 17:24:51 +01:00
7 changed files with 1305 additions and 2 deletions

2
input/6.txt Normal file
View File

@@ -0,0 +1,2 @@
Time: 62 64 91 90
Distance: 553 1010 1473 1074

1000
input/7.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,10 @@
use std::{fs::File, io::{BufReader, BufRead}}; use std::{
fs::File,
io::{BufRead, BufReader},
str::FromStr,
};
use regex::Regex;
pub fn load_input(filepath: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> { pub fn load_input(filepath: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let file = File::open(filepath)?; let file = File::open(filepath)?;
@@ -13,4 +18,17 @@ pub fn load_input(filepath: &str) -> Result<Vec<String>, Box<dyn std::error::Err
} }
Ok(result) Ok(result)
} }
pub fn parse_nums<T>(s: &str) -> Vec<T>
where
T: FromStr,
{
let regex = Regex::new(r"(?m)(\d+)").unwrap();
let result = regex.captures_iter(s);
result
.map(|e| e.get(0).unwrap().as_str())
.flat_map(|e| e.parse::<T>())
.collect()
}

View File

@@ -92,6 +92,36 @@ fn seed_to_location(maps: &Vec<TranslationMap>, num: u64) -> u64 {
return result; return result;
} }
fn pair_seeds(seeds: &[u64]) -> Vec<(u64, u64)> {
let mut output: Vec<(u64, u64)> = Vec::new();
for i in 0..seeds.len() {
if i % 2 == 1{
continue;
}
output.push((seeds[i],seeds[i+1]));
}
return output;
}
pub fn run_part2() -> Result<i32, Box<dyn std::error::Error>> {
let lines = load_input("./input/5.txt")?;
let seeds = get_seeds(lines.get(0).unwrap().as_str());
let maps = parse_input(&lines[1..]);
let pairs = pair_seeds(&seeds);
let res = pairs
.iter()
.flat_map(|e| e.0..(e.0 + e.1))
.map(|e| seed_to_location(&maps, e))
.min()
.unwrap();
Ok(res.try_into().unwrap())
}
pub fn run() -> Result<i32, Box<dyn std::error::Error>> { pub fn run() -> Result<i32, Box<dyn std::error::Error>> {
let lines = load_input("./input/5.txt")?; let lines = load_input("./input/5.txt")?;
let seeds = get_seeds(lines.get(0).unwrap().as_str()); let seeds = get_seeds(lines.get(0).unwrap().as_str());

View File

@@ -6,6 +6,8 @@ mod two;
mod three; mod three;
mod four; mod four;
mod five; mod five;
mod six;
mod seven;
fn main() { fn main() {
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
@@ -21,6 +23,10 @@ fn main() {
"4" => four::run(), "4" => four::run(),
"4p2" => four::run_part2(), "4p2" => four::run_part2(),
"5" => five::run(), "5" => five::run(),
"5p2" => five::run_part2(),
"6" => six::run(),
"6p2" => six::run_part2(),
"7" => seven::run(),
_ => Ok(-1), _ => Ok(-1),
}; };

194
src/seven.rs Normal file
View File

@@ -0,0 +1,194 @@
use std::{cmp::Ordering, collections::HashMap};
use crate::common::load_input;
//
// Card
//
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Copy, Clone, Debug)]
enum Card {
A = 14,
K = 13,
Q = 12,
J = 11,
T = 10,
N9 = 9,
N8 = 8,
N7 = 7,
N6 = 6,
N5 = 5,
N4 = 4,
N3 = 3,
N2 = 2,
}
impl TryFrom<char> for Card {
type Error = &'static str;
fn try_from(value: char) -> Result<Self, Self::Error> {
match value {
'A' => Ok(Card::A),
'K' => Ok(Card::K),
'Q' => Ok(Card::Q),
'J' => Ok(Card::J),
'T' => Ok(Card::T),
'9' => Ok(Card::N9),
'8' => Ok(Card::N8),
'7' => Ok(Card::N7),
'6' => Ok(Card::N6),
'5' => Ok(Card::N5),
'4' => Ok(Card::N4),
'3' => Ok(Card::N3),
'2' => Ok(Card::N2),
_ => Err("Not a card"),
}
}
}
//
// Hand Value
//
#[derive(PartialEq, PartialOrd, Ord,Eq, Hash, Copy, Clone, Debug)]
enum HandValue {
FiveOfKind = 6,
FourOfKind = 5,
FullHouse = 4,
ThreeOfKind = 3,
TwoPair = 2,
OnePair = 1,
HighCard = 0,
}
//
// Hand
//
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
struct Hand {
cards: [Card; 5],
}
impl TryFrom<&str> for Hand {
type Error = &'static str;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let cards: Vec<_> = value.chars().map(|e| Card::try_from(e)).collect();
if !cards.iter().all(|e| e.is_ok()) {
return Err("Invalid char");
}
if cards.iter().count() != 5 {
return Err("To many cards");
}
let arr: [Card; 5] = [
cards.get(0).unwrap().unwrap(),
cards.get(1).unwrap().unwrap(),
cards.get(2).unwrap().unwrap(),
cards.get(3).unwrap().unwrap(),
cards.get(4).unwrap().unwrap(),
];
return Ok(Hand { cards: arr });
}
}
impl Hand {
fn get_hand_value(&self) -> HandValue {
let groups = self.get_card_cout();
// Check Five of a kind
if groups.iter().any(|e| *e.1 == 5) {
return HandValue::FiveOfKind;
}
// Check for Four of a kind
if groups.iter().any(|e| *e.1 == 4) {
return HandValue::FourOfKind;
}
//Check full house
if groups.iter().any(|e| *e.1 == 3) && groups.iter().any(|e| *e.1 == 2) {
return HandValue::FullHouse;
}
// Check for Three of a kind
if groups.iter().any(|e| *e.1 == 3) {
return HandValue::ThreeOfKind;
}
// Check for 1 and 2 Pairs
let pairs = groups.iter().filter(|e| *e.1 == 2).count();
if pairs == 2 {
return HandValue::TwoPair;
}
if pairs == 1 {
return HandValue::OnePair;
}
return HandValue::HighCard;
}
fn get_card_cout(&self) -> HashMap<Card, u8> {
let mut rtn = HashMap::new();
self.cards.iter().for_each(|e| {
match rtn.get(e) {
None => rtn.insert(*e, 1u8),
Some(v) => rtn.insert(*e, v + 1u8),
};
});
return rtn;
}
}
impl PartialOrd for Hand {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(&other))
}
}
impl Ord for Hand {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let self_hand_value = self.get_hand_value();
let other_hand_value = other.get_hand_value();
if self_hand_value != other_hand_value {
return self_hand_value.cmp(&other_hand_value);
}
// Compare the cards
for (self_card, other_card) in self.cards.iter().zip(other.cards.iter()) {
if self_card != other_card {
return self_card.cmp(other_card);
}
}
return Ordering::Equal;
}
}
//
// Everything else
//
fn parse_input(lines: &[String]) -> Vec<(Hand, u64)> {
lines
.iter()
.map(|e| e.split_once(" ").unwrap())
.map(|e| (Hand::try_from(e.0).unwrap(), e.1.parse::<u64>().unwrap()))
.collect()
}
pub fn run() -> Result<i32, Box<dyn std::error::Error>> {
let lines = load_input("./input/7.txt")?;
let hands = parse_input(&lines);
let mut orderd_hands = hands.clone();
orderd_hands.sort_by_key(|e| e.0);
let score: u64 = orderd_hands.iter().enumerate().map(|e| (e.0 + 1) as u64 * (e.1.1)).sum();
Ok(score as i32)
}

53
src/six.rs Normal file
View File

@@ -0,0 +1,53 @@
use crate::common::{load_input, parse_nums};
fn parse_input(lines: &[String]) -> (Vec<u64>, Vec<u64>) {
(
parse_nums(lines.get(0).unwrap()),
parse_nums(lines.get(1).unwrap()),
)
}
fn distance_by_time_pressed(time_pressed: u64, race_time: u64) -> u64 {
(race_time - time_pressed) * time_pressed
}
fn join_nums(nums: &[u64]) -> u64 {
nums.iter()
.map(|e| e.to_string())
.collect::<String>()
.parse()
.unwrap()
}
pub fn run_part2() -> Result<i32, Box<dyn std::error::Error>> {
let lines = load_input("./input/6.txt")?;
let (time, distance) = parse_input(&lines);
let new_time = join_nums(&time);
let new_dist = join_nums(&distance);
let res = (0..new_time)
.map(|pressed| distance_by_time_pressed(pressed, new_time))
.filter(|e| *e > new_dist)
.count();
Ok(res.try_into().unwrap())
}
pub fn run() -> Result<i32, Box<dyn std::error::Error>> {
let lines = load_input("./input/6.txt")?;
let (time, distance) = parse_input(&lines);
let res = time
.iter()
.zip(distance.iter())
.map(|e| {
(0..*e.0)
.map(|pressed| distance_by_time_pressed(pressed, *e.0))
.filter(|dist| *dist > *e.1)
.count()
})
.reduce(|acc, e| e * acc)
.unwrap();
Ok(res.try_into().unwrap())
}