day21: problem 2 solution
not proud of this one either, completely cheated and it does not get exactly the correct error (it was off by one for my input), but the quadratic solver on Wolfram Alpha was able to do it.
This commit is contained in:
		
							
								
								
									
										267
									
								
								21/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										267
									
								
								21/Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -2,12 +2,27 @@
 | 
			
		||||
# It is not intended for manual editing.
 | 
			
		||||
version = 3
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "approx"
 | 
			
		||||
version = "0.5.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "num-traits",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "autocfg"
 | 
			
		||||
version = "1.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "bytemuck"
 | 
			
		||||
version = "1.14.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "cfg-if"
 | 
			
		||||
version = "1.0.0"
 | 
			
		||||
@@ -64,8 +79,10 @@ name = "day21"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "indicatif",
 | 
			
		||||
 "petgraph",
 | 
			
		||||
 "polyfit-rs",
 | 
			
		||||
 "primes",
 | 
			
		||||
 "rayon",
 | 
			
		||||
 "test-case",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@@ -80,34 +97,6 @@ version = "0.3.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "equivalent"
 | 
			
		||||
version = "1.0.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "fixedbitset"
 | 
			
		||||
version = "0.4.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "hashbrown"
 | 
			
		||||
version = "0.14.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "indexmap"
 | 
			
		||||
version = "2.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "equivalent",
 | 
			
		||||
 "hashbrown",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "indicatif"
 | 
			
		||||
version = "0.17.7"
 | 
			
		||||
@@ -142,6 +131,16 @@ version = "0.2.151"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "matrixmultiply"
 | 
			
		||||
version = "0.3.8"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "autocfg",
 | 
			
		||||
 "rawpointer",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "memoffset"
 | 
			
		||||
version = "0.9.0"
 | 
			
		||||
@@ -151,6 +150,72 @@ dependencies = [
 | 
			
		||||
 "autocfg",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "nalgebra"
 | 
			
		||||
version = "0.31.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "20bd243ab3dbb395b39ee730402d2e5405e448c75133ec49cc977762c4cba3d1"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "approx",
 | 
			
		||||
 "matrixmultiply",
 | 
			
		||||
 "nalgebra-macros",
 | 
			
		||||
 "num-complex",
 | 
			
		||||
 "num-rational",
 | 
			
		||||
 "num-traits",
 | 
			
		||||
 "simba",
 | 
			
		||||
 "typenum",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "nalgebra-macros"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn 1.0.109",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "num-complex"
 | 
			
		||||
version = "0.4.4"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "num-traits",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "num-integer"
 | 
			
		||||
version = "0.1.45"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "autocfg",
 | 
			
		||||
 "num-traits",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "num-rational"
 | 
			
		||||
version = "0.4.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "autocfg",
 | 
			
		||||
 "num-integer",
 | 
			
		||||
 "num-traits",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "num-traits"
 | 
			
		||||
version = "0.2.17"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "autocfg",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "number_prefix"
 | 
			
		||||
version = "0.4.0"
 | 
			
		||||
@@ -158,13 +223,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "petgraph"
 | 
			
		||||
version = "0.6.4"
 | 
			
		||||
name = "paste"
 | 
			
		||||
version = "1.0.14"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
 | 
			
		||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "polyfit-rs"
 | 
			
		||||
version = "0.2.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "ab98d9704c7300e37472a6790a447eaf501d664a1889737faa53c26790d2b697"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "fixedbitset",
 | 
			
		||||
 "indexmap",
 | 
			
		||||
 "nalgebra",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@@ -173,6 +243,36 @@ version = "1.6.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "primes"
 | 
			
		||||
version = "0.3.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "68a61082d8bceecd71a3870e9162002bb75f7ba9c7aa8b76227e887782fef9c8"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "proc-macro2"
 | 
			
		||||
version = "1.0.70"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "unicode-ident",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "quote"
 | 
			
		||||
version = "1.0.33"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rawpointer"
 | 
			
		||||
version = "0.2.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rayon"
 | 
			
		||||
version = "1.8.0"
 | 
			
		||||
@@ -193,12 +293,111 @@ dependencies = [
 | 
			
		||||
 "crossbeam-utils",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "safe_arch"
 | 
			
		||||
version = "0.7.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bytemuck",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "simba"
 | 
			
		||||
version = "0.7.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "2f3fd720c48c53cace224ae62bef1bbff363a70c68c4802a78b5cc6159618176"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "approx",
 | 
			
		||||
 "num-complex",
 | 
			
		||||
 "num-traits",
 | 
			
		||||
 "paste",
 | 
			
		||||
 "wide",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "syn"
 | 
			
		||||
version = "1.0.109"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "unicode-ident",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "syn"
 | 
			
		||||
version = "2.0.42"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "unicode-ident",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "test-case"
 | 
			
		||||
version = "3.3.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "test-case-macros",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "test-case-core"
 | 
			
		||||
version = "3.3.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cfg-if",
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn 2.0.42",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "test-case-macros"
 | 
			
		||||
version = "3.3.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
 "syn 2.0.42",
 | 
			
		||||
 "test-case-core",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "typenum"
 | 
			
		||||
version = "1.17.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "unicode-ident"
 | 
			
		||||
version = "1.0.12"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "unicode-width"
 | 
			
		||||
version = "0.1.11"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "wide"
 | 
			
		||||
version = "0.7.13"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "c68938b57b33da363195412cfc5fc37c9ed49aa9cfe2156fde64b8d2c9498242"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "bytemuck",
 | 
			
		||||
 "safe_arch",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-sys"
 | 
			
		||||
version = "0.45.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -7,5 +7,7 @@ edition = "2021"
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
indicatif = "0.17.7"
 | 
			
		||||
petgraph = "0.6.4"
 | 
			
		||||
polyfit-rs = "0.2.1"
 | 
			
		||||
primes = "0.3.0"
 | 
			
		||||
rayon = "1.8.0"
 | 
			
		||||
test-case = "3.3.1"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										142
									
								
								21/src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										142
									
								
								21/src/main.rs
									
									
									
									
									
								
							@@ -1,9 +1,7 @@
 | 
			
		||||
use core::panic;
 | 
			
		||||
use std::collections::HashSet;
 | 
			
		||||
use indicatif::{ProgressBar, ProgressStyle};
 | 
			
		||||
use petgraph::algo::k_shortest_path;
 | 
			
		||||
use petgraph::prelude::*;
 | 
			
		||||
use rayon::prelude::*;
 | 
			
		||||
use std::collections::HashSet;
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::{BufRead, BufReader, Lines};
 | 
			
		||||
use std::time::Instant;
 | 
			
		||||
@@ -31,46 +29,33 @@ fn main() {
 | 
			
		||||
 | 
			
		||||
// PARSE
 | 
			
		||||
 | 
			
		||||
type Position = (usize, usize);
 | 
			
		||||
type Position = (isize, isize);
 | 
			
		||||
type WrappedPosition = (usize, usize);
 | 
			
		||||
type Offset = (isize, isize);
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
struct MapTile {
 | 
			
		||||
    c: char,
 | 
			
		||||
    idx: NodeIndex,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MapTile {
 | 
			
		||||
    fn new(c: char, idx: NodeIndex) -> Self {
 | 
			
		||||
        Self { c, idx }
 | 
			
		||||
    fn new(c: char) -> Self {
 | 
			
		||||
        Self { c }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GraphType = DiGraph<char, ()>;
 | 
			
		||||
struct GardenMap {
 | 
			
		||||
    map: Vec<Vec<MapTile>>,
 | 
			
		||||
    graph: GraphType,
 | 
			
		||||
    start: Position,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: BufRead> From<Lines<T>> for GardenMap {
 | 
			
		||||
    fn from(lines: Lines<T>) -> Self {
 | 
			
		||||
        let mut graph = DiGraph::new();
 | 
			
		||||
        let map = lines
 | 
			
		||||
            .map(|line| {
 | 
			
		||||
                line.unwrap()
 | 
			
		||||
                    .chars()
 | 
			
		||||
                    .map(|c| MapTile::new(c, graph.add_node(c)))
 | 
			
		||||
                    .collect()
 | 
			
		||||
            })
 | 
			
		||||
            .map(|line| line.unwrap().chars().map(|c| MapTile::new(c)).collect())
 | 
			
		||||
            .collect();
 | 
			
		||||
        let mut new = Self {
 | 
			
		||||
            map,
 | 
			
		||||
            start: (0, 0),
 | 
			
		||||
            graph,
 | 
			
		||||
        };
 | 
			
		||||
        let mut new = Self { map, start: (0, 0) };
 | 
			
		||||
        new.find_start();
 | 
			
		||||
        new.build_graph();
 | 
			
		||||
        new
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -78,6 +63,21 @@ impl<T: BufRead> From<Lines<T>> for GardenMap {
 | 
			
		||||
const ADJACENCIES: [Offset; 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
 | 
			
		||||
 | 
			
		||||
impl GardenMap {
 | 
			
		||||
    fn wrap_pos(&self, pos: &Position) -> WrappedPosition {
 | 
			
		||||
        let (width, height) = (self.width() as isize, self.height() as isize);
 | 
			
		||||
        (
 | 
			
		||||
            if pos.0 < 0 {
 | 
			
		||||
                (pos.0 + (-pos.0 / width + 1) * width) as usize % self.width()
 | 
			
		||||
            } else {
 | 
			
		||||
                pos.0 as usize % self.width()
 | 
			
		||||
            },
 | 
			
		||||
            if pos.1 < 0 {
 | 
			
		||||
                (pos.1 + (-pos.1 / height + 1) * height) as usize % self.height()
 | 
			
		||||
            } else {
 | 
			
		||||
                pos.1 as usize % self.height()
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
    fn width(&self) -> usize {
 | 
			
		||||
        self.map[0].len()
 | 
			
		||||
    }
 | 
			
		||||
@@ -85,80 +85,103 @@ impl GardenMap {
 | 
			
		||||
        self.map.len()
 | 
			
		||||
    }
 | 
			
		||||
    fn at(&self, pos: &Position) -> &MapTile {
 | 
			
		||||
        let pos = self.wrap_pos(pos);
 | 
			
		||||
        &self.map[pos.1][pos.0]
 | 
			
		||||
    }
 | 
			
		||||
    fn at_mut(&mut self, pos: &Position) -> &mut MapTile {
 | 
			
		||||
        &mut self.map[pos.1][pos.0]
 | 
			
		||||
    }
 | 
			
		||||
    // return the valid 'moves' from pos
 | 
			
		||||
    fn adjacent_to(&self, pos: &Position) -> Vec<Position> {
 | 
			
		||||
        ADJACENCIES
 | 
			
		||||
            .iter()
 | 
			
		||||
            .filter_map(|ofs| self.offset_pos(pos, ofs))
 | 
			
		||||
            .filter(|pos| self.at(pos).c == '.' || self.at(pos).c == 'S')
 | 
			
		||||
            .filter(|pos| self.at(pos).c != '#')
 | 
			
		||||
            .collect()
 | 
			
		||||
    }
 | 
			
		||||
    fn offset_pos(&self, pos: &Position, ofs: &Offset) -> Option<Position> {
 | 
			
		||||
        let new_pos = (pos.0 as isize + ofs.0, pos.1 as isize + ofs.1);
 | 
			
		||||
        if new_pos.0 < 0 || new_pos.1 < 0 || new_pos.0 >= self.width() as isize || new_pos.1 >= self.height() as isize {
 | 
			
		||||
            return None;
 | 
			
		||||
        }
 | 
			
		||||
        return Some((new_pos.0 as usize, new_pos.1 as usize));
 | 
			
		||||
        return Some((new_pos.0, new_pos.1));
 | 
			
		||||
    }
 | 
			
		||||
    fn find_start(&mut self) {
 | 
			
		||||
        for (y, row) in self.map.iter().enumerate() {
 | 
			
		||||
            for (x, tile) in row.iter().enumerate() {
 | 
			
		||||
                if tile.c == 'S' {
 | 
			
		||||
                    self.start = (x, y);
 | 
			
		||||
                    self.start = (x as isize, y as isize);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        panic!("didn't find the start square!");
 | 
			
		||||
    }
 | 
			
		||||
    fn build_graph(&mut self) {
 | 
			
		||||
        for y in 0..self.height() {
 | 
			
		||||
            for x in 0..self.width() {
 | 
			
		||||
                for (x2, y2) in self.adjacent_to(&(x, y)) {
 | 
			
		||||
                    self.graph.add_edge(self.at(&(x, y)).idx, self.at(&(x2, y2)).idx, ());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    fn reachable_after(&self, from: &Position, n: usize) -> HashSet<Position> {
 | 
			
		||||
    fn reachable_after(&self, from: &Position, n: usize) -> u64 {
 | 
			
		||||
        let bar = ProgressBar::new(n as u64).with_style(
 | 
			
		||||
            ProgressStyle::with_template(
 | 
			
		||||
                "[{elapsed_precise}/{eta_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {per_sec}",
 | 
			
		||||
            )
 | 
			
		||||
            .unwrap(),
 | 
			
		||||
        );
 | 
			
		||||
        let mut visited_after: Vec<HashSet<Position>> = Vec::new();
 | 
			
		||||
        visited_after.push(HashSet::from([*from]));
 | 
			
		||||
        for i in 1..n + 1 {
 | 
			
		||||
        for i in 1..n+1 {
 | 
			
		||||
            visited_after.push(
 | 
			
		||||
                visited_after[i - 1]
 | 
			
		||||
                    .iter()
 | 
			
		||||
                    .flat_map(|last| self.adjacent_to(last))
 | 
			
		||||
                    .collect(),
 | 
			
		||||
            );
 | 
			
		||||
            bar.inc(1);
 | 
			
		||||
            // if primes::is_prime(i as u64) {
 | 
			
		||||
            //     println!("count after {} steps: {}", i, visited_after[i].len());
 | 
			
		||||
            // }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        visited_after[n].clone()
 | 
			
		||||
        visited_after[n].len() as u64
 | 
			
		||||
    }
 | 
			
		||||
    fn reachable_count_after(&self, from: &Position, n: usize) -> u64 {
 | 
			
		||||
        self.reachable_after(from, n).len() as u64
 | 
			
		||||
        let dim = self.width() as f64;
 | 
			
		||||
        let target_mod = (n % self.width()) as f64;
 | 
			
		||||
        let x_values:Vec<f64> = vec![target_mod, target_mod + dim, target_mod + 2.*dim];
 | 
			
		||||
        let y_values:Vec<f64> = x_values.iter().map(|n| self.reachable_after(from, *n as usize) as f64).collect();
 | 
			
		||||
 | 
			
		||||
        let coeffs = polyfit_rs::polyfit_rs::polyfit(
 | 
			
		||||
            &x_values,
 | 
			
		||||
            &y_values,
 | 
			
		||||
            2,
 | 
			
		||||
        ).unwrap();
 | 
			
		||||
        println!("values: x: {:?} y: {:?}", x_values, y_values);
 | 
			
		||||
        println!("coefficients: {:?}", coeffs);
 | 
			
		||||
 | 
			
		||||
        let f_n= n as f64;
 | 
			
		||||
        let result = coeffs[0] + coeffs[1] * f_n  + coeffs[2] * f_n.powf(2.0);
 | 
			
		||||
 | 
			
		||||
        result.round() as u64
 | 
			
		||||
    }
 | 
			
		||||
    fn draw_with_bounds(&self, from: &Position, to: &Position) {
 | 
			
		||||
        for row in from.1..to.1 + 1 {
 | 
			
		||||
            for col in from.0..to.0 + 1 {
 | 
			
		||||
                print!("{}", self.at(&(col, row)).c);
 | 
			
		||||
            }
 | 
			
		||||
            println!();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn print_visited(map: &GardenMap, visited: &Vec<Vec<bool>>) {
 | 
			
		||||
    for (y, row) in visited.iter().enumerate() {
 | 
			
		||||
        for (x, cell) in row.iter().enumerate() {
 | 
			
		||||
            print!("{}", if *cell { 'O' } else { map.at(&(x, y)).c });
 | 
			
		||||
        }
 | 
			
		||||
        println!();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
// fn print_visited(map: &GardenMap, visited: &Vec<Vec<bool>>) {
 | 
			
		||||
//     for (y, row) in visited.iter().enumerate() {
 | 
			
		||||
//         for (x, cell) in row.iter().enumerate() {
 | 
			
		||||
//             print!("{}", if *cell { 'O' } else { map.at(&(x, y)).c });
 | 
			
		||||
//         }
 | 
			
		||||
//         println!();
 | 
			
		||||
//     }
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// PROBLEM 1 solution
 | 
			
		||||
 | 
			
		||||
fn problem1_impl<T: BufRead>(input: Lines<T>, n: usize) -> u64 {
 | 
			
		||||
    let map = GardenMap::from(input);
 | 
			
		||||
    // println!("map: {:?} start: {:?}", map.map, &map.start);
 | 
			
		||||
 | 
			
		||||
    // map.draw_with_bounds(
 | 
			
		||||
    //     &(-(map.width() as isize), -(map.height() as isize)),
 | 
			
		||||
    //     &(map.width() as isize * 2 + 1, map.height() as isize * 2 + 1),
 | 
			
		||||
    // );
 | 
			
		||||
    map.reachable_count_after(&map.start, n)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -168,13 +191,14 @@ fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
 | 
			
		||||
 | 
			
		||||
// PROBLEM 2 solution
 | 
			
		||||
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
 | 
			
		||||
    0
 | 
			
		||||
    problem1_impl(input, 26501365)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use crate::*;
 | 
			
		||||
    use std::io::Cursor;
 | 
			
		||||
    use test_case::test_case;
 | 
			
		||||
 | 
			
		||||
    const EXAMPLE: &str = &"...........
 | 
			
		||||
.....###.#.
 | 
			
		||||
@@ -194,9 +218,13 @@ mod tests {
 | 
			
		||||
        assert_eq!(problem1_impl(c.lines(), 6), 16);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn problem2_example() {
 | 
			
		||||
    #[test_case(6, 16)]
 | 
			
		||||
    #[test_case(10, 50)]
 | 
			
		||||
    #[test_case(50, 1594)]
 | 
			
		||||
    #[test_case(100, 6536)]
 | 
			
		||||
    #[test_case(500, 167004)]
 | 
			
		||||
    fn problem2_example(n: usize, expect: u64) {
 | 
			
		||||
        let c = Cursor::new(EXAMPLE);
 | 
			
		||||
        assert_eq!(problem2(c.lines()), 0);
 | 
			
		||||
        assert_eq!(problem1_impl(c.lines(), n), expect);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user