divide repository in src and lib
This commit is contained in:
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user