diff --git a/Cargo.lock b/Cargo.lock index d5f15c4..4fc128f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,7 @@ dependencies = [ "itertools", "num", "prev-iter", + "rand 0.8.5", "regex", "rust-crypto", "strum", @@ -68,6 +69,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "either" version = "1.9.0" @@ -86,6 +93,17 @@ version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +[[package]] +name = "getrandom" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + [[package]] name = "heck" version = "0.4.1" @@ -195,6 +213,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "prev-iter" version = "0.1.2" @@ -242,6 +266,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -257,6 +302,15 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -405,7 +459,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", - "wasi", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] @@ -421,6 +475,12 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index a52ad24..71455a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,4 +16,5 @@ strum = "0.25.0" strum_macros = "0.25" prev-iter = "0.1.2" regex = "1.10.2" -num = "0.4.1" \ No newline at end of file +num = "0.4.1" +rand = "0.8.5" diff --git a/src/day25.rs b/src/day25.rs new file mode 100644 index 0000000..c1f6616 --- /dev/null +++ b/src/day25.rs @@ -0,0 +1,120 @@ +use std::collections::{HashSet, HashMap}; +use rand::Rng; + +use aoc_runner_derive::{aoc, aoc_generator}; + +#[derive(Debug, Clone)] +struct Graph { + edges: Vec<(String, String)>, + vertex_count: usize +} + +impl Graph { + fn cut(&mut self) -> (usize, usize, usize) { + let mut contracted_edges = self.edges.clone(); + let mut contracted_vertex_count = self.vertex_count; + let mut contracted: HashMap> = HashMap::new(); + + //for _ in 0..contracted_vertex_count { + while contracted_vertex_count > 2 { + let random = rand::thread_rng().gen_range(0..contracted_edges.len()); + let edge_to_contract = contracted_edges[random].clone(); + if contracted.contains_key(&edge_to_contract.0) { + contracted.get_mut(&edge_to_contract.0.clone()).unwrap().push(edge_to_contract.1.clone()); + } else { + contracted.insert(edge_to_contract.0.clone(), vec![edge_to_contract.1.clone()]); + } + + if contracted.contains_key(&edge_to_contract.1) { + let mut to_append = contracted.clone().get_mut(&edge_to_contract.1).unwrap().clone(); + contracted.get_mut(&edge_to_contract.0).unwrap().append(&mut to_append); + contracted.remove(&edge_to_contract.1); + } + + let mut new_edges: Vec<(String, String)> = vec![]; + + for edge in contracted_edges { + if edge.1 == edge_to_contract.1 { + new_edges.push((edge.0.clone(), edge_to_contract.0.clone())); + } else if edge.0 == edge_to_contract.1 { + new_edges.push((edge_to_contract.0.clone(), edge.1.clone())); + } else { + new_edges.push(edge.clone()); + } + } + + let tmp = new_edges.iter().cloned().filter(|x| x.0 != x.1).collect::>(); + + contracted_edges = tmp; + contracted_vertex_count -= 1; + + } + + let counts = contracted.iter().map(|x| x.1.len() + 1).collect::>(); + + return (contracted_edges.len(), counts[0], *counts.last().unwrap()); + } +} + +#[aoc_generator(day25)] +fn parse(input: &str) -> Graph { + let input = input.lines().flat_map(|line| { + let line = line.split(' ').map(|x| x.trim_end_matches(':').to_string()).collect::>(); + line[1..].iter().cloned().map(|x| (line[0].clone(), x)).collect::>() + }).collect::>(); + + let vertex_count = input.clone().into_iter().flat_map(|x| vec![x.0, x.1]).collect::>().len(); + Graph { + edges: input, + vertex_count + } +} + +#[aoc(day25, part1)] +fn part1(graph: &Graph) -> usize { + let graph = &mut graph.clone(); + let mut min_cut = usize::MAX; + let mut count1 = 0; + let mut count2 = 0; + + while min_cut != 3 { + (min_cut, count1, count2) = graph.cut(); + } + + count1 * count2 +} + +// #[aoc(day25, part2)] +// fn part2(input: &str) -> String { +// todo!() +// } + + +#[cfg(test)] +mod tests { + use super::*; + + const EX: &str = r"jqt: rhn xhk nvd +rsh: frs pzl lsr +xhk: hfx +cmg: qnr nvd lhk bvb +rhn: xhk bvb hfx +bvb: xhk hfx +pzl: lsr hfx nvd +qnr: nvd +ntq: jqt hfx bvb xhk +nvd: lhk +lsr: lhk +rzs: qnr cmg lsr rsh +frs: qnr lhk lsr"; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse(EX)), 54); + } + + // #[test] + // fn part2_example() { + // assert_eq!(part2(&parse("")), ""); + // } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index b12b494..8114024 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod day25; mod day24; mod day23; mod day22;