Skip to content

Instantly share code, notes, and snippets.

@Dronakurl
Created December 18, 2023 10:08
Show Gist options
  • Save Dronakurl/62dc514efdeff6fd3ce085fd2fdb5e56 to your computer and use it in GitHub Desktop.
Save Dronakurl/62dc514efdeff6fd3ce085fd2fdb5e56 to your computer and use it in GitHub Desktop.
day16
#![allow(dead_code)]
use crate::printgrid::{printgrid, GridElement};
use crate::read_file::read_file;
use array2d::Array2D;
use log::*;
use std::env;
use std::time::Instant;
mod printgrid;
mod read_file;
#[derive(Clone, Debug, PartialEq)]
struct Beam {
cur: (usize, usize),
dir: (i8, i8),
}
impl Beam {
fn new(row: usize, col: usize, dir: (i8, i8)) -> Beam {
Beam {
cur: (row, col),
dir,
}
}
fn is_in_hist(hist: &Vec<Beam>, row: usize, col: usize, dir: (i8, i8)) -> bool {
hist.contains(&Beam {
cur: (row, col),
dir,
})
}
fn walk(&mut self, grid: &mut Array2D<GridElement>, hist: &mut Vec<Beam>) {
debug!("dir={:?} cur={:?}", self.dir, self.cur);
let (row, col) = (self.cur.0 as usize, self.cur.1 as usize);
let ce: &mut GridElement;
match grid.get_mut(row, col) {
None => {
return;
}
Some(fe) => {
ce = fe;
}
}
ce.energized = true;
match ce.typ {
'/' => {
self.dir = match self.dir {
(1, 0) => (0, -1),
(-1, 0) => (0, 1),
(0, 1) => (-1, 0),
(0, -1) => (1, 0),
_ => self.dir,
}
}
'\\' => {
self.dir = match self.dir {
(1, 0) => (0, 1),
(-1, 0) => (0, -1),
(0, 1) => (1, 0),
(0, -1) => (-1, 0),
_ => self.dir,
}
}
'|' => {
self.dir = match self.dir {
(0, 1) | (0, -1) => {
let mut b = Beam {
cur: (ce.row, ce.col),
dir: (-1, 0),
};
// debug!("| cur={:?} dir={:?} {:?} hit me ", self.cur, self.dir, &b);
b.walk(grid, hist);
(1, 0)
}
_ => self.dir,
}
}
'-' => {
self.dir = match self.dir {
(1, 0) | (-1, 0) => {
let mut b = Beam {
cur: (ce.row, ce.col),
dir: (0, 1),
};
// debug!("- cur={:?} dir={:?} {:?} hit me ", self.cur, self.dir, &b);
b.walk(grid, hist);
(0, -1)
}
_ => self.dir,
}
}
_ => self.dir = self.dir,
}
if let Some(nextgridele) = match self.dir {
(-1, 0) if row >= 1 => grid.get(row - 1, col),
(1, 0) => grid.get(row + 1, col),
(0, -1) if col >= 1 => grid.get(row, col - 1),
(0, 1) => grid.get(row, col + 1),
_ => None,
} {
self.cur = (nextgridele.row, nextgridele.col);
}
if Beam::is_in_hist(hist, self.cur.0, self.cur.1, self.dir) {
// debug!("{:?}", self);
// debug!("{:?}", hist);
return;
}
hist.push(self.clone());
self.walk(grid, hist);
}
}
fn count_energized(grid: &Array2D<GridElement>) -> i32 {
let mut total: i32 = 0;
for ge in grid.elements_row_major_iter() {
if ge.energized {
total += 1;
}
}
total
}
fn reset_energized(grid: &mut Array2D<GridElement>) {
for (x, y) in grid.indices_row_major() {
if let Some(element) = grid.get_mut(x, y) {
if element.energized {
element.energized = false;
}
}
}
}
fn main() {
env_logger::init();
let start = Instant::now();
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
println!("Usage: {} <filename>", args[0]);
return;
}
let inputtxt;
match read_file(&args[1]) {
Ok(contents) => {
inputtxt = contents;
}
Err(e) => {
println!("Error reading file: {}", e);
std::process::exit(1);
}
}
let lines: Vec<&str> = inputtxt.lines().collect();
let hei = lines.len();
let wid = lines.first().map_or(0, |line| line.len());
let mut grid: Array2D<GridElement> =
Array2D::filled_with(GridElement::new(0, 0, '.'), hei, wid);
for (row, line) in inputtxt.lines().enumerate() {
for (col, c) in line.chars().enumerate() {
if let Some(ge) = grid.get_mut(row, col) {
ge.row = row;
ge.col = col;
ge.typ = c;
}
}
}
let mut b = Beam {
cur: (0, 0),
dir: (0, 1),
};
let mut hist: Vec<Beam> = Vec::new();
b.walk(&mut grid, &mut hist);
printgrid(&grid);
println!("part 1: {}", count_energized(&grid));
println!("time elapsed: {:?}", start.elapsed());
let mut edges: Vec<Beam> = Vec::new();
for col in 0..wid {
edges.push(Beam {
cur: (0, col),
dir: (1, 0),
});
edges.push(Beam {
cur: (hei - 1, col),
dir: (-1, 0),
});
}
edges.push(Beam {
cur: (0, 0),
dir: (0, 1),
});
edges.push(Beam {
cur: (hei - 1, 0),
dir: (0, 1),
});
edges.push(Beam {
cur: (0, wid - 1),
dir: (0, -1),
});
edges.push(Beam {
cur: (hei - 1, wid - 1),
dir: (0, -1),
});
for row in 0..hei {
edges.push(Beam {
cur: (row, 0),
dir: (0, 1),
});
edges.push(Beam {
cur: (row, wid - 1),
dir: (0, -1),
});
}
let mut max = 0_i32;
for edge in edges.iter_mut() {
reset_energized(&mut grid);
let mut hist: Vec<Beam> = Vec::new();
edge.walk(&mut grid, &mut hist);
let cnt = count_energized(&grid);
info!("{:?} {}", edge, cnt);
if cnt > max {
max = cnt;
}
}
println!("part 2 = {}", max);
println!("time elapsed: {:?}", start.elapsed());
}
#[cfg(test)]
mod test;
use array2d::Array2D;
use log::{log_enabled, Level};
/// typ="/", ".", "-", "|", "\"
#[derive(Clone)]
pub struct GridElement {
pub col: usize,
pub row: usize,
pub typ: char,
pub energized: bool,
}
impl GridElement {
pub fn new(col: usize, row: usize, typ: char) -> GridElement {
GridElement {
col,
row,
typ,
energized: false,
}
}
}
pub fn printgrid(grid: &Array2D<GridElement>) {
if !log_enabled!(Level::Debug) {
return;
}
print!(" ");
for i in 0..grid.column_len() {
print!("{}", i);
}
println!();
for (n, row) in grid.rows_iter().enumerate() {
print!("{} ", n);
for element in row {
print!("{}", element.typ);
}
println!();
}
println!("---------------------------------");
print!(" ");
for i in 0..grid.column_len() {
print!("{}", i);
}
println!();
for (n, row) in grid.rows_iter().enumerate() {
print!("{} ", n);
for element in row {
if element.energized {
print!("#");
} else {
print!(".");
}
}
println!();
}
}
use std::fs::File;
use std::io::prelude::*;
pub fn read_file(file_name: &str) -> std::io::Result<String> {
let mut file = File::open(file_name)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
use super::*;
#[test]
fn test_isin() {
assert!(true);
let b = Beam {
dir: (-1, 0),
cur: (23, 12),
};
println!("{:?}", &b);
let hist = vec![b];
println!("{:?}", &hist);
assert!(Beam::is_in_hist(&hist, 23, 12, (-1, 0)));
}
#[test]
fn test_notin() {
let b = Beam {
dir: (-1, 0),
cur: (23, 12),
};
println!("{:?}", &b);
let hist = vec![b];
println!("{:?}", &hist);
assert!(!Beam::is_in_hist(&hist, 3, 12, (-1, 0)));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment