Refactor grouping count into a trait.

This commit is contained in:
2018-12-06 16:19:52 +01:00
parent d53100e591
commit c44ebaa238
4 changed files with 54 additions and 27 deletions

View File

@@ -1,3 +1,5 @@
use std::collections::HashMap;
use std::hash::Hash;
use std::io; use std::io;
/// Apply Erathostenes's sieve to the supplied array /// Apply Erathostenes's sieve to the supplied array
@@ -7,7 +9,7 @@ use std::io;
/// * `dest` - the destination slice to fill with the sieve. This is /// * `dest` - the destination slice to fill with the sieve. This is
/// assumed to be filled with "true" before being handed to this /// assumed to be filled with "true" before being handed to this
/// method. /// method.
pub fn prime_sieve(dest: &mut[bool]) { pub fn prime_sieve(dest: &mut [bool]) {
if dest.len() >= 1 { if dest.len() >= 1 {
dest[0] = false; dest[0] = false;
} }
@@ -20,7 +22,7 @@ pub fn prime_sieve(dest: &mut[bool]) {
for i in 1..(limit + 1) { for i in 1..(limit + 1) {
if !dest[i] { if !dest[i] {
continue continue;
} }
for j in ((i * i)..(dest.len())).step_by(i) { for j in ((i * i)..(dest.len())).step_by(i) {
@@ -48,6 +50,35 @@ pub fn trim_back(input: &mut Vec<u8>) {
} }
} }
/// An interface to count elements in particular categories.
pub trait GroupingCount {
/// The type of the categories under inspection
type Type;
/// Count the occurrence of all possible values.
///
/// This method will return a map from a value to its occurrence rate.
fn grouping_count(&mut self) -> HashMap<Self::Type, usize>;
}
impl<T> GroupingCount for T
where T: Iterator,
T::Item: Eq + Hash {
type Type = T::Item;
fn grouping_count(&mut self) -> HashMap<Self::Type, usize>
{
let mut counts = HashMap::new();
for element in self {
*counts.entry(element).or_insert(0) += 1;
}
counts
}
}
/// Solution trait /// Solution trait
/// ///
/// Every day's solution should implement this function so that it can /// Every day's solution should implement this function so that it can
@@ -79,4 +110,12 @@ mod tests {
assert_eq!(output, input); assert_eq!(output, input);
} }
#[test]
fn test_grouping_count() {
let result = [1, 1, 2, 2, 3, 1].iter().grouping_count();
assert_eq!(3, result[&1]);
assert_eq!(2, result[&2]);
assert_eq!(1, result[&3]);
}
} }

View File

@@ -3,16 +3,11 @@ use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use common; use common;
use common::GroupingCount;
/// Count the occurrence characters in a string. /// Count the occurrence characters in a string.
fn count_chars(word: &str) -> HashMap<char, u32> { fn count_chars(word: &str) -> HashMap<char, usize> {
let mut counts: HashMap<char, u32> = HashMap::new(); word.chars().grouping_count()
for c in word.chars() {
*counts.entry(c).or_insert(0) += 1;
}
counts
} }
/// Compute the number of different positions between two strings. /// Compute the number of different positions between two strings.

View File

@@ -3,9 +3,11 @@ use std::io;
use std::io::BufRead; use std::io::BufRead;
use std::ops::Range; use std::ops::Range;
use common;
use regex; use regex;
use common;
use common::GroupingCount;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct Claim { struct Claim {
x: usize, x: usize,
@@ -60,15 +62,10 @@ impl Day03 {
} }
} }
fn get_claims(&self) -> HashMap<(usize, usize), i32> { fn get_claims(&self) -> HashMap<(usize, usize), usize> {
let mut claims = HashMap::new(); self.claims.iter()
for claim in &self.claims { .flat_map(|x| x.range())
for coordinate in claim.range() { .grouping_count()
*claims.entry(coordinate).or_insert(0) += 1;
}
}
claims
} }
} }

View File

@@ -1,10 +1,10 @@
use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
use std::io::BufRead; use std::io::BufRead;
use std::io::BufReader; use std::io::BufReader;
use std::io::Read; use std::io::Read;
use common::Solution; use common::Solution;
use common::GroupingCount;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct Coordinate { struct Coordinate {
@@ -124,13 +124,9 @@ impl Solution for Day06 {
infinite.extend([grid[y][0], grid[y][self.xmax]].iter().filter_map(claim_filter)); infinite.extend([grid[y][0], grid[y][self.xmax]].iter().filter_map(claim_filter));
} }
let mut counts = HashMap::new(); let counts = grid.iter().flat_map(|x| x.iter())
for instance in grid.iter().flat_map(|x| x.iter())
.filter_map(claim_filter) .filter_map(claim_filter)
.filter(|x| !infinite.contains(x)) { .filter(|x| !infinite.contains(x)).grouping_count();
*counts.entry(instance).or_insert(0) += 1;
}
format!("{}", counts.values().max().unwrap()) format!("{}", counts.values().max().unwrap())
} }