diff --git a/src/main.rs b/src/main.rs index ba5cbc5..3924703 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ fn main() { // aoc_2018::tasks::day11::task1(); - aoc_2018::tasks::day11::task2(); + aoc_2018::tasks::day11::task2_fast(); } diff --git a/src/tasks/day11.rs b/src/tasks/day11.rs index 4cbed88..9c992b6 100644 --- a/src/tasks/day11.rs +++ b/src/tasks/day11.rs @@ -19,6 +19,17 @@ pub fn task1() { pub fn task2() { let serial = 6392; + + let mut values: Vec> = Vec::with_capacity(301); + for x in 0..=300 { + let mut v: Vec = Vec::with_capacity(301); + for y in 0..=300 { + v.push(fuel_level(x, y, serial)); + } + values.push(v); + } + let values = &values; + let result = (1..300) .map(|square_size| { let result = (1..=300 - square_size) @@ -27,7 +38,7 @@ pub fn task2() { let power: i32 = (x..x + square_size) .map(|x| { (y..y + square_size) - .map(move |y| fuel_level(x, y, serial)) + .map(move |y| values[x as usize][y as usize]) .sum::() }) .sum(); @@ -41,6 +52,56 @@ pub fn task2() { println!("{:?}", result); } +pub fn task2_fast() { + let serial = 6392; + + let mut cache: Vec> = Vec::with_capacity(301); + for x in 0 as usize..=300 { + let mut v: Vec = Vec::with_capacity(301); + for y in 0 as usize..=300 { + if x == 0 || y == 0 { + v.push(0); + } else { + v.push( + fuel_level(x as i32, y as i32, serial) + v[v.len() - 1] + cache[x - 1][y] + - cache[x - 1][y - 1], + ) + } + } + cache.push(v); + } + let values = &cache; + + for x in 0 as usize..=300 { + for y in 0 as usize..=300 { + if x != 0 && y != 0 { + let cached = area_sum(&values, x, y, 1); + let calc = fuel_level(x as i32, y as i32, serial); + //println!("{},{}: {} ({})", x, y, values[x][y], calc); + assert_eq!(calc, cached); + } + } + } + + let result = (1..=300) + .map(|square_size| { + let result = (1..=301 - square_size) + .flat_map(|x: usize| (1..=301 - square_size).map(move |y: usize| (x, y))) + .map(|(x, y)| (x, y, area_sum(&values, x, y, square_size))) + .max_by_key(|(_, _, value)| *value) + .unwrap(); + (result.0, result.1, result.2, square_size) + }) + .max_by_key(|result| result.2); + println!("{:?}", result); +} + +fn area_sum(values: &Vec>, x: usize, y: usize, length: usize) -> i32 { + values[x + length - 1][y + length - 1] + values[x - 1][y - 1] + - values[x - 1][y + length - 1] + - values[x + length - 1][y - 1] +} + fn fuel_level(x: i32, y: i32, serial: i32) -> i32 { let rack_id = x + 10; let mut power = rack_id * y;