@@ -4,10 +4,18 @@ use std::fmt;
44pub fn least_satisfying < T , P > ( slice : & [ T ] , mut predicate : P ) -> usize
55where
66 T : fmt:: Display + fmt:: Debug ,
7- P : FnMut ( & T ) -> Satisfies ,
7+ P : FnMut ( & T , usize , usize ) -> Satisfies ,
88{
99 let mut cache = BTreeMap :: new ( ) ;
10- let mut predicate = |idx : usize | * cache. entry ( idx) . or_insert_with ( || predicate ( & slice[ idx] ) ) ;
10+ let mut predicate = |idx : usize , rm_no, lm_yes| {
11+ let range = lm_yes - rm_no + 1 ;
12+ // FIXME: This does not consider unknown_ranges.
13+ let remaining = range / 2 ;
14+ let estimate = estimate_steps ( range) ;
15+ * cache
16+ . entry ( idx)
17+ . or_insert_with ( || predicate ( & slice[ idx] , remaining, estimate) )
18+ } ;
1119 let mut unknown_ranges: Vec < ( usize , usize ) > = Vec :: new ( ) ;
1220 // presume that the slice starts with a no
1321 // this should be tested before call
4048 }
4149 }
4250
43- let r = predicate ( next) ;
51+ let r = predicate ( next, rm_no , lm_yes ) ;
4452 match r {
4553 Satisfies :: Yes => {
4654 lm_yes = next;
@@ -52,11 +60,13 @@ where
5260 }
5361 Satisfies :: Unknown => {
5462 let mut left = next;
55- while left > 0 && predicate ( left) == Satisfies :: Unknown {
63+ while left > 0 && predicate ( left, rm_no , lm_yes ) == Satisfies :: Unknown {
5664 left -= 1 ;
5765 }
5866 let mut right = next;
59- while right + 1 < slice. len ( ) && predicate ( right) == Satisfies :: Unknown {
67+ while right + 1 < slice. len ( )
68+ && predicate ( right, rm_no, lm_yes) == Satisfies :: Unknown
69+ {
6070 right += 1 ;
6171 }
6272 unknown_ranges. push ( ( left + 1 , right - 1 ) ) ;
@@ -66,10 +76,33 @@ where
6676 }
6777}
6878
79+ fn estimate_steps ( range : usize ) -> usize {
80+ // Replace with int_log when it is stabilized.
81+ let log2 = |mut n| {
82+ let mut r = 0 ;
83+ while n > 1 {
84+ r += 1 ;
85+ n >>= 1 ;
86+ }
87+ r
88+ } ;
89+ if range < 3 {
90+ return 0 ;
91+ }
92+ let n = log2 ( range) ;
93+ let e = 1 << n;
94+ let x = range - e;
95+ if e < 3 * x {
96+ n
97+ } else {
98+ n - 1
99+ }
100+ }
101+
69102#[ cfg( test) ]
70103mod tests {
71104 use super :: Satisfies :: { No , Unknown , Yes } ;
72- use super :: { least_satisfying, Satisfies } ;
105+ use super :: { estimate_steps , least_satisfying, Satisfies } ;
73106 use quickcheck:: { QuickCheck , TestResult } ;
74107
75108 fn prop ( xs : Vec < Option < bool > > ) -> TestResult {
@@ -89,59 +122,62 @@ mod tests {
89122 }
90123 }
91124
92- let res = least_satisfying ( & satisfies_v, |i| * i) ;
125+ let res = least_satisfying ( & satisfies_v, |i, _ , _ | * i) ;
93126 let exp = first_yes. unwrap ( ) ;
94127 TestResult :: from_bool ( res == exp)
95128 }
96129
97130 #[ test]
98131 fn least_satisfying_1 ( ) {
99132 assert_eq ! (
100- least_satisfying( & [ No , Unknown , Unknown , No , Yes ] , |i| * i) ,
133+ least_satisfying( & [ No , Unknown , Unknown , No , Yes ] , |i, _ , _ | * i) ,
101134 4
102135 ) ;
103136 }
104137
105138 #[ test]
106139 fn least_satisfying_2 ( ) {
107140 assert_eq ! (
108- least_satisfying( & [ No , Unknown , Yes , Unknown , Yes ] , |i| * i) ,
141+ least_satisfying( & [ No , Unknown , Yes , Unknown , Yes ] , |i, _ , _ | * i) ,
109142 2
110143 ) ;
111144 }
112145
113146 #[ test]
114147 fn least_satisfying_3 ( ) {
115- assert_eq ! ( least_satisfying( & [ No , No , No , No , Yes ] , |i| * i) , 4 ) ;
148+ assert_eq ! ( least_satisfying( & [ No , No , No , No , Yes ] , |i, _ , _ | * i) , 4 ) ;
116149 }
117150
118151 #[ test]
119152 fn least_satisfying_4 ( ) {
120- assert_eq ! ( least_satisfying( & [ No , No , Yes , Yes , Yes ] , |i| * i) , 2 ) ;
153+ assert_eq ! ( least_satisfying( & [ No , No , Yes , Yes , Yes ] , |i, _ , _ | * i) , 2 ) ;
121154 }
122155
123156 #[ test]
124157 fn least_satisfying_5 ( ) {
125- assert_eq ! ( least_satisfying( & [ No , Yes , Yes , Yes , Yes ] , |i| * i) , 1 ) ;
158+ assert_eq ! ( least_satisfying( & [ No , Yes , Yes , Yes , Yes ] , |i, _ , _ | * i) , 1 ) ;
126159 }
127160
128161 #[ test]
129162 fn least_satisfying_6 ( ) {
130163 assert_eq ! (
131- least_satisfying( & [ No , Yes , Yes , Unknown , Unknown , Yes , Unknown , Yes ] , |i| * i) ,
164+ least_satisfying(
165+ & [ No , Yes , Yes , Unknown , Unknown , Yes , Unknown , Yes ] ,
166+ |i, _, _| * i
167+ ) ,
132168 1
133169 ) ;
134170 }
135171
136172 #[ test]
137173 fn least_satisfying_7 ( ) {
138- assert_eq ! ( least_satisfying( & [ No , Yes , Unknown , Yes ] , |i| * i) , 1 ) ;
174+ assert_eq ! ( least_satisfying( & [ No , Yes , Unknown , Yes ] , |i, _ , _ | * i) , 1 ) ;
139175 }
140176
141177 #[ test]
142178 fn least_satisfying_8 ( ) {
143179 assert_eq ! (
144- least_satisfying( & [ No , Unknown , No , No , Unknown , Yes , Yes ] , |i| * i) ,
180+ least_satisfying( & [ No , Unknown , No , No , Unknown , Yes , Yes ] , |i, _ , _ | * i) ,
145181 5
146182 ) ;
147183 }
@@ -150,6 +186,22 @@ mod tests {
150186 fn qc_prop ( ) {
151187 QuickCheck :: new ( ) . quickcheck ( prop as fn ( _) -> _ ) ;
152188 }
189+
190+ #[ test]
191+ fn estimates ( ) {
192+ for ( n, expect) in & [
193+ ( 0 , 0 ) ,
194+ ( 1 , 0 ) ,
195+ ( 2 , 0 ) ,
196+ ( 3 , 1 ) ,
197+ ( 4 , 1 ) ,
198+ ( 5 , 1 ) ,
199+ ( 6 , 2 ) ,
200+ ( 150 , 6 ) ,
201+ ] {
202+ assert_eq ! ( estimate_steps( * n) , * expect) ;
203+ }
204+ }
153205}
154206
155207#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
0 commit comments