divide repository in src and lib

This commit is contained in:
timeshifter
2022-08-14 21:14:01 +02:00
parent 4bac3290e5
commit a43cdc4494
19 changed files with 41 additions and 10 deletions
+192
View File
@@ -0,0 +1,192 @@
use std::{fmt::Debug, fs};
const LENGTH: usize = 4;
type Data = u32;
type Neighbours = Vec<Coordinate>;
struct Coordinate {
x: usize,
y: usize,
}
impl Coordinate {
fn new(x: usize, y: usize) -> Self {
Self { x, y }
}
}
impl Debug for Coordinate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let inner = &format!("{},{}", self.x, self.y);
f.write_str(inner)
}
}
struct Grid {
grid: Vec<Vec<Data>>,
nx: usize,
ny: usize,
curr_x: usize,
curr_y: usize,
curr_direction: Direction,
done: bool,
}
impl Grid {
fn from_file(filename: &str) -> Self {
let grid: Vec<Vec<_>> = fs::read_to_string(filename)
.unwrap()
.split_terminator('\n')
.map(|line| {
line.split_whitespace()
.map(|cell| cell.parse::<u8>().unwrap() as Data)
.collect()
})
.collect();
let ny = grid.len();
let nx = grid[0].len();
Grid {
grid,
nx,
ny,
curr_x: 0,
curr_y: 0,
curr_direction: Direction::None,
done: false,
}
}
fn run(&mut self) {
let mut largest = 0;
loop {
if let Some(coordinates) = self.next() {
let value = coordinates.iter().map(|c| self.grid[c.y][c.x]).product();
if value > largest {
largest = value;
}
}
if self.done {
break;
}
}
println!("{largest}");
}
fn advance_index(&mut self) {
if self.curr_x == self.nx - 1 {
self.curr_x = 0;
self.curr_y += 1;
if self.curr_y == self.ny {
self.done = true;
}
} else {
self.curr_x += 1;
}
}
fn get_neighbours(&self) -> Option<Neighbours> {
match self.curr_direction {
Direction::Down => self.get_neighbours_down(),
Direction::Right => self.get_neighbours_right(),
Direction::DiagonalUp => self.get_neighbours_diag_up(),
Direction::DiagonalDown => self.get_neighbours_diag_down(),
Direction::None => unreachable!(),
}
}
fn get_neighbours_down(&self) -> Option<Neighbours> {
let max_y = self.curr_y + LENGTH;
if max_y > self.ny {
None
} else {
Some(
(self.curr_y..max_y)
.map(|y| Coordinate::new(self.curr_x, y))
.collect(),
)
}
}
fn get_neighbours_right(&self) -> Option<Neighbours> {
let max_x = self.curr_x + LENGTH;
if max_x > self.nx {
None
} else {
Some(
(self.curr_x..max_x)
.map(|x| Coordinate::new(x, self.curr_y))
.collect(),
)
}
}
fn get_neighbours_diag_up(&self) -> Option<Neighbours> {
let max_x = self.curr_x + LENGTH;
let min_y = self.curr_y.wrapping_sub(LENGTH);
if max_x > self.nx || min_y > self.ny {
None
} else {
Some(
(self.curr_x..max_x)
.zip(self.curr_y..min_y)
.map(|(x, y)| Coordinate::new(x, y))
.collect(),
)
}
}
fn get_neighbours_diag_down(&self) -> Option<Neighbours> {
let max_x = self.curr_x + LENGTH;
let max_y = self.curr_y + LENGTH;
if max_x > self.nx || max_y > self.ny {
None
} else {
Some(
(self.curr_x..max_x)
.zip(self.curr_y..max_y)
.map(|(x, y)| Coordinate::new(x, y))
.collect(),
)
}
}
}
impl Iterator for Grid {
type Item = Neighbours;
fn next(&mut self) -> Option<Self::Item> {
let has_wrapped;
(self.curr_direction, has_wrapped) = self.curr_direction.next();
if has_wrapped {
self.advance_index();
};
self.get_neighbours()
}
}
#[derive(Debug)]
enum Direction {
None,
Down,
Right,
DiagonalUp,
DiagonalDown,
}
impl Direction {
fn next(&self) -> (Self, bool) {
match self {
Direction::None => (Direction::Down, false),
Direction::Down => (Direction::Right, false),
Direction::Right => (Direction::DiagonalUp, false),
Direction::DiagonalUp => (Direction::DiagonalDown, false),
Direction::DiagonalDown => (Direction::Down, true),
}
}
}
fn main() {
let mut grid = Grid::from_file("grid.txt");
grid.run();
}