@@ -4,10 +4,14 @@ 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 , remaining, estimate| {
11+ * cache
12+ . entry ( idx)
13+ . or_insert_with ( || predicate ( & slice[ idx] , remaining, estimate) )
14+ } ;
1115 let mut unknown_ranges: Vec < ( usize , usize ) > = Vec :: new ( ) ;
1216 // presume that the slice starts with a no
1317 // this should be tested before call
4044 }
4145 }
4246
43- let r = predicate ( next) ;
47+ let mut range = lm_yes - rm_no + 1 ;
48+ // FIXME: This does not consider unknown_ranges.
49+ let mut remaining = range / 2 ;
50+ let estimate = estimate_steps ( range) ;
51+ let r = predicate ( next, remaining, estimate) ;
4452 match r {
4553 Satisfies :: Yes => {
4654 lm_yes = next;
@@ -52,12 +60,20 @@ where
5260 }
5361 Satisfies :: Unknown => {
5462 let mut left = next;
55- while left > 0 && predicate ( left) == Satisfies :: Unknown {
63+ while left > 0
64+ && predicate ( left, remaining, estimate_steps ( range) ) == Satisfies :: Unknown
65+ {
5666 left -= 1 ;
67+ remaining = remaining. saturating_sub ( 1 ) ;
68+ range = range. saturating_sub ( 1 ) ;
5769 }
5870 let mut right = next;
59- while right + 1 < slice. len ( ) && predicate ( right) == Satisfies :: Unknown {
71+ while right + 1 < slice. len ( )
72+ && predicate ( right, remaining, estimate_steps ( range) ) == Satisfies :: Unknown
73+ {
6074 right += 1 ;
75+ remaining = remaining. saturating_sub ( 1 ) ;
76+ range = range. saturating_sub ( 1 ) ;
6177 }
6278 unknown_ranges. push ( ( left + 1 , right - 1 ) ) ;
6379 next = left;
@@ -66,10 +82,33 @@ where
6682 }
6783}
6884
85+ fn estimate_steps ( range : usize ) -> usize {
86+ // Replace with int_log when it is stabilized.
87+ let log2 = |mut n| {
88+ let mut r = 0 ;
89+ while n > 1 {
90+ r += 1 ;
91+ n >>= 1 ;
92+ }
93+ r
94+ } ;
95+ if range < 3 {
96+ return 0 ;
97+ }
98+ let n = log2 ( range) ;
99+ let e = 1 << n;
100+ let x = range - e;
101+ if e < 3 * x {
102+ n
103+ } else {
104+ n - 1
105+ }
106+ }
107+
69108#[ cfg( test) ]
70109mod tests {
71110 use super :: Satisfies :: { No , Unknown , Yes } ;
72- use super :: { least_satisfying, Satisfies } ;
111+ use super :: { estimate_steps , least_satisfying, Satisfies } ;
73112 use quickcheck:: { QuickCheck , TestResult } ;
74113
75114 fn prop ( xs : Vec < Option < bool > > ) -> TestResult {
@@ -89,59 +128,62 @@ mod tests {
89128 }
90129 }
91130
92- let res = least_satisfying ( & satisfies_v, |i| * i) ;
131+ let res = least_satisfying ( & satisfies_v, |i, _ , _ | * i) ;
93132 let exp = first_yes. unwrap ( ) ;
94133 TestResult :: from_bool ( res == exp)
95134 }
96135
97136 #[ test]
98137 fn least_satisfying_1 ( ) {
99138 assert_eq ! (
100- least_satisfying( & [ No , Unknown , Unknown , No , Yes ] , |i| * i) ,
139+ least_satisfying( & [ No , Unknown , Unknown , No , Yes ] , |i, _ , _ | * i) ,
101140 4
102141 ) ;
103142 }
104143
105144 #[ test]
106145 fn least_satisfying_2 ( ) {
107146 assert_eq ! (
108- least_satisfying( & [ No , Unknown , Yes , Unknown , Yes ] , |i| * i) ,
147+ least_satisfying( & [ No , Unknown , Yes , Unknown , Yes ] , |i, _ , _ | * i) ,
109148 2
110149 ) ;
111150 }
112151
113152 #[ test]
114153 fn least_satisfying_3 ( ) {
115- assert_eq ! ( least_satisfying( & [ No , No , No , No , Yes ] , |i| * i) , 4 ) ;
154+ assert_eq ! ( least_satisfying( & [ No , No , No , No , Yes ] , |i, _ , _ | * i) , 4 ) ;
116155 }
117156
118157 #[ test]
119158 fn least_satisfying_4 ( ) {
120- assert_eq ! ( least_satisfying( & [ No , No , Yes , Yes , Yes ] , |i| * i) , 2 ) ;
159+ assert_eq ! ( least_satisfying( & [ No , No , Yes , Yes , Yes ] , |i, _ , _ | * i) , 2 ) ;
121160 }
122161
123162 #[ test]
124163 fn least_satisfying_5 ( ) {
125- assert_eq ! ( least_satisfying( & [ No , Yes , Yes , Yes , Yes ] , |i| * i) , 1 ) ;
164+ assert_eq ! ( least_satisfying( & [ No , Yes , Yes , Yes , Yes ] , |i, _ , _ | * i) , 1 ) ;
126165 }
127166
128167 #[ test]
129168 fn least_satisfying_6 ( ) {
130169 assert_eq ! (
131- least_satisfying( & [ No , Yes , Yes , Unknown , Unknown , Yes , Unknown , Yes ] , |i| * i) ,
170+ least_satisfying(
171+ & [ No , Yes , Yes , Unknown , Unknown , Yes , Unknown , Yes ] ,
172+ |i, _, _| * i
173+ ) ,
132174 1
133175 ) ;
134176 }
135177
136178 #[ test]
137179 fn least_satisfying_7 ( ) {
138- assert_eq ! ( least_satisfying( & [ No , Yes , Unknown , Yes ] , |i| * i) , 1 ) ;
180+ assert_eq ! ( least_satisfying( & [ No , Yes , Unknown , Yes ] , |i, _ , _ | * i) , 1 ) ;
139181 }
140182
141183 #[ test]
142184 fn least_satisfying_8 ( ) {
143185 assert_eq ! (
144- least_satisfying( & [ No , Unknown , No , No , Unknown , Yes , Yes ] , |i| * i) ,
186+ least_satisfying( & [ No , Unknown , No , No , Unknown , Yes , Yes ] , |i, _ , _ | * i) ,
145187 5
146188 ) ;
147189 }
@@ -150,6 +192,22 @@ mod tests {
150192 fn qc_prop ( ) {
151193 QuickCheck :: new ( ) . quickcheck ( prop as fn ( _) -> _ ) ;
152194 }
195+
196+ #[ test]
197+ fn estimates ( ) {
198+ for ( n, expect) in & [
199+ ( 0 , 0 ) ,
200+ ( 1 , 0 ) ,
201+ ( 2 , 0 ) ,
202+ ( 3 , 1 ) ,
203+ ( 4 , 1 ) ,
204+ ( 5 , 1 ) ,
205+ ( 6 , 2 ) ,
206+ ( 150 , 6 ) ,
207+ ] {
208+ assert_eq ! ( estimate_steps( * n) , * expect) ;
209+ }
210+ }
153211}
154212
155213#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
0 commit comments