// Copyright 2022 Christian Ulrich // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . use std::io; pub struct Forest { trees: Vec>, } pub enum Direction { North, East, South, West, } pub struct Trees<'a> { forest: &'a Forest, direction: Direction, x: usize, y: usize, } impl Forest { pub fn from_stdin() -> Result { let mut trees = vec![]; for line in io::stdin().lines() { let line = line.unwrap(); if line.len() > 0 { trees.push(line.bytes().map(|b| b - '0' as u8).collect()); } } Ok(Self { trees: trees }) } pub fn dimensions(&self) -> (usize, usize) { (self.trees[0].len(), self.trees.len()) } pub fn tree(&self, x: usize, y: usize) -> Option { Some(*self.trees.get(y)?.get(x)?) } pub fn view(&self, x: usize, y: usize, direction: Direction) -> Option { let _ = self.tree(x, y)?; Some(Trees { forest: self, direction: direction, x: x, y: y, }) } } impl Iterator for Trees<'_> { type Item = u8; fn next(&mut self) -> Option { match self.direction { Direction::North => self.y = self.y.checked_sub(1)?, Direction::East => self.x = self.x.checked_add(1)?, Direction::South => self.y = self.y.checked_add(1)?, Direction::West => self.x = self.x.checked_sub(1)?, }; self.forest.tree(self.x, self.y) } }