The first part was simple enough. Adding in the 3 remaining tilt methods for star 2 was also simple enough, and worked just how I figured it would. Tried the brute force solution first, but realized it was going to take a ridiculous amount of time and went back to figure out an algorithm. It was simple enough to guess that it would hit a point where it just repeats infinitely, but actually coding out the math to extrapolate that took way more time than I want to admit. Not sure why I struggled with it so much, but after some pen and paper mathing, I essentially got there. Ended up having to subract 1
from this calculation, and either I'm just missing something or am way too tired, because I don't know why it's one less than what I thought it would be, but it works so who am I to complain.
https://github.com/capitalpb/advent_of_code_2023/blob/main/src/solvers/day14.rs
use crate::Solver;
#[derive(Debug)]
struct PlatformMap {
tiles: Vec>,
}
impl PlatformMap {
fn from(input: &str) -> PlatformMap {
PlatformMap {
tiles: input.lines().map(|line| line.chars().collect()).collect(),
}
}
fn load(&self) -> usize {
self.tiles
.iter()
.enumerate()
.map(|(row, tiles)| {
tiles.iter().filter(|tile| *tile == &'O').count() * (self.tiles.len() - row)
})
.sum()
}
fn tilt_north(&mut self) {
for row in 1..self.tiles.len() {
for col in 0..self.tiles[0].len() {
if self.tiles[row][col] != 'O' {
continue;
}
let mut new_row = row;
for check_row in (0..row).rev() {
if self.tiles[check_row][col] == '.' {
new_row = check_row;
} else {
break;
}
}
self.tiles[row][col] = '.';
self.tiles[new_row][col] = 'O';
}
}
}
fn tilt_west(&mut self) {
for col in 1..self.tiles[0].len() {
for row in 0..self.tiles.len() {
if self.tiles[row][col] != 'O' {
continue;
}
let mut new_col = col;
for check_col in (0..col).rev() {
if self.tiles[row][check_col] == '.' {
new_col = check_col;
} else {
break;
}
}
self.tiles[row][col] = '.';
self.tiles[row][new_col] = 'O';
}
}
}
fn tilt_south(&mut self) {
for row in (0..(self.tiles.len() - 1)).rev() {
for col in 0..self.tiles[0].len() {
if self.tiles[row][col] != 'O' {
continue;
}
let mut new_row = row;
for check_row in (row + 1)..self.tiles.len() {
if self.tiles[check_row][col] == '.' {
new_row = check_row;
} else {
break;
}
}
self.tiles[row][col] = '.';
self.tiles[new_row][col] = 'O';
}
}
}
fn tilt_east(&mut self) {
for col in (0..(self.tiles[0].len() - 1)).rev() {
for row in 0..self.tiles.len() {
if self.tiles[row][col] != 'O' {
continue;
}
let mut new_col = col;
for check_col in (col + 1)..self.tiles[0].len() {
if self.tiles[row][check_col] == '.' {
new_col = check_col;
} else {
break;
}
}
self.tiles[row][col] = '.';
self.tiles[row][new_col] = 'O';
}
}
}
}
pub struct Day14;
impl Solver for Day14 {
fn star_one(&self, input: &str) -> String {
let mut platform_map = PlatformMap::from(input);
platform_map.tilt_north();
platform_map.load().to_string()
}
fn star_two(&self, input: &str) -> String {
let mut platform_map = PlatformMap::from(input);
let mut map_history: Vec>> = vec![];
for index in 0..1_000_000_000 {
platform_map.tilt_north();
platform_map.tilt_west();
platform_map.tilt_south();
platform_map.tilt_east();
if let Some(repeat_start) = map_history
.iter()
.position(|tiles| tiles == &platform_map.tiles)
{
let repeat_length = index - repeat_start;
let delta = (1_000_000_000 - repeat_start) % repeat_length;
let solution_index = repeat_start + delta - 1;
return PlatformMap {
tiles: map_history[solution_index].clone(),
}
.load()
.to_string();
}
map_history.push(platform_map.tiles.clone());
}
platform_map.load().to_string()
}
}
I've had the damn song stuck in my head since I saw this post.