From 57d5137b5283d21eea9be8f0ac1bdd6160766a00 Mon Sep 17 00:00:00 2001 From: Gard Spreemann Date: Tue, 7 Dec 2021 15:24:17 +0100 Subject: Day 4 --- 04/Cargo.toml | 15 ++ 04/input.txt | 601 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 04/src/part-1.rs | 90 +++++++++ 04/src/part-2.rs | 95 +++++++++ 04/src/tensor.rs | 156 +++++++++++++++ 04/test.txt | 20 ++ 6 files changed, 977 insertions(+) create mode 100644 04/Cargo.toml create mode 100644 04/input.txt create mode 100644 04/src/part-1.rs create mode 100644 04/src/part-2.rs create mode 100644 04/src/tensor.rs create mode 100644 04/test.txt diff --git a/04/Cargo.toml b/04/Cargo.toml new file mode 100644 index 0000000..b98bd9d --- /dev/null +++ b/04/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "day-04" +version = "0.1.0" +authors = ["Gard Spreemann "] +edition = "2021" + +[[bin]] +name = "part-1" +path = "src/part-1.rs" + +[[bin]] +name = "part-2" +path = "src/part-2.rs" + +[dependencies] diff --git a/04/input.txt b/04/input.txt new file mode 100644 index 0000000..ee55530 --- /dev/null +++ b/04/input.txt @@ -0,0 +1,601 @@ +27,14,70,7,85,66,65,57,68,23,33,78,4,84,25,18,43,71,76,61,34,82,93,74,26,15,83,64,2,35,19,97,32,47,6,51,99,20,77,75,56,73,80,86,55,36,13,95,52,63,79,72,9,10,16,8,69,11,50,54,81,22,45,1,12,88,44,17,62,0,96,94,31,90,39,92,37,40,5,98,24,38,46,21,30,49,41,87,91,60,48,29,59,89,3,42,58,53,67,28 + +31 23 52 26 8 +27 89 37 80 46 +97 19 63 34 79 +13 59 45 12 73 +42 25 22 6 39 + +27 71 24 3 0 +79 42 32 72 62 +99 52 11 92 33 +38 22 16 44 39 +35 26 76 49 58 + +39 19 82 53 57 +52 98 69 77 23 + 1 40 18 66 83 +34 85 28 48 16 +15 93 38 96 27 + +74 50 88 84 99 +34 2 11 25 17 +57 4 19 83 1 +59 77 42 36 33 +73 22 23 37 55 + +98 91 56 84 78 +45 21 24 83 40 +46 58 8 67 4 +33 97 55 7 86 + 2 68 64 27 69 + +68 29 14 49 26 + 4 21 87 71 32 +58 5 17 46 93 +45 96 8 83 2 +78 91 9 20 42 + +49 81 19 48 37 +38 23 45 82 92 +93 99 67 66 42 +40 74 25 56 16 +21 47 26 75 61 + +53 66 72 30 34 +55 82 77 6 92 +60 56 8 22 88 + 5 71 49 29 74 +28 2 32 84 73 + +52 31 24 68 41 +48 82 19 29 65 +51 91 97 39 80 + 3 55 43 40 38 +20 89 53 45 75 + +29 74 19 89 18 +32 88 93 46 63 +91 4 94 64 5 +57 54 49 36 40 +97 81 39 77 1 + + 7 57 94 84 39 +92 3 28 15 75 +88 45 65 81 63 +86 4 89 37 71 + 8 13 66 42 85 + +60 66 35 47 98 +96 27 40 51 39 + 3 64 25 28 74 +58 17 97 59 29 +95 31 18 44 37 + + 3 31 97 85 71 +79 82 22 61 98 +87 14 17 66 75 +36 89 88 83 63 +44 8 81 25 48 + +73 84 28 90 94 +25 19 44 10 23 + 8 59 17 9 93 +20 77 97 64 6 +98 82 27 70 91 + +18 51 16 99 2 +58 22 89 13 19 +39 66 91 8 32 +49 24 85 94 42 +45 70 10 86 4 + +23 81 66 13 34 +25 80 97 5 42 +79 35 2 78 9 + 0 6 91 94 45 +21 90 76 50 56 + +50 92 2 96 75 +85 82 80 97 31 +61 35 55 27 56 +74 42 9 29 90 +86 15 88 47 1 + +18 20 54 92 62 +45 22 32 61 75 + 1 38 50 81 42 +82 4 21 77 65 +27 51 56 39 48 + +36 10 62 28 70 +94 99 34 54 6 +15 1 41 13 12 +92 52 2 63 82 +90 64 29 69 32 + +23 77 33 90 17 +45 78 5 67 28 +57 73 89 81 21 +49 64 37 15 14 + 7 59 4 43 16 + +81 92 25 28 90 +93 72 43 94 26 +24 9 13 74 10 +21 2 36 32 51 +87 97 55 86 71 + +82 71 99 17 90 +69 95 65 55 10 + 9 92 39 62 78 +59 13 61 24 44 + 8 31 58 0 57 + +17 83 55 99 27 +79 4 33 76 7 +81 43 44 49 72 + 2 48 97 20 77 +47 60 35 16 63 + +93 95 94 1 98 +61 57 84 55 22 +85 40 65 46 59 +21 15 63 77 7 +13 99 49 3 96 + + 8 21 14 45 41 +65 63 82 62 28 +91 44 22 79 96 +20 75 86 3 26 +74 11 42 59 36 + + 5 52 43 92 99 +46 63 10 45 81 +13 66 21 32 89 +25 28 96 40 88 +27 18 31 73 34 + + 3 26 43 32 36 +68 87 67 65 99 +73 61 20 90 7 +21 52 2 82 10 +58 49 56 16 80 + +97 25 93 63 32 +87 14 5 22 76 +89 92 91 3 51 + 0 24 95 69 20 +96 11 10 1 55 + +95 86 44 75 70 +59 76 45 2 99 + 1 34 71 81 41 +87 14 33 84 96 + 8 38 9 82 68 + +27 71 70 75 76 +25 87 2 79 96 +20 88 50 37 32 +48 94 63 86 22 +15 6 34 78 59 + +30 89 51 31 77 +74 10 86 71 84 +29 54 58 44 5 +11 90 26 50 63 +64 62 20 40 46 + +37 9 46 23 31 +68 21 25 36 90 +17 33 6 50 30 +11 89 20 47 60 +26 59 34 62 77 + +84 52 40 97 7 +88 30 42 58 94 +64 10 2 90 83 +44 35 77 91 47 +14 74 9 78 53 + +86 14 0 39 24 +87 69 58 8 73 +88 74 27 40 51 +63 54 55 93 61 +16 66 15 21 48 + +43 70 9 81 42 +36 54 99 34 95 +98 19 90 25 44 +69 56 18 77 49 +58 16 67 75 57 + +36 44 14 98 23 +31 5 83 46 3 +45 21 41 11 60 +33 81 88 92 65 +13 51 48 59 71 + +12 5 70 87 32 +42 18 90 73 88 +68 29 76 38 55 +67 62 15 77 34 +39 27 51 54 19 + +87 8 92 93 88 +77 54 15 1 43 +35 97 26 21 29 +13 46 96 69 47 +51 38 91 32 63 + +73 99 30 15 16 +42 58 21 88 44 +45 13 27 68 9 +36 6 81 53 5 +78 76 11 60 1 + +57 76 50 78 31 +45 42 68 53 16 + 9 88 89 19 21 +96 61 97 69 34 +98 87 33 82 0 + + 4 16 89 57 64 +46 75 77 65 23 +71 42 96 52 38 + 1 21 93 0 35 +59 80 53 36 58 + +97 62 35 1 88 +98 60 17 45 94 +12 43 65 23 19 +71 52 3 40 59 +50 76 61 20 22 + +92 65 38 93 13 +55 26 10 46 29 +85 23 19 74 34 +60 14 27 36 18 +53 4 52 49 17 + +99 56 93 70 28 +25 0 77 80 57 +91 50 72 76 23 +53 58 95 78 59 +75 85 90 44 9 + +30 8 5 60 6 +28 35 59 70 96 +20 99 98 81 79 +94 78 27 71 4 + 7 34 43 46 51 + +93 65 22 69 33 +92 49 75 35 11 +58 39 62 86 83 +64 4 76 48 82 +74 1 56 95 31 + + 1 78 98 90 55 +80 14 36 99 7 +85 8 10 9 92 +76 11 40 70 62 +43 53 74 35 58 + +46 78 35 28 49 +84 73 65 25 34 +40 59 66 36 67 +16 22 29 0 45 +20 56 39 88 91 + +32 58 35 25 79 +78 94 57 38 14 +89 87 68 48 76 + 7 67 40 51 33 +95 31 43 93 92 + +38 21 82 31 23 +54 16 77 37 42 +73 99 7 34 90 +71 26 5 91 52 +22 27 47 85 62 + + 2 86 28 37 55 + 1 82 9 36 31 +52 98 89 30 60 +13 17 63 38 57 +73 50 42 20 12 + +56 3 67 62 35 +59 39 19 22 27 +21 58 57 41 54 +75 13 82 50 32 +23 5 99 66 10 + + 7 19 45 66 78 +38 57 40 73 87 +58 30 99 53 83 +64 1 8 56 95 +70 77 16 18 82 + +72 83 95 37 35 +54 59 92 21 79 + 7 81 86 29 41 +52 99 42 57 71 + 3 15 75 34 77 + + 7 70 5 69 4 +34 60 40 73 6 +74 54 67 32 38 +93 62 17 51 86 +57 88 99 3 16 + +42 74 11 34 7 +82 47 71 31 58 +69 23 43 4 64 +32 19 98 93 41 +63 97 8 85 48 + +63 54 34 38 86 + 4 27 15 49 0 +61 77 53 98 74 +62 23 88 97 37 +93 28 25 50 13 + +56 82 41 27 79 +23 31 64 7 65 +52 98 93 16 57 +88 49 10 11 62 +43 95 53 51 83 + +41 10 87 54 86 +19 22 13 40 17 +37 27 45 29 63 +83 85 81 90 7 +57 88 47 66 56 + +67 44 54 88 89 +20 46 61 28 92 +86 49 60 83 95 +42 78 97 51 96 +11 62 4 26 31 + +18 68 87 26 70 +62 84 11 33 90 + 0 45 66 83 6 +20 19 27 44 55 +52 8 5 7 3 + +54 94 88 76 92 +13 98 22 33 26 +95 62 53 81 24 +29 69 15 87 25 +61 40 84 90 93 + + 7 31 3 28 46 +20 51 21 18 38 +30 92 39 70 61 +27 88 35 96 74 +23 5 66 11 42 + +40 61 90 57 54 +41 14 99 62 59 +92 10 48 81 52 +22 29 77 18 87 +31 79 25 94 13 + +17 26 44 98 57 +74 83 51 14 11 +76 91 96 64 33 +43 45 92 72 27 +66 3 28 20 40 + +88 82 44 71 55 +83 47 51 76 24 +86 19 42 34 99 +30 31 87 48 62 +98 53 68 9 21 + + 3 31 6 41 61 +24 77 81 96 44 +78 73 1 98 11 +40 80 27 65 92 +62 67 2 30 10 + +78 46 50 65 56 +84 16 32 58 86 +22 12 54 99 35 + 9 43 55 10 94 +66 81 59 92 76 + +78 3 55 23 83 +13 42 94 91 22 +14 37 31 67 71 + 8 61 57 34 43 +74 50 0 39 65 + +78 16 13 91 34 +14 74 86 3 97 +12 89 58 65 51 +29 57 48 44 93 +95 1 42 39 92 + +93 96 16 85 25 +59 3 70 19 17 +21 84 58 38 86 +57 10 35 95 79 +81 44 73 63 9 + +22 1 96 7 93 +40 49 2 4 66 +87 21 17 32 48 +44 28 42 99 26 +69 8 85 86 75 + +21 31 37 87 28 +89 43 74 83 57 +95 29 92 88 35 +94 25 97 81 50 +15 19 73 45 63 + +92 62 67 95 57 +30 8 4 39 64 +99 31 70 63 96 +25 53 24 93 35 +34 51 82 91 28 + +41 30 20 56 46 +16 32 98 60 35 +67 9 43 42 88 +78 90 71 5 29 +49 31 37 63 18 + +80 40 88 5 62 + 3 6 74 71 97 +19 58 63 59 38 +50 64 34 68 45 +25 30 21 33 83 + +10 65 67 17 50 +21 51 18 68 59 +29 78 77 99 76 +62 35 96 7 95 +82 53 42 49 69 + +74 65 89 6 1 +18 30 72 75 24 +60 50 52 55 82 +68 99 4 61 22 + 9 37 84 57 87 + +96 85 56 72 2 + 9 38 98 12 4 +34 45 74 97 86 +18 94 64 70 68 +91 41 58 39 66 + +34 13 26 80 29 + 0 4 21 60 90 +39 73 12 2 19 +64 44 61 88 45 +59 50 8 91 49 + +34 85 55 2 75 +10 15 89 12 63 +90 29 87 73 71 +38 17 84 45 9 +97 98 77 23 61 + +47 43 22 58 1 +63 44 2 94 99 +33 81 51 49 13 +38 86 42 91 23 + 7 67 68 39 84 + + 4 26 12 38 41 +43 16 88 71 99 +50 24 19 77 98 +23 73 44 10 51 +56 42 30 52 59 + +57 16 9 62 27 +26 65 56 10 82 + 0 74 78 12 99 +77 18 38 5 37 + 7 60 40 90 23 + +14 69 18 51 8 +21 79 60 36 12 +68 44 59 45 16 +90 50 85 25 70 +91 31 30 54 26 + +24 40 51 72 63 +31 60 62 25 96 + 9 44 35 28 91 +97 4 34 81 2 +61 68 94 52 86 + + 0 57 95 88 94 +36 38 25 35 19 +13 6 8 61 98 +45 85 86 69 97 +41 32 7 15 59 + +41 82 19 29 34 +44 96 6 91 76 +69 21 32 94 98 + 4 10 88 30 2 + 8 74 56 65 99 + +36 91 73 15 54 +62 55 40 27 44 +11 60 95 61 46 +31 32 21 41 35 +74 86 83 89 79 + + 2 96 94 82 68 +39 83 49 30 15 +62 11 86 99 59 +51 80 12 72 58 +87 66 98 53 29 + +44 71 18 63 85 +11 75 60 66 13 +36 9 94 57 8 +10 12 32 3 86 + 4 29 54 70 21 + +27 33 76 83 67 +77 29 65 39 44 +52 34 25 93 64 +35 4 57 92 84 +41 51 88 96 0 + +21 91 82 3 26 +23 8 36 20 73 +54 39 60 34 57 +49 99 97 69 43 +41 93 95 80 63 + +73 77 4 9 22 +17 33 15 86 79 +38 16 99 98 30 +64 92 76 50 68 +83 85 52 87 88 + +57 53 13 36 76 + 7 10 91 3 22 + 8 84 56 73 59 +62 80 85 38 33 +68 97 47 14 96 + +36 8 98 43 70 +85 95 31 1 51 +33 41 78 89 56 +76 16 15 34 82 +12 18 39 4 3 + +98 49 41 30 95 +68 89 81 48 84 +15 19 90 66 14 +32 1 88 34 64 +73 65 6 20 86 + +22 18 13 74 34 +75 4 60 88 46 +25 97 54 94 91 +42 67 40 11 81 + 5 12 49 48 15 + +82 91 18 73 57 +97 50 34 16 66 +29 43 81 20 15 +19 44 85 4 32 +90 58 39 53 42 + +50 53 83 10 0 +93 16 84 23 13 +89 63 75 69 51 +65 35 67 56 70 + 4 37 29 47 38 diff --git a/04/src/part-1.rs b/04/src/part-1.rs new file mode 100644 index 0000000..3852036 --- /dev/null +++ b/04/src/part-1.rs @@ -0,0 +1,90 @@ +mod tensor; + +use std::io::{BufRead}; +use std::collections::{HashMap}; +use std::ops::{IndexMut}; + +pub type Matrix = tensor::Tensor<(bool, u64), 2>; +pub type Index = tensor::Index<2>; + +fn read_board(handle: &mut std::io::StdinLock) -> Option { + let mut lines = handle.lines(); + let first_line = lines.next()?.ok()?; + let mut words = first_line.split_whitespace(); + let mut data: Vec<(bool, u64)> = words.map(|x| (false, x.parse().expect("Malformed input"))).collect(); + let n = data.len(); + for i in 1..n { + let line = lines.next().expect("Malformed input").expect("IO error"); + let mut words = line.split_whitespace(); + data.extend(words.map(|x| (false, x.parse::().expect("Malformed input")))); + } + lines.next(); + Some(Matrix::new_from([n, n], data)) +} + +fn is_board_winning(board: & Matrix, pivot: Index) -> bool { + let mut win_row = true; + for j in 0..board.shape()[1] { + if !board[[pivot[0], j]].0 { win_row = false; break; } + } + if win_row { return true; } + let mut win_col = true; + for i in 0..board.shape()[0] { + if !board[[i, pivot[1]]].0 { win_col = false; break; } + } + win_col +} + +fn board_score(board: & Matrix) -> u64 { + board.data().into_iter().filter(|x| !x.0).map(|x| x.1).sum() +} + +pub fn main() { + let mut stdin = std::io::stdin(); + + let numbers: Vec = { + let mut handle = stdin.lock(); + let mut lines = handle.lines(); + let line = lines.next().expect("Malformed input").expect("IO error"); + let mut words = line.split(','); + words.map(|s| s.parse().expect("Malformed input")).collect() + }; + + { + let mut handle = stdin.lock(); + let mut lines = handle.lines(); + lines.next(); + } + let mut handle = stdin.lock(); + + let mut boards: Vec = Vec::new(); + let mut inverse: HashMap> = HashMap::new(); + + while let Some(mat) = read_board(&mut handle) { + let shape = mat.shape(); + for i in 0..shape[0] { + for j in 0..shape[1] { + let x = mat[[i, j]].1; + if let Some(k) = inverse.get_mut(&x) { + k.push((boards.len(), [i, j])); + } + else { inverse.insert(x, vec![(boards.len(), [i, j])]); } + } + } + boards.push(mat); + } + + //println!("Got {} boards and {} inv maps elements.", boards.len(), inverse.len()); + + for x in numbers.into_iter() { + for (board_num, idx) in inverse.get(&x).unwrap().into_iter() { + //println!("Marking ({}, {}) on board {}", idx[0], idx[1], board_num); + let board: &mut Matrix = boards.index_mut(*board_num); + board[idx].0 = true; + if is_board_winning(board, *idx) { + println!("{}", board_score(board)*x); + return; + } + } + } +} diff --git a/04/src/part-2.rs b/04/src/part-2.rs new file mode 100644 index 0000000..9903375 --- /dev/null +++ b/04/src/part-2.rs @@ -0,0 +1,95 @@ +mod tensor; + +use std::io::{BufRead}; +use std::collections::{HashMap, HashSet}; +use std::ops::{IndexMut}; + +pub type Matrix = tensor::Tensor<(bool, u64), 2>; +pub type Index = tensor::Index<2>; + +fn read_board(handle: &mut std::io::StdinLock) -> Option { + let mut lines = handle.lines(); + let first_line = lines.next()?.ok()?; + let mut words = first_line.split_whitespace(); + let mut data: Vec<(bool, u64)> = words.map(|x| (false, x.parse().expect("Malformed input"))).collect(); + let n = data.len(); + for i in 1..n { + let line = lines.next().expect("Malformed input").expect("IO error"); + let mut words = line.split_whitespace(); + data.extend(words.map(|x| (false, x.parse::().expect("Malformed input")))); + } + lines.next(); + Some(Matrix::new_from([n, n], data)) +} + +fn is_board_winning(board: & Matrix, pivot: Index) -> bool { + let mut win_row = true; + for j in 0..board.shape()[1] { + if !board[[pivot[0], j]].0 { win_row = false; break; } + } + if win_row { return true; } + let mut win_col = true; + for i in 0..board.shape()[0] { + if !board[[i, pivot[1]]].0 { win_col = false; break; } + } + win_col +} + +fn board_score(board: & Matrix) -> u64 { + board.data().into_iter().filter(|x| !x.0).map(|x| x.1).sum() +} + +pub fn main() { + let mut stdin = std::io::stdin(); + + let numbers: Vec = { + let mut handle = stdin.lock(); + let mut lines = handle.lines(); + let line = lines.next().expect("Malformed input").expect("IO error"); + let mut words = line.split(','); + words.map(|s| s.parse().expect("Malformed input")).collect() + }; + + { + let mut handle = stdin.lock(); + let mut lines = handle.lines(); + lines.next(); + } + let mut handle = stdin.lock(); + + let mut boards: Vec = Vec::new(); + let mut inverse: HashMap> = HashMap::new(); + + while let Some(mat) = read_board(&mut handle) { + let shape = mat.shape(); + for i in 0..shape[0] { + for j in 0..shape[1] { + let x = mat[[i, j]].1; + if let Some(k) = inverse.get_mut(&x) { + k.push((boards.len(), [i, j])); + } + else { inverse.insert(x, vec![(boards.len(), [i, j])]); } + } + } + boards.push(mat); + } + + //println!("Got {} boards and {} inv maps elements.", boards.len(), inverse.len()); + let mut boards_not_yet_won: HashSet = HashSet::new(); + boards_not_yet_won.extend(0..boards.len()); + for x in numbers.into_iter() { + for (board_num, idx) in inverse.get(&x).unwrap().into_iter() { + //println!("Marking ({}, {}) on board {}", idx[0], idx[1], board_num); + let board: &mut Matrix = boards.index_mut(*board_num); + board[idx].0 = true; + if is_board_winning(board, *idx) { + boards_not_yet_won.remove(board_num); + if boards_not_yet_won.is_empty() { + println!("{}", board_score(board)*x); + return; + } + //winning_boards.push((*board_num, board_score(board)*x)); + } + } + } +} diff --git a/04/src/tensor.rs b/04/src/tensor.rs new file mode 100644 index 0000000..6760d99 --- /dev/null +++ b/04/src/tensor.rs @@ -0,0 +1,156 @@ +#![allow(dead_code)] + +pub type Shape = [usize; D]; +pub type Index = Shape; + +pub struct Tensor { + data: Vec, + shape: Shape, + strides: Shape +} + +pub type Tensor1 = Tensor; +pub type Tensor2 = Tensor; +pub type Tensor3 = Tensor; +pub type Tensor4 = Tensor; +pub type Index1 = Index<1>; +pub type Index2 = Index<2>; +pub type Index3 = Index<3>; +pub type Index4 = Index<4>; + + +impl Tensor { + pub fn new(shape: Shape, x: T) -> Self { + let dim = D; + if dim == 0 { panic!("Empty shape not allowed."); } + + let mut len = shape[dim-1]; + let mut strides: Shape = [0; D]; + strides[dim-1] = 1; + for d in (1..dim).rev() { // d=dim-1, …, 1. + strides[d-1] = shape[d]*strides[d]; + len *= shape[d-1]; + } + if len == 0 { panic!("Empty dimensions not allowed."); } + + Self { + data: vec![x; len], + shape: shape, + strides: strides, + } + } + + pub fn new_from(shape: Shape, x: Vec) -> Self { + let dim = D; + if dim == 0 { panic!("Empty shape not allowed."); } + + let mut len = shape[dim-1]; + let mut strides: Shape = [0; D]; + strides[dim-1] = 1; + for d in (1..dim).rev() { // d=dim-1, …, 1. + strides[d-1] = shape[d]*strides[d]; + len *= shape[d-1]; + } + if len == 0 { panic!("Empty dimensions not allowed."); } + + if len != x.len() { panic!("Vector of length {} cannot fill tensor with {} entries.", x.len(), len); } + + Self { + data: x, + shape: shape, + strides: strides, + } + } + + + #[inline(always)] + fn flatten_idx(self: & Self, idx: & Index) -> usize { + // NOTE: This is a very hot code path. Should benchmark versus explicit loop. + idx.iter().zip(self.strides.iter()).fold(0, |sum, (i, s)| sum + i*s) + } + + fn bound_check_panic(self: & Self, idx: & Index) -> () { + for d in 0..self.dim() { + let i = *(unsafe { idx.get_unchecked(d) }); + if i >= self.shape[d] { + panic!("{}-dimensional tensor index is out of bounds in dimension {} ({} >= {}).", self.dim(), d, i, self.shape[d]) + } + } + } + + pub fn dim(self: & Self) -> usize { D } + + pub fn shape(self: & Self) -> & Shape { &self.shape } + + pub unsafe fn el_unchecked(self: & Self, idx: & Index) -> & T { self.data.get_unchecked(self.flatten_idx(idx)) } + + pub unsafe fn el_unchecked_mut(self: &mut Self, idx: & Index) -> &mut T { + let flat_idx = self.flatten_idx(idx); + self.data.get_unchecked_mut(flat_idx) + } + + pub fn flat_len(self: & Self) -> usize { self.data.len() } + pub fn size(self: & Self) -> usize { self.flat_len()*std::mem::size_of::() } + + pub fn fill_with(self: &mut Self, x: & [T]) -> () { + // Already panics on size mismatch. + self.data.copy_from_slice(x) + } + + pub fn data(self: & Self) -> & [T] { &self.data } +} + +impl Tensor { + pub fn dirty_print(self: & Self) { + for i in 0..self.shape[0] { + for j in 0..self.shape[1] { + print!("{} ", self[[i, j]]); + } + println!(""); + } + } +} + +impl std::ops::Index> for Tensor { + type Output = T; + + fn index(self: & Self, idx: Index) -> & Self::Output { + self.bound_check_panic(&idx); + unsafe { self.el_unchecked(&idx) } + } +} + +impl std::ops::Index<& Index> for Tensor { + type Output = T; + + fn index(self: & Self, idx: & Index) -> & Self::Output { + self.bound_check_panic(idx); + unsafe { self.el_unchecked(idx) } + } +} + +impl std::ops::IndexMut> for Tensor { + fn index_mut(self: &mut Self, idx: Index) -> &mut Self::Output { + self.bound_check_panic(&idx); + unsafe { self.el_unchecked_mut(&idx) } + } +} + +impl std::ops::IndexMut<& Index> for Tensor { + fn index_mut(self: &mut Self, idx: & Index) -> &mut Self::Output { + self.bound_check_panic(idx); + unsafe { self.el_unchecked_mut(idx) } + } +} + +impl IntoIterator for Tensor { + type Item = T; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { self.data.into_iter() } +} + + +// FIXME: Should have a proper IntoIter implementing IntoIter for &'a Tensor. + +// Note: Tensor is also sliceable (due to the Index implementations) diff --git a/04/test.txt b/04/test.txt new file mode 100644 index 0000000..f06791d --- /dev/null +++ b/04/test.txt @@ -0,0 +1,20 @@ +7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 + +22 13 17 11 0 + 8 2 23 4 24 +21 9 14 16 7 + 6 10 3 18 5 + 1 12 20 15 19 + + 3 15 0 2 22 + 9 18 13 17 5 +19 8 7 25 23 +20 11 10 24 4 +14 21 16 12 6 + +14 21 17 24 4 +10 16 15 9 19 +18 8 23 26 20 +22 11 13 6 5 + 2 0 12 3 7 + -- cgit v1.2.3