Compare commits
4 Commits
f0c1f6aa9f
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
8b4524912f
|
|||
|
6334f8f0a8
|
|||
|
691b44d1e9
|
|||
|
7e0d58a8ea
|
2
input/6.txt
Normal file
2
input/6.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Time: 62 64 91 90
|
||||||
|
Distance: 553 1010 1473 1074
|
||||||
1000
input/7.txt
Normal file
1000
input/7.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||||
|
}
|
||||||
|
|||||||
30
src/five.rs
30
src/five.rs
@@ -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());
|
||||||
|
|||||||
@@ -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
194
src/seven.rs
Normal 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
53
src/six.rs
Normal 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())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user