Skip to content
This repository has been archived by the owner on Aug 1, 2024. It is now read-only.

Commit

Permalink
day 7
Browse files Browse the repository at this point in the history
  • Loading branch information
jpyamamoto committed Dec 17, 2023
1 parent b3220a3 commit 31c5579
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 3 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ tinyjson = "2.5.1"

# Solution dependencies
rayon = "1.8.0"
itertools = "0.12.0"
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<img src="./.assets/christmas_ferris.png" width="164">

<<<<<<< HEAD
# 🎄 Advent of Code 2023

Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.rust-lang.org/).
Expand All @@ -27,10 +26,11 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
| [Day 2](./src/bin/02.rs) | `107.7µs` | `108.3µs` |
| [Day 3](./src/bin/03.rs) | `115.2µs` | `113.3µs` |
| [Day 4](./src/bin/04.rs) | `255.7µs` | `257.4µs` |
| [Day 5](./src/bin/05.rs) | `45.7µs` | `44.6s` |
| [Day 5](./src/bin/05.rs) | `45.7µs` | `44600000000.0µs` |
| [Day 6](./src/bin/06.rs) | `375.0ns` | `240.0ns` |
| [Day 7](./src/bin/07.rs) | `5.8ms` | `5.3ms` |

**Total: 2.28ms**
**Total: 44613.38ms**
<!--- benchmarking table --->

---
Expand Down
174 changes: 174 additions & 0 deletions src/bin/07.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
use std::{str::FromStr, cmp::Ordering, iter::zip};
use itertools::Itertools;

advent_of_code::solution!(7);

const JOKER: &char = &'X';
const CARDS: &'static [char] = &[*JOKER, '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'];

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Card {
id: char
}

#[derive(Debug, PartialEq, Eq)]
struct Hand {
cards: [Card; 5],
bid: u32
}

#[derive(Debug, PartialEq, Eq)]
struct ParseCardError;

#[derive(Debug, PartialEq, Eq)]
struct ParseHandError;

impl TryInto<Card> for char {
type Error = ParseCardError;

fn try_into(self) -> Result<Card, Self::Error> {
if CARDS.contains(&self) {
Ok(Card { id: self })
} else {
Err(ParseCardError)
}
}
}

impl PartialOrd for Card {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Card {
fn cmp(&self, other: &Self) -> Ordering {
let index_self = CARDS.iter().position(|&x| x == self.id);
let index_other = CARDS.iter().position(|&x| x == other.id);

index_self.cmp(&index_other)
}
}

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) -> Ordering {
let index_self = self.rank_type();
let index_other = other.rank_type();

if index_self != index_other {
return index_self.cmp(&index_other);
}

for (x, y) in zip(self.cards, other.cards) {
if x == y {
continue;
} else {
return x.cmp(&y);
}
};

Ordering::Equal
}
}

impl FromStr for Hand {
type Err = ParseHandError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = s.split_ascii_whitespace().collect();
let bid: u32 = parts[1].parse().map_err(|_| ParseHandError)?;

if parts[0].len() == 5 {
let mut cards: [Card; 5] = [Card { id: 'A' }; 5];

for (i, c) in parts[0].chars().enumerate() {
cards[i] = c.try_into().unwrap();
};

Ok(Hand { cards, bid })
} else {
Err(ParseHandError)
}
}
}

impl Hand {
fn rank_type(&self) -> u32 {
let jokers: usize = self.cards.into_iter().filter(|c| c.id == *JOKER).count();

let mut groups: Vec<usize> = self.cards
.into_iter()
.filter(|c| c.id != *JOKER)
.into_group_map_by(|c| c.id)
.into_iter()
.map(|(_, v)| v.len())
.sorted()
.collect();

if groups.is_empty() {
groups.push(jokers);
} else {
let i = groups.len();
groups[i-1] += jokers;
}

match groups[..] {
[5] => 6,
[1, 4] => 5,
[2, 3] => 4,
[1, 1, 3] => 3,
[1, 2, 2] => 2,
[1, 1, 1, 2] => 1,
_ => 0
}
}
}

fn parse(input: &str) -> Vec<Hand> {
input.lines().map(|l| l.parse().unwrap()).collect()
}

pub fn part_one(input: &str) -> Option<u32> {
let mut data: Vec<Hand> = parse(input);
data.sort();

data.iter()
.enumerate()
.map(|(i, h)| h.bid * (i as u32 + 1))
.sum::<u32>()
.into()
}

pub fn part_two(input: &str) -> Option<u32> {
let mut data: Vec<Hand> = parse(&input.replace("J", &JOKER.to_string()));
data.sort();

data.iter()
.enumerate()
.map(|(i, h)| h.bid * (i as u32 + 1))
.sum::<u32>()
.into()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(6440));
}

#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, Some(5905));
}
}

0 comments on commit 31c5579

Please sign in to comment.