Update readmes and day8

master
Alex Selimov 11 hours ago
parent cc49d8009d
commit c5de45d22a

@ -13,3 +13,4 @@ Below are a list of the programming languages used to solve each day:
- Day 5 - Python
- Day 6 - Rust
- Day 7 - Python
- Day 8 - Rust

@ -1,4 +1,4 @@
# Day 4
# Day 5
## Instructions

@ -0,0 +1,12 @@
# Day 6
## Instructions
From the root directory of the crate (where this README is) just execute:
```
cargo run
```
The solution will be printed to the terminal output.

@ -0,0 +1,16 @@
# Day 7
## Instructions
From the root directory of the crate (where this README is) just execute:
```
cargo run
```
The solution will be printed to the terminal output.
## Notes
Was unable to get to part 2. Hopefully will be able to revisit this.

@ -0,0 +1,7 @@
[package]
name = "day8"
version = "0.1.0"
edition = "2021"
[dependencies]
itertools = "*"

@ -0,0 +1,12 @@
# Day 8
## Instructions
From the root directory of the crate (where this README is) just execute:
```
cargo run
```
The solution will be printed to the terminal output.

@ -0,0 +1,220 @@
use std::{
collections::{HashMap, HashSet},
error::Error,
fmt::Display,
fs::File,
io::{BufRead, BufReader},
rc::Rc,
};
use itertools::Itertools;
/// Basic error type
#[derive(Debug)]
enum ParsingError {
ParserFailure,
IndexOutOfBounds,
InconsistentGrid,
}
impl Display for ParsingError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParsingError::ParserFailure => write!(f, "Failed to parse segment"),
ParsingError::IndexOutOfBounds => write!(f, "Index out of bounds for CharGrid"),
ParsingError::InconsistentGrid => write!(f, "File is not a consistent char grid"),
}
}
}
type MyResult<T> = Result<T, Box<dyn Error>>;
impl Error for ParsingError {}
/// Struct that flattens out the input grid
#[derive(Clone)]
pub struct CharGrid {
pub chars: Vec<char>,
pub m: usize,
pub n: usize,
pub same_freq_positions: Vec<Vec<usize>>,
}
impl CharGrid {
/// Take a file and split it into a CharGrid. Since input has only ASCII characters this should
/// be fine
pub fn new(input_file: &str) -> MyResult<CharGrid> {
let file = File::open(input_file)?;
let reader = BufReader::new(file);
let mut m = 0;
let mut n: Option<usize> = None;
let chars: Vec<char> = reader
.lines()
.map(|line| -> MyResult<Vec<char>> {
let parsed_line = Vec::from_iter(line?.chars());
m += 1;
if n.is_none() {
n = Some(parsed_line.len());
} else if n.unwrap() != parsed_line.len() {
return Err(Box::new(ParsingError::InconsistentGrid));
}
Ok(parsed_line)
})
.collect::<MyResult<Vec<Vec<char>>>>()?
.into_iter()
.flatten()
.collect();
let n = n.unwrap();
// Now loop and get all the unique indices
let mut char_indices: HashMap<char, usize> = HashMap::new();
let mut curr_idx = 0;
let mut same_freq_positions: Vec<Vec<usize>> = Vec::new();
for (i, c) in chars.iter().enumerate() {
if *c != '.' {
let idx = match char_indices.get(c) {
Some(idx) => idx,
None => {
char_indices.insert(*c, curr_idx);
curr_idx += 1;
same_freq_positions.push(vec![]);
&(curr_idx - 1)
}
};
same_freq_positions[*idx].push(i);
}
}
Ok(CharGrid {
chars,
m,
n,
same_freq_positions,
})
}
/// Get an index within the grid
pub fn get(&self, i: i32, j: i32) -> MyResult<char> {
let idx = self.two2one_index(i, j)?;
Ok(self.chars[idx])
}
// Convert the one dimensional index to two dimensional index
pub fn one2two_index(&self, idx: usize) -> (usize, usize) {
let i = idx / self.n;
let j = idx % self.n;
(i, j)
}
// Convert the two dimensional index to one dimensional index
pub fn two2one_index(&self, i: i32, j: i32) -> MyResult<usize> {
if i < 0 || j < 0 {
Err(Box::new(ParsingError::IndexOutOfBounds))
} else if i as usize >= self.m || j as usize >= self.n {
Err(Box::new(ParsingError::IndexOutOfBounds))
} else {
Ok((i as usize) * self.n + (j as usize))
}
}
}
/// Get the antinodes for a single frequency assuming only resonant frequencies
pub fn get_antinodes_single_freq_part1(grid: &CharGrid, positions: &[usize]) -> HashSet<usize> {
let grid_iter = positions.iter();
let mut unique_position = HashSet::new();
for (node1, node2) in grid_iter.clone().cartesian_product(grid_iter) {
if node1 != node2 {
let (x1, y1) = grid.one2two_index(*node1);
let (x2, y2) = grid.one2two_index(*node2);
let x_antinode = (2 * x1).checked_sub(x2);
let y_antinode = (2 * y1).checked_sub(y2);
if let (Some(x_antinode), Some(y_antinode)) = (x_antinode, y_antinode) {
if let Ok(idx) = grid.two2one_index(x_antinode as i32, y_antinode as i32) {
unique_position.insert(idx);
}
}
}
}
unique_position
}
/// Get the antinodes for a single frequency assuming resonant harmonics
/// NOTE: We shouldn't need two separate functions since part1 is a subset of part2 but running out
/// of time again so leaving it as a separate function for now
pub fn get_antinodes_single_freq_part2(grid: &CharGrid, positions: &[usize]) -> HashSet<usize> {
let grid_iter = positions.iter();
let mut unique_position = HashSet::new();
for (node1, node2) in grid_iter.clone().cartesian_product(grid_iter) {
if node1 != node2 {
let mut step = 1;
loop {
let (x1, y1) = grid.one2two_index(*node1);
let (x2, y2) = grid.one2two_index(*node2);
let xstep = x1 as i32 - x2 as i32;
let ystep = y1 as i32 - y2 as i32;
let x_antinode: MyResult<usize> = (x1 as i32 - (step * xstep))
.try_into()
.map_err(|err| -> Box<dyn Error> { Box::new(err) });
let y_antinode: MyResult<usize> = (y1 as i32 - (step * ystep))
.try_into()
.map_err(|err| -> Box<dyn Error> { Box::new(err) });
if let (Ok(x_antinode), Ok(y_antinode)) = (x_antinode, y_antinode) {
if let Ok(idx) = grid.two2one_index(x_antinode as i32, y_antinode as i32) {
unique_position.insert(idx);
} else {
break;
}
} else {
break;
}
step += 1;
}
}
}
unique_position
}
pub enum Mode {
Part1,
Part2,
}
/// Get antinodes for all frequencies
pub fn get_antinode_count(grid: &CharGrid, mode: &Mode) -> usize {
let mut unique_positions: HashSet<usize> = HashSet::new();
for positions in grid.same_freq_positions.iter() {
match mode {
Mode::Part1 => {
unique_positions.extend(get_antinodes_single_freq_part1(grid, positions))
}
Mode::Part2 => {
unique_positions.extend(get_antinodes_single_freq_part2(grid, positions))
}
}
}
unique_positions.len()
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_antinode_calc() {
let grid = CharGrid::new("test_inputs/test_input.txt").unwrap();
assert_eq!(get_antinode_count(&grid, &Mode::Part1), 14);
assert_eq!(get_antinode_count(&grid, &Mode::Part2), 34);
}
#[test]
fn simple_part2_test() {
let grid = CharGrid::new("./test_inputs/simple_part2.txt").unwrap();
assert_eq!(get_antinode_count(&grid, &Mode::Part2), 9);
}
}

@ -0,0 +1,20 @@
use day8::{get_antinode_count, CharGrid, Mode};
fn main() {
let grid = match CharGrid::new("test_inputs/input.txt") {
Ok(grid) => grid,
Err(err) => {
println!("Failed because of \n{err}");
panic!("Program failed to execute")
}
};
println!(
"Solution to part 1 is {}",
get_antinode_count(&grid, &Mode::Part1)
);
println!(
"Solution to part 2 is {}",
get_antinode_count(&grid, &Mode::Part2)
);
}

@ -0,0 +1,50 @@
.C...............w.......................M.E......
...............G........V.............Q....M......
u........k...........V.y..3........Q..........4.a.
..........c.9........k..................i..7..a...
..............y.......................o....a......
.......C...........6.......y.............E........
.............................5....x............i..
...............c.....wy..V.......5..............E.
........k.......c....G..I............o.........m..
............C....s......G......o..........5.......
......................Q...............5....e...4i.
.....I.....................................m.....j
....9K.T.....I...c......w...................X.....
................I.........w....f............3..e.N
C............9..........6..............7...3......
...Z........K.......T.................6...........
......Z..................6...............HN.E.m...
...K...........................1....N...e.o..X....
............hz......................7........j....
.........9......U.R......n.....4.Q..L...X.........
..................A...........S.......0...........
...............l.........p...........2.3M.......x.
.h........................U.................g.....
...Hld...........A..W.......................1x....
.....Z.....n.......lp...e............Xj...L.......
........hU................7...j...S...............
......n............U..........D....S..q...........
....H.....d.r..T..............0..........L.S......
......H......A..T...lp.........LK....1.....2.f.x..
....Z............................g....4...........
..d..r............V...............f..g....2.......
.rn.........D............Pp........q....g.........
..................................................
...................D...0.........Y..t...P.q.......
.......R.s.......................q.P..1...........
...........h..........................2.........f.
........................W.........................
...8...........O................k.................
....rY...........D................P...............
....................O...u.........................
..s..................F............................
...................R......F.......................
......8...........z0....F................J.W......
...................F..z................u..........
..............R.........O.............v.Jt........
s.............8.........m........J.t............v.
......Y.....M........................u..tv........
.................................................v
..................................................
.................z.W..................J...........

@ -0,0 +1,10 @@
T.........
...T......
.T........
..........
..........
..........
..........
..........
..........
..........

@ -0,0 +1,12 @@
............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............
Loading…
Cancel
Save