finish 11

This commit is contained in:
Dr. Matthias Ratajczak
2022-08-19 14:39:05 +02:00
parent 6f761dea95
commit 333e414d81
5 changed files with 207 additions and 186 deletions
+39
View File
@@ -0,0 +1,39 @@
use std::fmt::Debug;
#[derive(PartialEq)]
pub struct Coordinate {
pub x: usize,
pub y: usize,
}
impl Coordinate {
pub fn new(x: usize, y: usize) -> Self {
Self { x, y }
}
pub fn from_coordinate_pairs(x_idxs: [usize; 4], y_idxs: [usize; 4]) -> [Self; 4] {
let result: Vec<_> = x_idxs
.iter()
.zip(y_idxs)
.map(|(x, y)| Self::new(*x, y))
.collect();
result.try_into().unwrap()
}
}
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)
}
}
pub trait Show {
fn show(&self) -> String;
}
impl Show for [Coordinate; 4] {
fn show(&self) -> String {
self.iter().map(|c| format!("{},{} --", c.x, c.y)).collect()
}
}
+19
View File
@@ -0,0 +1,19 @@
#[derive(Debug)]
pub enum Direction {
Down,
Right,
DiagonalUp,
DiagonalDown,
}
impl Iterator for Direction {
type Item = (Self, bool);
fn next(&mut self) -> Option<Self::Item> {
match self {
Direction::Down => Some((Direction::Right, false)),
Direction::Right => Some((Direction::DiagonalUp, false)),
Direction::DiagonalUp => Some((Direction::DiagonalDown, false)),
Direction::DiagonalDown => Some((Direction::Down, true)),
}
}
}
+37
View File
@@ -0,0 +1,37 @@
use crate::neighbours::Neighbours;
type Data = u32;
pub struct Grid {
grid: Vec<Vec<Data>>,
neighbours: Neighbours,
}
impl Grid {
pub fn from_file(filename: &str) -> Self {
let grid: Vec<Vec<_>> = std::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();
let neighbours = Neighbours::new(nx, ny);
Grid { grid, neighbours }
}
pub fn run(&mut self) {
let mut largest = 0;
while let Some(coordinates) = self.neighbours.next() {
let value = coordinates.iter().map(|c| self.grid[c.y][c.x]).product();
if value > largest {
largest = value;
}
}
println!("{largest}");
}
}
+5 -186
View File
@@ -1,190 +1,9 @@
use std::{fmt::Debug, fs};
mod coordinate;
mod direction;
mod grid;
mod neighbours;
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),
}
}
}
use grid::Grid;
fn main() {
let mut grid = Grid::from_file("grid.txt");
+107
View File
@@ -0,0 +1,107 @@
use crate::coordinate::Coordinate;
use crate::direction::Direction;
const LENGTH: usize = 4;
pub struct Neighbours {
nx: usize,
ny: usize,
x: usize,
y: usize,
current_direction: Direction,
done: bool,
}
impl Neighbours {
pub fn new(nx: usize, ny: usize) -> Self {
Self {
nx,
ny,
x: 0,
y: 0,
current_direction: Direction::Down,
done: false,
}
}
fn iterate_direction(&mut self) {
let (new_direction, has_wrapped) = self.current_direction.next().unwrap();
self.current_direction = new_direction;
if has_wrapped {
self.x += 1;
if self.x == self.nx {
self.x = 0;
self.y += 1;
if self.y == self.ny {
self.done = true;
}
}
}
}
}
impl Iterator for Neighbours {
type Item = [Coordinate; 4];
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
}
let x = self.x;
let y = self.y;
let x_idxs;
let y_idxs;
match self.current_direction {
Direction::Down => {
x_idxs = [x; 4];
y_idxs = [y, y + 1, y + 2, y + 3];
}
Direction::Right => {
x_idxs = [x, x + 1, x + 2, x + 3];
y_idxs = [y; 4];
}
Direction::DiagonalUp => {
if y < LENGTH {
self.iterate_direction();
return self.next();
}
x_idxs = [x, x + 1, x + 2, x + 3];
y_idxs = [y, y - 1, y - 2, y - 3];
}
Direction::DiagonalDown => {
x_idxs = [x, x + 1, x + 2, x + 3];
y_idxs = [y, y + 1, y + 2, y + 3];
}
}
if x_idxs.iter().any(|x| *x >= self.nx) || y_idxs.iter().any(|y| *y >= self.ny) {
self.iterate_direction();
return self.next();
}
let result = Coordinate::from_coordinate_pairs(x_idxs, y_idxs);
self.iterate_direction();
Some(result)
}
}
#[cfg(test)]
mod test {
use super::Neighbours;
use crate::coordinate::Coordinate as C;
#[test]
fn neighbours() {
let mut n = Neighbours::new(20, 20);
n.next()
.unwrap()
.iter()
.zip([C::new(0, 0), C::new(0, 1), C::new(0, 2), C::new(0, 3)])
.for_each(|(c1, c2)| assert_eq!(*c1, c2));
}
}