Skip to content

Commit

Permalink
Day 9
Browse files Browse the repository at this point in the history
  • Loading branch information
UnderscoreTud committed Dec 9, 2024
1 parent 9959fc4 commit 07487b7
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 2 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
| [Day 5](./src/bin/05.rs) | `344.6µs` | `323.6µs` |
| [Day 6](./src/bin/06.rs) | `488.0µs` | `119.9ms` |
| [Day 7](./src/bin/07.rs) | `80.3µs` | `113.7µs` |
| [Day 8](./src/bin/08.rs) | `9.9µs` | `12.2µs` |
| [Day 8](./src/bin/08.rs) | `10.2µs` | `12.4µs` |
| [Day 9](./src/bin/09.rs) | `2.9ms` | `49.1ms` |

**Total: 123.92ms**
**Total: 175.92ms**
<!--- benchmarking table --->

---
Expand Down
1 change: 1 addition & 0 deletions data/examples/09.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2333133121414131402
132 changes: 132 additions & 0 deletions src/bin/09.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use std::ops::Range;
use itertools::Itertools;

advent_of_code::solution!(9);

#[derive(Debug)]
struct DiskMap<T> {
data: Vec<T>
}

impl DiskMap<Option<usize>> {
fn parse(input: &str) -> DiskMap<Option<usize>> {
let data = (&input.chars().chunks(2)).into_iter()
.enumerate()
.flat_map(|(id_number, mut chunk)| {
let Some(Some(file_size)) = chunk.next().map(|char| char.to_digit(10)) else { return Vec::new() };
let mut file = vec![Some(id_number); file_size as usize];
if let Some(Some(free_space)) = chunk.next().map(|char| char.to_digit(10)) {
file.append(&mut vec![None; free_space as usize]);
file
} else {
file
}
})
.collect();
DiskMap {
data
}
}

fn checksum(&self) -> u64 {
let len = self.data.len();
let mut sum = 0;
let (mut head, mut tail) = (1, len);
while head < tail {
let mut value = None;
if let Some(val) = self.data[head] {
value = Some(val);
} else {
while head < tail {
tail -= 1;
if let Some(val) = self.data[tail] {
value = Some(val);
break;
};
}
}
let Some(value) = value else { break };
sum += head * value;
head += 1;
}
sum as u64
}
}

#[derive(Default, Clone, Debug)]
struct Interval {
id: u64,
interval: Range<u32>,
}

impl DiskMap<Interval> {
fn parse_intervals(input: &str) -> DiskMap<Interval> {
let mut last_index = 0;
let data = (&input.chars().chunks(2)).into_iter()
.enumerate()
.map(|(id_number, mut chunk)| {
let Some(Some(file_size)) = chunk.next().map(|char| char.to_digit(10)) else { return Interval::default() };
let file = Interval {
id: id_number as u64,
interval: last_index..(last_index + file_size)
};
last_index = file.interval.end;
if let Some(Some(free_space)) = chunk.next().map(|char| char.to_digit(10)) {
last_index += free_space;
}
file
})
.collect_vec();
DiskMap {
data
}
}

fn checksum(&self) -> u64 {
let mut data = self.data.clone();
for index in (1..data.len()).rev() {
let interval = &self.data[index];
let actual_index = data.iter().rposition(|x| x.id == interval.id).unwrap();
let interval_size = interval.interval.end - interval.interval.start;
let Some((new_index, start_index, _)) = (0..actual_index)
.map(|index| (index, &data[index].interval, &data[index + 1].interval))
.map(|(index, x, y)| (index, x.end, y.start - x.end))
.find(|(_, _, size)| size >= &(interval_size)) else { continue };
let interval = Interval {
interval: start_index..(start_index + interval_size),
..*interval
};
data.remove(actual_index);
data.insert(new_index + 1, interval);
}
data.iter()
.map(|Interval { id, interval }| interval.clone().map(|x| id * (x as u64)).sum::<u64>())
.sum()
}
}

pub fn part_one(input: &str) -> Option<u64> {
Some(DiskMap::parse(input).checksum())
}

pub fn part_two(input: &str) -> Option<u64> {
let disk_map = DiskMap::parse_intervals(input);
Some(disk_map.checksum())
}

#[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(1928));
}

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

0 comments on commit 07487b7

Please sign in to comment.