1
1
use std:: collections:: { HashMap , HashSet } ;
2
2
use anyhow:: Result ;
3
3
4
+ #[ cfg( not( feature="timing" ) ) ]
4
5
fn main ( ) -> Result < ( ) > {
5
6
let mut misplaced_sum = 0 ;
6
7
let mut badge_sum = 0 ;
@@ -15,13 +16,34 @@ fn main() -> Result<()> {
15
16
Ok ( ( ) )
16
17
}
17
18
19
+ // Benchmark for the intersection functions
20
+ #[ cfg( feature="timing" ) ]
21
+ fn main ( ) -> Result < ( ) > {
22
+ use advent_2022:: terminal:: elapsed;
23
+ let str_len = 10000 ;
24
+ let vec_len = 1000 ;
25
+ let group: Vec < _ > = include_str ! ( "example.txt" ) . lines ( ) . take ( 3 )
26
+ . map ( |e| e. chars ( ) . cycle ( ) . take ( str_len) . collect :: < String > ( ) )
27
+ . collect ( ) ;
28
+
29
+ for i in 1 ..=group. len ( ) {
30
+ let repeated: Vec < _ > = group[ ..i] . iter ( ) . map ( |s| s. as_str ( ) ) . cycle ( ) . take ( vec_len) . collect ( ) ;
31
+ elapsed ! ( format!( "all_1 subset {}" , i) , intersect_all_1( & repeated) . len( ) ) ;
32
+ elapsed ! ( format!( "all_2 subset {}" , i) , intersect_all_2( & repeated) . len( ) ) ;
33
+ elapsed ! ( format!( "all_3 subset {}" , i) , intersect_all_3( & repeated) . len( ) ) ;
34
+ println ! ( ) ;
35
+ }
36
+
37
+ Ok ( ( ) )
38
+ }
39
+
18
40
fn misplaced_item ( elf : & str ) -> HashSet < char > {
19
41
let left = & elf[ ..elf. len ( ) /2 ] ;
20
42
let right = & elf[ elf. len ( ) /2 ..] ;
21
43
intersect_all_2 ( & [ left, right] )
22
44
}
23
45
24
- #[ cfg( test) ]
46
+ #[ cfg( any ( test, feature= "timing" ) ) ]
25
47
fn intersect_all_1 ( inputs : & [ & str ] ) -> HashSet < char > {
26
48
let packs: Vec < _ > = inputs. iter ( ) . map ( |p| p. chars ( ) . collect :: < HashSet < _ > > ( ) ) . collect ( ) ;
27
49
let all_items: HashSet < _ > = inputs. iter ( ) . flat_map ( |p| p. chars ( ) ) . collect ( ) ;
@@ -39,13 +61,29 @@ fn intersect_all_2(inputs: &[&str]) -> HashSet<char> {
39
61
* v = keep;
40
62
}
41
63
}
42
- // could also set v=false here and not invert the keep variable, guessing it'd be slower
43
64
intersection. retain ( |_, & mut v| v == keep) ;
44
65
keep = !keep;
45
66
}
46
67
intersection. into_keys ( ) . collect ( )
47
68
}
48
69
70
+ // same as all_2 but utilizes .retain()'s mutable value; marginally slower than all_2
71
+ #[ cfg( any( test, feature="timing" ) ) ]
72
+ fn intersect_all_3 ( inputs : & [ & str ] ) -> HashSet < char > {
73
+ if inputs. is_empty ( ) { return HashSet :: new ( ) ; }
74
+ let mut inputs = inputs. iter ( ) ;
75
+ let mut intersection: HashMap < _ , _ > = inputs. next ( ) . expect ( "non-empty" ) . chars ( ) . map ( |c| ( c, false ) ) . collect ( ) ;
76
+ for input in inputs {
77
+ for c in input. chars ( ) {
78
+ if let Some ( v) = intersection. get_mut ( & c) {
79
+ * v = true ;
80
+ }
81
+ }
82
+ intersection. retain ( |_, v| { let ret = * v; * v = false ; ret } ) ;
83
+ }
84
+ intersection. into_keys ( ) . collect ( )
85
+ }
86
+
49
87
fn score_set ( common : & HashSet < char > ) -> u32 {
50
88
assert_eq ! ( common. len( ) , 1 ) ;
51
89
score ( * common. iter ( ) . next ( ) . expect ( "non-empty" ) )
@@ -90,5 +128,6 @@ mod tests {
90
128
intersect_impls ! {
91
129
all_1: intersect_all_1,
92
130
all_2: intersect_all_2,
131
+ all_3: intersect_all_3,
93
132
}
94
133
}
0 commit comments