@@ -74,7 +74,7 @@ where Self: Debug
74
74
75
75
#[ derive( Debug ) ]
76
76
pub struct Partition {
77
- pub ends : Vec < ( usize , usize ) > ,
77
+ pub ends : Vec < ( usize , usize ) > , // index, partition point
78
78
pub total : usize ,
79
79
}
80
80
@@ -117,8 +117,11 @@ where
117
117
T : List + ' a ,
118
118
T :: Item < ' a > : Debug ,
119
119
{
120
+ // The cut point value.
120
121
target : T :: Item < ' a > ,
122
+ // The domain of partition point in each list, and also the domain of the generated task size in each list.
121
123
domains : Vec < EndDomain > ,
124
+ // The size domain of the generated task if the current target is used as the cut point.
122
125
sum : EndDomain ,
123
126
}
124
127
@@ -136,6 +139,7 @@ where T: List
136
139
}
137
140
138
141
pub fn init ( & mut self ) -> bool {
142
+ // Take the smallest first and the smallest last of all the lists as the initial target range.
139
143
let target: ( Option < T :: Item < ' a > > , Option < T :: Item < ' a > > ) =
140
144
self . all_list . iter ( ) . fold ( ( None , None ) , |( min, max) , ls| {
141
145
let min = match ( min, ls. first ( ) ) {
@@ -151,9 +155,8 @@ where T: List
151
155
152
156
( min, max)
153
157
} ) ;
154
- let ( min_target, max_target) = if let ( Some ( min) , Some ( max) ) = target {
155
- ( min, max)
156
- } else {
158
+ let ( Some ( min_target) , Some ( max_target) ) = target else {
159
+ // invalid empty input
157
160
return false ;
158
161
} ;
159
162
@@ -189,7 +192,7 @@ where T: List
189
192
190
193
pub fn is_small_task ( & mut self ) -> bool {
191
194
loop {
192
- let sum = self . do_search_max ( Some ( 8 ) ) ;
195
+ let sum = self . reduce_max_domain ( Some ( 8 ) ) ;
193
196
match self . expect . overlaps ( sum) {
194
197
Overlap :: Left => return true ,
195
198
Overlap :: Right => return false ,
@@ -203,7 +206,7 @@ where T: List
203
206
for _ in 0 ..max_iter {
204
207
match self . overlaps ( ) {
205
208
( _, _, Overlap :: Cross ) => {
206
- let sum = self . do_search_max ( Some ( n) ) ;
209
+ let sum = self . reduce_max_domain ( Some ( n) ) ;
207
210
if self . is_finish ( sum) {
208
211
return Partition :: new ( self . max_target . unwrap ( ) ) ;
209
212
}
@@ -221,7 +224,7 @@ where T: List
221
224
Some ( Overlap :: Cross ) ,
222
225
Overlap :: Right ,
223
226
) => {
224
- let sum = self . do_search_mid ( Some ( n) ) ;
227
+ let sum = self . reduce_mid_domain ( Some ( n) ) ;
225
228
match self . expect . overlaps ( sum) {
226
229
Overlap :: Right => self . cut_right ( ) ,
227
230
Overlap :: Left if matches ! ( min_overlap, Overlap :: Left ) => self . cut_left ( ) ,
@@ -232,7 +235,7 @@ where T: List
232
235
}
233
236
}
234
237
( Overlap :: Cross , Some ( Overlap :: Left ) , Overlap :: Right ) => {
235
- let sum = self . do_search_min ( Some ( n) ) ;
238
+ let sum = self . reduce_min_domain ( Some ( n) ) ;
236
239
match self . expect . overlaps ( sum) {
237
240
Overlap :: Left => self . cut_left ( ) ,
238
241
Overlap :: Cross if sum. done ( ) => {
@@ -251,19 +254,19 @@ where T: List
251
254
} ;
252
255
}
253
256
254
- self . do_search_max ( None ) ;
257
+ self . reduce_max_domain ( None ) ;
255
258
Partition :: new ( self . max_target . unwrap ( ) )
256
259
}
257
260
258
- fn do_search_max ( & mut self , n : Option < usize > ) -> EndDomain {
261
+ fn reduce_max_domain ( & mut self , n : Option < usize > ) -> EndDomain {
259
262
do_search ( self . all_list , self . max_target . as_mut ( ) . unwrap ( ) , n)
260
263
}
261
264
262
- fn do_search_min ( & mut self , n : Option < usize > ) -> EndDomain {
265
+ fn reduce_min_domain ( & mut self , n : Option < usize > ) -> EndDomain {
263
266
do_search ( self . all_list , self . min_target . as_mut ( ) . unwrap ( ) , n)
264
267
}
265
268
266
- fn do_search_mid ( & mut self , n : Option < usize > ) -> EndDomain {
269
+ fn reduce_mid_domain ( & mut self , n : Option < usize > ) -> EndDomain {
267
270
do_search ( self . all_list , self . mid_target . as_mut ( ) . unwrap ( ) , n)
268
271
}
269
272
@@ -290,11 +293,8 @@ where T: List
290
293
if max_domain. is_zero ( ) {
291
294
continue ;
292
295
}
293
- let five = EndDomain {
294
- min : min_domain. min ,
295
- max : max_domain. min ,
296
- }
297
- . five_point ( ) ;
296
+
297
+ let five = min_domain. merge ( max_domain) . five_point ( ) ;
298
298
for v in five. into_iter ( ) . filter_map ( |i| {
299
299
let v = ls. index ( i) ;
300
300
if v >= * min_target && v <= * max_target {
@@ -336,6 +336,7 @@ where T: List
336
336
}
337
337
338
338
fn overlaps ( & self ) -> ( Overlap , Option < Overlap > , Overlap ) {
339
+ // Compare expect task size domain with min_target,mid_target and max_target task size domain.
339
340
(
340
341
self . expect . overlaps ( self . min_target . as_ref ( ) . unwrap ( ) . sum ) ,
341
342
self . mid_target
@@ -392,11 +393,16 @@ where
392
393
393
394
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Default ) ]
394
395
pub struct EndDomain {
395
- pub min : usize ,
396
- pub max : usize ,
396
+ min : usize ,
397
+ max : usize ,
397
398
}
398
399
399
400
impl EndDomain {
401
+ pub fn new ( min : usize , max : usize ) -> EndDomain {
402
+ assert ! ( min <= max) ;
403
+ EndDomain { min, max }
404
+ }
405
+
400
406
fn done ( & self ) -> bool {
401
407
self . min == self . max
402
408
}
@@ -453,6 +459,13 @@ impl EndDomain {
453
459
] ,
454
460
}
455
461
}
462
+
463
+ fn merge ( & self , other : & EndDomain ) -> EndDomain {
464
+ EndDomain {
465
+ min : self . min . min ( other. min ) ,
466
+ max : self . max . max ( other. max ) ,
467
+ }
468
+ }
456
469
}
457
470
458
471
#[ derive( Debug ) ]
@@ -481,15 +494,18 @@ impl std::iter::Sum for EndDomain {
481
494
482
495
impl From < std:: ops:: RangeInclusive < usize > > for EndDomain {
483
496
fn from ( value : std:: ops:: RangeInclusive < usize > ) -> Self {
484
- EndDomain {
485
- min : * value. start ( ) ,
486
- max : * value. end ( ) ,
487
- }
497
+ EndDomain :: new ( * value. start ( ) , * value. end ( ) )
488
498
}
489
499
}
490
500
491
501
#[ cfg( test) ]
492
502
mod tests {
503
+ use std:: iter:: repeat_with;
504
+
505
+ use rand:: rngs:: StdRng ;
506
+ use rand:: Rng ;
507
+ use rand:: SeedableRng ;
508
+
493
509
use super :: * ;
494
510
495
511
impl List for & [ i32 ] {
@@ -525,35 +541,67 @@ mod tests {
525
541
run_test ( & all_list, ( 5 ..=10 ) . into ( ) , 10 ) ;
526
542
}
527
543
544
+ {
545
+ let all_list = issue_16923 ( ) ;
546
+
547
+ let all_list: Vec < _ > = all_list. iter ( ) . map ( |v| v. as_slice ( ) ) . collect ( ) ;
548
+ run_test ( & all_list, ( 5 ..=100 ) . into ( ) , 20 ) ;
549
+ }
550
+
528
551
for _ in 0 ..100 {
529
- let all_list = rand_data ( ) ;
552
+ let all_list = rand_data ( rand :: random ( ) ) ;
530
553
let all_list: Vec < _ > = all_list. iter ( ) . map ( |v| v. as_slice ( ) ) . collect ( ) ;
531
554
532
- run_test ( & all_list, ( 5 ..=10 ) . into ( ) , 10 )
555
+ run_test ( & all_list, ( 5 ..=100 ) . into ( ) , 20 )
533
556
}
534
557
}
535
558
536
- fn rand_data ( ) -> Vec < Vec < i32 > > {
537
- use rand:: Rng ;
538
- let mut rng = rand:: thread_rng ( ) ;
559
+ fn rand_data ( seed : u64 ) -> Vec < Vec < i32 > > {
560
+ let mut rng = StdRng :: seed_from_u64 ( seed) ;
539
561
540
- ( 0 ..5 )
541
- . map ( |_| {
542
- let rows: usize = rng. gen_range ( 0 ..=20 ) ;
543
- let mut data = ( 0 ..rows)
544
- . map ( |_| rng. gen_range ( 0 ..=1000 ) )
545
- . collect :: < Vec < _ > > ( ) ;
546
- data. sort ( ) ;
547
- data
548
- } )
549
- . collect :: < Vec < _ > > ( )
562
+ let list = rng. gen_range ( 1 ..=10 ) ;
563
+ repeat_with ( || {
564
+ let rows = rng. gen_range ( 0 ..=40 ) ;
565
+ let mut data = repeat_with ( || rng. gen_range ( 0 ..=1000 ) )
566
+ . take ( rows)
567
+ . collect :: < Vec < _ > > ( ) ;
568
+ data. sort ( ) ;
569
+ data
570
+ } )
571
+ . take ( list)
572
+ . collect :: < Vec < _ > > ( )
573
+ }
574
+
575
+ fn issue_16923 ( ) -> Vec < Vec < i32 > > {
576
+ vec ! [
577
+ vec![ 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ] ,
578
+ vec![
579
+ 3 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 8 , 13 , 13 , 13 , 13 , 13 , 13 ,
580
+ 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 18 ,
581
+ ] ,
582
+ vec![ 6 , 6 , 6 , 6 , 6 ] ,
583
+ vec![
584
+ 2 , 4 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 7 , 11 , 12 , 14 , 15 , 16 , 19 ,
585
+ ] ,
586
+ vec![
587
+ 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,
588
+ ] ,
589
+ vec![
590
+ 1 , 5 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,
591
+ 11 , 12 , 14 , 15 , 17 , 18 , 21 , 22 , 24 , 25 , 27 ,
592
+ ] ,
593
+ vec![
594
+ 0 , 9 , 10 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 13 , 20 ,
595
+ 23 , 26 , 27 , 27 , 27 , 27 , 27 , 27 , 27 , 28 ,
596
+ ] ,
597
+ ]
550
598
}
551
599
552
600
fn run_test ( all_list : & [ & [ i32 ] ] , expect_size : EndDomain , max_iter : usize ) {
553
601
let mut candidate = Candidate :: new ( all_list, expect_size) ;
554
602
555
603
let got = if candidate. init ( ) {
556
- candidate. calc_partition ( 3 , max_iter)
604
+ candidate. calc_partition ( 4 , max_iter)
557
605
} else {
558
606
let sum: usize = all_list. iter ( ) . map ( |ls| ls. len ( ) ) . sum ( ) ;
559
607
assert_eq ! ( sum, 0 ) ;
@@ -574,11 +622,13 @@ mod tests {
574
622
( ls[ ..end] . last ( ) , ls[ end..] . first ( ) )
575
623
} )
576
624
. fold ( ( None , None ) , |acc, ( end, start) | {
577
- ( acc. 0 . max ( end) , match ( acc. 1 , start) {
625
+ let max_end = acc. 0 . max ( end) ;
626
+ let min_start = match ( acc. 1 , start) {
578
627
( None , None ) => None ,
579
628
( None , v @ Some ( _) ) | ( v @ Some ( _) , None ) => v,
580
629
( Some ( a) , Some ( b) ) => Some ( a. min ( b) ) ,
581
- } )
630
+ } ;
631
+ ( max_end, min_start)
582
632
} ) ;
583
633
match x {
584
634
( Some ( a) , Some ( b) ) => assert ! ( a < b, "all_list {all_list:?}" ) ,
0 commit comments