diff --git a/day08/src/main.rs b/day08/src/main.rs
index ace3d2322832f09c808ab8f4c27e35ee76f20a0c..ab8faec76de62c94272f88599406c71b97bf1546 100644
--- a/day08/src/main.rs
+++ b/day08/src/main.rs
@@ -5,6 +5,7 @@ mod matrix;
 use matrix::Matrix;
 use std::fs::read_to_string;
 
+#[allow(unused)]
 fn solve_without_types() {
     let data = read_to_string("data.txt").unwrap();
     let width = data.lines().next().unwrap().len();
@@ -89,7 +90,7 @@ fn main() {
     let mut datamat = Matrix::new_from_str(&data, |c| (c.to_digit(10).unwrap(), false));
 
     datamat.lines_mut().for_each(|line| {
-        line.iter_mut().fold(-1, |acc, v| {
+        line.fold(-1, |acc, v| {
             if v.0 as i32 > acc {
                 v.1 = true;
                 v.0 as i32
@@ -99,7 +100,7 @@ fn main() {
         });
     });
     datamat.lines_mut().for_each(|line| {
-        line.iter_mut().rev().fold(-1, |acc, v| {
+        line.rev().fold(-1, |acc, v| {
             if v.0 as i32 > acc {
                 v.1 = true;
                 v.0 as i32
@@ -120,8 +121,22 @@ fn main() {
         });
     });
 
+    datamat.collumns_mut().for_each(|col| {
+        col.rev().fold(-1, |acc, v| {
+            if v.0 as i32 > acc {
+                v.1 = true;
+                v.0 as i32
+            } else {
+                acc
+            }
+        });
+    });
+
     datamat.lines().for_each(|v| {
-        v.iter().for_each(|x| print!("{}", if x.1 { 'A' } else { '_' }));
+        v.for_each(|x| print!("{}", if x.1 { 'A' } else { '_' }));
         println!();
-    })
+    });
+
+    let visible = datamat.elements.iter().filter(|v| v.1).count();
+    println!("Visible trees: {visible}");
 }
diff --git a/day08/src/matrix.rs b/day08/src/matrix.rs
deleted file mode 100644
index aead067cfbf6d7a3f6c9f95d8a45b59a2324378a..0000000000000000000000000000000000000000
--- a/day08/src/matrix.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-use std::{
-    iter::{repeat_with, Take},
-    marker::PhantomData,
-    slice::{Chunks, ChunksMut},
-};
-
-pub struct Matrix<T: Clone> {
-    pub width: usize,
-    pub height: usize,
-    pub elements: Vec<T>,
-}
-
-impl<T: Clone> Matrix<T> {
-    pub fn new() -> Self {
-        Self {
-            width: 0,
-            height: 0,
-            elements: Vec::new(),
-        }
-    }
-
-    pub fn new_from_str<F>(source: &str, f: F) -> Self
-    where
-        F: FnMut(char) -> T,
-    {
-        let mut f_mut = f;
-        let mut iter = source.chars().filter(|c| c != &'\n');
-        let width = source.lines().next().unwrap_or("").len();
-        let height = source.lines().count();
-        Self {
-            width,
-            height,
-            elements: repeat_with(|| f_mut(iter.next().unwrap()))
-                .take(width * height)
-                .collect::<Vec<_>>(),
-        }
-    }
-
-    pub fn lines(&self) -> MatrixLines<T> {
-        MatrixLines(self.elements.chunks(self.width))
-    }
-
-    pub fn lines_mut(&mut self) -> MatrixLinesMut<T> {
-        MatrixLinesMut(self.elements.chunks_mut(self.width))
-    }
-
-    pub fn collumns_mut(&mut self) -> impl Iterator<Item = MatrixCollumnMut<'_, T>> {
-        let mut collumn = 0;
-        let width = self.width;
-        MatrixCollumnsMut {
-            iter: repeat_with(move || {
-                let i = collumn;
-                collumn += 1;
-                MatrixCollumnMut {
-                    collumn: i,
-                    width,
-                    index: 0,
-                    obj: self,
-                    phantom: PhantomData,
-                }
-            })
-            .take(width),
-        }
-    }
-
-    pub fn collumns(&self) -> MatrixCollumns<T> {
-        MatrixCollumns::new(self)
-    }
-
-    pub fn resize(&mut self, width: usize, height: usize, value: T)
-    where
-        T: Clone,
-    {
-        self.width = width;
-        self.height = height;
-        self.elements.resize(width * height, value);
-    }
-}
-
-pub struct MatrixCollumnsMut<'a, T, I>
-where
-    T: Clone + 'a,
-    I: Iterator<Item = MatrixCollumnMut<'a, T>>,
-{
-    iter: Take<I>,
-}
-
-impl<'a, T, I> Iterator for MatrixCollumnsMut<'a, T, I>
-where
-    T: Clone + 'a,
-    I: Iterator<Item = MatrixCollumnMut<'a, T>>,
-{
-    type Item = MatrixCollumnMut<'a, T>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.iter.next()
-    }
-}
-
-pub struct MatrixCollumnMut<'a, T: Clone> {
-    width: usize,
-    collumn: usize,
-    index: usize,
-    obj: *mut Matrix<T>,
-    phantom: PhantomData<&'a T>,
-}
-
-impl<'a, T: Clone> Iterator for MatrixCollumnMut<'a, T> {
-    type Item = &'a mut T;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        let i = self.index;
-        self.index += 1;
-        if i < self.width {
-            Some(unsafe {
-                &mut *(*self.obj)
-                    .elements
-                    .as_mut_ptr()
-                    .add(self.collumn + i * self.width)
-            })
-        } else {
-            None
-        }
-    }
-}
-
-#[derive(Clone, Copy)]
-pub struct MatrixCollumns<'a, T: Clone> {
-    parent: &'a Matrix<T>,
-    index: usize,
-}
-
-impl<'a, T: Clone> MatrixCollumns<'a, T> {
-    pub fn new(parent: &'a Matrix<T>) -> Self {
-        Self { parent, index: 0 }
-    }
-}
-
-impl<'a, T: Clone> Iterator for MatrixCollumns<'a, T> {
-    type Item = MatrixCollumn<'a, T>;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        if self.index < self.parent.width {
-            self.index += 1;
-            Some(MatrixCollumn::new(self.clone(), self.index - 1))
-        } else {
-            None
-        }
-    }
-}
-
-pub struct MatrixCollumn<'a, T: Clone> {
-    parent: MatrixCollumns<'a, T>,
-    offset: usize,
-    index: usize,
-}
-
-impl<'a, T: Clone> MatrixCollumn<'a, T> {
-    pub fn new(parent: MatrixCollumns<'a, T>, offset: usize) -> Self {
-        Self {
-            parent,
-            offset,
-            index: 0,
-        }
-    }
-}
-
-impl<'a, T: Clone> Iterator for MatrixCollumn<'a, T> {
-    type Item = &'a T;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        if self.index < self.parent.parent.height {
-            self.index += 1;
-            Some(
-                &self.parent.parent.elements
-                    [self.offset + (self.index - 1) * self.parent.parent.width],
-            )
-        } else {
-            None
-        }
-    }
-}
-
-impl<'a, T: Clone> ExactSizeIterator for MatrixCollumn<'a, T> {}
-
-pub struct MatrixLines<'a, T>(Chunks<'a, T>);
-
-impl<'a, T> Iterator for MatrixLines<'a, T> {
-    type Item = &'a [T];
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.0.next()
-    }
-}
-
-impl<'a, T> ExactSizeIterator for MatrixLines<'a, T> {}
-
-pub struct MatrixLinesMut<'a, T>(ChunksMut<'a, T>);
-
-impl<'a, T> Iterator for MatrixLinesMut<'a, T> {
-    type Item = &'a mut [T];
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.0.next()
-    }
-}
-
-impl<'a, T> ExactSizeIterator for MatrixLinesMut<'a, T> {}
diff --git a/day08/src/matrix/collumns.rs b/day08/src/matrix/collumns.rs
new file mode 100644
index 0000000000000000000000000000000000000000..925eca629b17f85528d5717448e0ac3895368795
--- /dev/null
+++ b/day08/src/matrix/collumns.rs
@@ -0,0 +1,164 @@
+use std::marker::PhantomData;
+
+#[derive(Clone, Copy)]
+pub struct MatrixCollumns<'a, T: Clone> {
+    parent: &'a super::Matrix<T>,
+    index: usize,
+}
+
+impl<'a, T: Clone> MatrixCollumns<'a, T> {
+    pub fn new(parent: &'a super::Matrix<T>) -> Self {
+        Self { parent, index: 0 }
+    }
+}
+
+impl<'a, T: Clone> Iterator for MatrixCollumns<'a, T> {
+    type Item = MatrixCollumn<'a, T>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.index < self.parent.width {
+            self.index += 1;
+            Some(MatrixCollumn::new(self.clone(), self.index - 1))
+        } else {
+            None
+        }
+    }
+}
+
+pub struct MatrixCollumn<'a, T: Clone> {
+    parent: MatrixCollumns<'a, T>,
+    offset: usize,
+    index: usize,
+}
+
+impl<'a, T: Clone> MatrixCollumn<'a, T> {
+    pub fn new(parent: MatrixCollumns<'a, T>, offset: usize) -> Self {
+        Self {
+            parent,
+            offset,
+            index: 0,
+        }
+    }
+}
+
+impl<'a, T: Clone> Iterator for MatrixCollumn<'a, T> {
+    type Item = &'a T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.index < self.parent.parent.height {
+            self.index += 1;
+            Some(
+                &self.parent.parent.elements
+                    [self.offset + (self.index - 1) * self.parent.parent.width],
+            )
+        } else {
+            None
+        }
+    }
+}
+
+impl<'a, T: Clone> ExactSizeIterator for MatrixCollumn<'a, T> {}
+
+pub struct MatrixCollumnsMut<'a, T: Clone> {
+    obj: *mut super::Matrix<T>,
+    collumn: usize,
+    phantom: PhantomData<&'a T>,
+}
+
+impl<'a, T: Clone> MatrixCollumnsMut<'a, T> {
+    pub fn new(parent: &'a mut super::Matrix<T>) -> Self {
+        Self {
+            obj: parent,
+            collumn: 0,
+            phantom: PhantomData,
+        }
+    }
+}
+
+impl<'a, T: Clone> Iterator for MatrixCollumnsMut<'a, T> {
+    type Item = MatrixCollumnMut<'a, T>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let i = self.collumn;
+        let width = unsafe { (*self.obj).width };
+        let height = unsafe { (*self.obj).width };
+        if i >= width {
+            return None;
+        }
+        self.collumn += 1;
+
+        Some(MatrixCollumnMut::new(self.obj, i, height))
+    }
+}
+
+pub struct MatrixCollumnMut<'a, T: Clone> {
+    collumn: usize,
+    index: usize,
+    back_index: Option<usize>,
+    obj: *mut super::Matrix<T>,
+    phantom: PhantomData<&'a T>,
+}
+
+impl<'a, T: Clone> MatrixCollumnMut<'a, T> {
+    pub fn new(obj: *mut super::Matrix<T>, collumn: usize, height: usize) -> Self {
+        Self {
+            collumn,
+            index: 0,
+            back_index: Some(height - 1),
+            obj,
+            phantom: PhantomData,
+        }
+    }
+}
+
+impl<'a, T: Clone> Iterator for MatrixCollumnMut<'a, T> {
+    type Item = &'a mut T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let i = self.index;
+        self.index += 1;
+        let width = unsafe { (*self.obj).width };
+        let height = unsafe { (*self.obj).height };
+        if i < height && self.back_index.is_some() && i != (self.back_index.clone().unwrap() + 1) {
+            Some(unsafe {
+                &mut *(*self.obj)
+                    .elements
+                    .as_mut_ptr()
+                    .add(self.collumn + i * width)
+            })
+        } else {
+            None
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let remaining = (unsafe { (*self.obj).height } - self.index) as usize;
+        (remaining, Some(remaining))
+    }
+}
+
+impl<'a, T: Clone> ExactSizeIterator for MatrixCollumnMut<'a, T> {}
+
+impl<'a, T: Clone> DoubleEndedIterator for MatrixCollumnMut<'a, T> {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        if self.back_index.is_none() {
+            return None;
+        }
+
+        let i = self.back_index.clone().unwrap();
+        self.back_index = if i > 0 { Some(i - 1) } else { None };
+
+        let width = unsafe { (*self.obj).width };
+        let height = unsafe { (*self.obj).height };
+        if i < height && (i + 1) != self.index {
+            Some(unsafe {
+                &mut *(*self.obj)
+                    .elements
+                    .as_mut_ptr()
+                    .add(self.collumn + i * width)
+            })
+        } else {
+            None
+        }
+    }
+}
diff --git a/day08/src/matrix/lines.rs b/day08/src/matrix/lines.rs
new file mode 100644
index 0000000000000000000000000000000000000000..cc5d575973ac7c7228dbe5c4c329b16595d7e747
--- /dev/null
+++ b/day08/src/matrix/lines.rs
@@ -0,0 +1,53 @@
+use std::slice::{Chunks, ChunksMut};
+
+use super::Matrix;
+
+pub struct MatrixLines<'a, T>(Chunks<'a, T>);
+
+impl<'a, T: Clone> MatrixLines<'a, T> {
+    pub fn new(parent: &'a Matrix<T>) -> Self {
+        Self(parent.elements.chunks(parent.width))
+    }
+}
+
+impl<'a, T> Iterator for MatrixLines<'a, T> {
+    type Item = core::slice::Iter<'a, T>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.0.next() {
+            Some(v) => Some(v.iter()),
+            None => None
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+}
+
+impl<'a, T> ExactSizeIterator for MatrixLines<'a, T> {}
+
+pub struct MatrixLinesMut<'a, T>(ChunksMut<'a, T>);
+
+impl<'a, T: Clone> MatrixLinesMut<'a, T> {
+    pub fn new(parent: &'a mut Matrix<T>) -> Self {
+        Self(parent.elements.chunks_mut(parent.width))
+    }
+}
+
+impl<'a, T> Iterator for MatrixLinesMut<'a, T> {
+    type Item = core::slice::IterMut<'a, T>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.0.next() {
+            Some(v) => Some(v.iter_mut()),
+            None => None
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.0.size_hint()
+    }
+}
+
+impl<'a, T> ExactSizeIterator for MatrixLinesMut<'a, T> {}
\ No newline at end of file
diff --git a/day08/src/matrix/mod.rs b/day08/src/matrix/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..13e2ab4f1dbff6dc746f9d36f5611635458d98e3
--- /dev/null
+++ b/day08/src/matrix/mod.rs
@@ -0,0 +1,64 @@
+use std::iter::repeat_with;
+
+use self::{
+    collumns::{MatrixCollumns, MatrixCollumnsMut},
+    lines::{MatrixLines, MatrixLinesMut},
+};
+
+mod collumns;
+mod lines;
+
+pub struct Matrix<T: Clone> {
+    pub width: usize,
+    pub height: usize,
+    pub elements: Vec<T>,
+}
+
+impl<T: Clone> Matrix<T> {
+    #[allow(unused)]
+    pub fn new() -> Self {
+        Self {
+            width: 0,
+            height: 0,
+            elements: Vec::new(),
+        }
+    }
+
+    #[allow(unused)]
+    pub fn new_from_str<F>(source: &str, f: F) -> Self
+    where
+        F: FnMut(char) -> T,
+    {
+        let mut f_mut = f;
+        let mut iter = source.chars().filter(|c| c != &'\n');
+        let width = source.lines().next().unwrap_or("").len();
+        let height = source.lines().count();
+        Self {
+            width,
+            height,
+            elements: repeat_with(|| f_mut(iter.next().unwrap()))
+                .take(width * height)
+                .collect::<Vec<_>>(),
+        }
+    }
+
+    #[allow(unused)]
+    pub fn lines(&self) -> MatrixLines<T> {
+        MatrixLines::new(self)
+    }
+
+    #[allow(unused)]
+    pub fn lines_mut(&mut self) -> MatrixLinesMut<T> {
+        MatrixLinesMut::new(self)
+    }
+
+    #[allow(unused)]
+    pub fn collumns(&self) -> MatrixCollumns<T> {
+        MatrixCollumns::new(self)
+    }
+
+    #[allow(unused)]
+    pub fn collumns_mut(&mut self) -> MatrixCollumnsMut<T> {
+        MatrixCollumnsMut::new(self)
+    }
+}