Compare commits
No commits in common. "0e475d9264b1147d02f78c6dc5a93010d94ccaa2" and "27e5979042bda85ca719cd189d696fc57b75d07c" have entirely different histories.
0e475d9264
...
27e5979042
|
@ -2,31 +2,6 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "minimal-lexical"
|
|
||||||
version = "0.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nom"
|
|
||||||
version = "7.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"minimal-lexical",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "problems"
|
name = "problems"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
|
||||||
"nom",
|
|
||||||
]
|
|
||||||
|
|
|
@ -6,4 +6,3 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nom = { version = "7" }
|
|
||||||
|
|
1000
2022/data/day4.txt
1000
2022/data/day4.txt
File diff suppressed because it is too large
Load Diff
148
2022/src/day4.rs
148
2022/src/day4.rs
|
@ -1,148 +0,0 @@
|
||||||
use nom::{self, bytes::complete::tag, character::complete, sequence::separated_pair, IResult};
|
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
const INPUT: &str = include_str!("../data/day4.txt");
|
|
||||||
|
|
||||||
pub fn part1() -> String {
|
|
||||||
format!("{}", count_full_containments(&input(INPUT)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn part2() -> String {
|
|
||||||
format!("{}", count_overlaps(&input(INPUT)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn count_full_containments(pairings: &Vec<ElfPairing>) -> u32 {
|
|
||||||
pairings
|
|
||||||
.into_iter()
|
|
||||||
.filter(|pairing| pairing.has_full_containment())
|
|
||||||
.count() as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
fn count_overlaps(pairings: &Vec<ElfPairing>) -> u32 {
|
|
||||||
pairings
|
|
||||||
.into_iter()
|
|
||||||
.filter(|pairing| pairing.has_overlap())
|
|
||||||
.count() as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ElfPairing {
|
|
||||||
elf1: Vec<u32>,
|
|
||||||
elf2: Vec<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ElfPairing {
|
|
||||||
fn has_full_containment(&self) -> bool {
|
|
||||||
let elf1 = self.elf1.iter().cloned().collect::<HashSet<u32>>();
|
|
||||||
let elf2 = self.elf2.iter().cloned().collect::<HashSet<u32>>();
|
|
||||||
elf1.is_subset(&elf2) || elf2.is_subset(&elf1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_overlap(&self) -> bool {
|
|
||||||
let element_count = self.elf1.len() + self.elf2.len();
|
|
||||||
let combined_set = self
|
|
||||||
.elf1
|
|
||||||
.iter()
|
|
||||||
.chain(self.elf2.iter())
|
|
||||||
.cloned()
|
|
||||||
.collect::<HashSet<u32>>();
|
|
||||||
combined_set.len() < element_count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn input(data: &str) -> Vec<ElfPairing> {
|
|
||||||
data.lines()
|
|
||||||
.map(|line| {
|
|
||||||
let (_, pairing) = elf_pair(line).unwrap();
|
|
||||||
pairing
|
|
||||||
})
|
|
||||||
.collect::<Vec<ElfPairing>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn elf_pair(input: &str) -> IResult<&str, ElfPairing> {
|
|
||||||
let (input, elf1) = elf_range(input)?;
|
|
||||||
let (input, _) = tag(",")(input)?;
|
|
||||||
let (input, elf2) = elf_range(input)?;
|
|
||||||
|
|
||||||
Ok((input, ElfPairing { elf1, elf2 }))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn elf_range(input: &str) -> IResult<&str, Vec<u32>> {
|
|
||||||
let (input, start) = complete::u32(input)?;
|
|
||||||
let (input, _) = tag("-")(input)?;
|
|
||||||
let (input, end) = complete::u32(input)?;
|
|
||||||
|
|
||||||
Ok((input, (start..end + 1).collect::<Vec<u32>>()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
const TEST_DATA: &str = "2-4,6-8
|
|
||||||
2-3,4-5
|
|
||||||
5-7,7-9
|
|
||||||
2-8,3-7
|
|
||||||
6-6,4-6
|
|
||||||
2-6,4-8";
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_gets_a_hashset_from_a_range() {
|
|
||||||
assert_eq!(vec![2, 3, 4], (2..5).collect::<Vec<u32>>());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_input<F>(test: F)
|
|
||||||
where
|
|
||||||
F: Fn(Vec<ElfPairing>) -> () + std::panic::UnwindSafe,
|
|
||||||
{
|
|
||||||
test(input(TEST_DATA));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_parses_input_correctly() {
|
|
||||||
with_input(|pairings| {
|
|
||||||
assert_eq!(vec![2, 3, 4], pairings[0].elf1);
|
|
||||||
assert_eq!(vec![6, 7, 8], pairings[0].elf2);
|
|
||||||
|
|
||||||
assert_eq!(vec![6], pairings[4].elf1);
|
|
||||||
assert_eq!(vec![4, 5, 6], pairings[4].elf2);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_checks_full_containment() {
|
|
||||||
with_input(|pairings| {
|
|
||||||
assert!(!pairings[0].has_full_containment());
|
|
||||||
assert!(!pairings[1].has_full_containment());
|
|
||||||
assert!(!pairings[2].has_full_containment());
|
|
||||||
assert!(pairings[3].has_full_containment());
|
|
||||||
assert!(pairings[4].has_full_containment());
|
|
||||||
assert!(!pairings[5].has_full_containment());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_counts_full_containments() {
|
|
||||||
with_input(|pairings| {
|
|
||||||
assert_eq!(2, count_full_containments(&pairings));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_checks_overlap() {
|
|
||||||
with_input(|pairings| {
|
|
||||||
assert!(!pairings[0].has_overlap());
|
|
||||||
assert!(!pairings[1].has_overlap());
|
|
||||||
assert!(pairings[2].has_overlap());
|
|
||||||
assert!(pairings[3].has_overlap());
|
|
||||||
assert!(pairings[4].has_overlap());
|
|
||||||
assert!(pairings[5].has_overlap());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_checks_part1() {
|
|
||||||
let pairings = input(INPUT);
|
|
||||||
assert_eq!(466, count_full_containments(&pairings));
|
|
||||||
assert_eq!(865, count_overlaps(&pairings));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
mod day1;
|
mod day1;
|
||||||
mod day2;
|
mod day2;
|
||||||
mod day3;
|
mod day3;
|
||||||
mod day4;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let day = std::env::args().skip(1).next();
|
let day = std::env::args().skip(1).next();
|
||||||
|
@ -13,8 +12,6 @@ fn main() {
|
||||||
Some("2b") => day2::part2(),
|
Some("2b") => day2::part2(),
|
||||||
Some("3a") => day3::part1(),
|
Some("3a") => day3::part1(),
|
||||||
Some("3b") => day3::part2(),
|
Some("3b") => day3::part2(),
|
||||||
Some("4a") => day4::part1(),
|
|
||||||
Some("4b") => day4::part2(),
|
|
||||||
_ => panic!("unrecognized day"),
|
_ => panic!("unrecognized day"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue