11// Returns a random number between [min,max)
22const random = ( min : number , max : number ) => {
3- return Math . floor ( Math . random ( ) * ( max - min ) ) + min ;
4- } ;
5-
6- // Returns a new list if each group of 5 inside of l[i]
7- // eg:
8- // arr := [0,1,2,3,4,5,6,7,8,9]:
9- // l:= [[0,1,2,3,4],[5,6,7,8,9]]
10- const groupOf5 = ( arr :number [ ] ) => {
11- let l = [ ] ;
12- let g = [ ] ;
13- for ( let i = 0 ; i < arr . length ; i ++ ) {
14- if ( g . length < 5 ) g . push ( arr [ i ] ) ;
15- else {
16- l . push ( g ) ;
17- g = [ ] ;
18- g . push ( arr [ i ] ) ;
19- }
3+ return Math . floor ( Math . random ( ) * ( max - min ) ) + min ;
4+ } ;
5+
6+ // Returns a new list if each group of 5 inside of l[i]
7+ // eg:
8+ // arr := [0,1,2,3,4,5,6,7,8,9]:
9+ // l:= [[0,1,2,3,4],[5,6,7,8,9]]
10+ const groupOf5 = ( arr : number [ ] ) => {
11+ let l = [ ] ;
12+ let g = [ ] ;
13+ for ( let i = 0 ; i < arr . length ; i ++ ) {
14+ if ( g . length < 5 ) g . push ( arr [ i ] ) ;
15+ else {
16+ l . push ( g ) ;
17+ g = [ ] ;
18+ g . push ( arr [ i ] ) ;
2019 }
21- l . push ( g ) ;
22- return l ;
23- } ;
24-
25- // Returns the median of a list with 5 values or less
26- const medianOf5 = ( arr :number [ ] ) => {
27- if ( arr . length > 5 ) throw new Error ( 'Arr cannot have more than 5 numbers' ) ;
28- arr . sort ( function ( a , b ) {
29- return a - b ;
30- } ) ;
31- const m = Math . floor ( arr . length / 2 ) ;
32- return arr [ m ] ;
33- } ;
34-
35- // Returns 'the median of the medians'
36- const medianOfMedians = ( arr : number [ ] ) => {
37- // break arr into arr.length/5 of sie 5 each
38- const l = groupOf5 ( arr ) ;
39- // array with arr.length/5 medians
40- const c = [ ] ;
41- for ( let i = 0 ; i < l . length ; i ++ ) {
42- c . push ( medianOf5 ( l [ i ] ) ) ;
20+ }
21+ l . push ( g ) ;
22+ return l ;
23+ } ;
24+
25+ // Returns the median of a list with 5 values or less
26+ const medianOf5 = ( arr : number [ ] ) => {
27+ if ( arr . length > 5 ) throw new Error ( "Arr cannot have more than 5 numbers" ) ;
28+ arr . sort ( function ( a , b ) {
29+ return a - b ;
30+ } ) ;
31+ const m = Math . floor ( arr . length / 2 ) ;
32+ return arr [ m ] ;
33+ } ;
34+
35+ // Returns 'the median of the medians'
36+ // - Recursively compute "median of medians":
37+ // - Break arr in groups of five elements
38+ // - Calculate medians = each median from each "Group of 5"
39+ // - Recusrively compute the median from medians
40+ const medianOfMedians = ( arr : number [ ] ) => {
41+ // break arr into arr.length/5 of sie 5 each
42+ const l = groupOf5 ( arr ) ;
43+ // array with arr.length/5 medians
44+ const c = [ ] ;
45+ for ( let i = 0 ; i < l . length ; i ++ ) {
46+ c . push ( medianOf5 ( l [ i ] ) ) ;
47+ }
48+ //middle of c
49+ let mc = Math . floor ( c . length / 2 ) ;
50+ //recursively compute median of c
51+ const p = selection ( c , mc , 1 ) ;
52+ const idx = arr . indexOf ( p ) ;
53+ // swap to the 1st position
54+ [ arr [ 0 ] , arr [ idx ] ] = [ arr [ idx ] , arr [ 0 ] ] ;
55+ return p ;
56+ } ;
57+
58+ // Returns a pivot
59+ // chooseP:
60+ // 0: Random Pivot
61+ // 1: Deterministic Pivot ('median of medians')
62+ const choosePivot = ( arr : number [ ] , chooseP : number ) => {
63+ switch ( chooseP ) {
64+ case 0 :
65+ default :
66+ const idx = random ( 0 , arr . length ) ;
67+ [ arr [ 0 ] , arr [ idx ] ] = [ arr [ idx ] , arr [ 0 ] ] ;
68+ return arr [ 0 ] ;
69+ case 1 :
70+ return medianOfMedians ( arr ) ;
71+ }
72+ } ;
73+
74+ // Returns: the order statistic of a given pivot (its correct position if the arr was ordered)
75+ // also make a partition around the pivot
76+ // chooseP:
77+ // 0: Randomized Selection
78+ // 1: Deterministic Selection
79+ const partition = ( arr : number [ ] , chooseP = 0 ) => {
80+ // const p = choosePivot(arr, chooseP);
81+ const p = choosePivot ( arr , chooseP ) ;
82+ // keep track of how many elements are smaller than the pivot
83+ // this will be its 'right' position if arr is sorted
84+ let i = 1 ;
85+ // elements with idx < j : partitioned
86+ // elements with idx > j unpartitioned
87+ for ( let j = 1 ; j < arr . length ; j ++ ) {
88+ // check if the next element is smaller than the pivot
89+ if ( arr [ j ] < p ) {
90+ // swap and move i
91+ [ arr [ i ] , arr [ j ] ] = [ arr [ j ] , arr [ i ] ] ;
92+ i ++ ;
4393 }
44- //middle of c
45- let mc = Math . floor ( c . length / 2 ) ;
46- //recursively compute median of c
47- const p = selection ( c , mc , 1 ) ;
48- return p ;
49- } ;
50-
51- // Returns a pivot
52- // chooseP:
53- // 0: Random Pivot
54- // 1: Deterministic Pivot ('median of medians')
55- const choosePivot = ( arr :number [ ] , chooseP :number ) => {
56- switch ( chooseP ) {
57- case 0 :
58- default :
59- const idx = random ( 0 , arr . length ) ;
60- [ arr [ 0 ] , arr [ idx ] ] = [ arr [ idx ] , arr [ 0 ] ] ;
61- return arr [ 0 ] ;
62- case 1 :
63- return medianOfMedians ( arr ) ;
64- }
65- } ;
66-
67- // Returns: the order statistic of a given pivot (its correct position if the arr was ordered)
68- // also make a partition around the pivot
69- // chooseP:
70- // 0: Randomized Selection
71- // 1: Deterministic Selection
72- const partition = ( arr : number [ ] , chooseP = 0 ) => {
73- const p = choosePivot ( arr , chooseP ) ;
74- // keep track of how many elements are smaller than the pivot
75- // this will be its 'right' position if arr is sorted
76- let i = 1 ;
77- // elements with idx < j : partitioned
78- // elements with idx > j unpartitioned
79- for ( let j = 1 ; j < arr . length ; j ++ ) {
80- // check if the next element is smaller than the pivot
81- if ( arr [ j ] < p ) {
82- // swap and move i
83- [ arr [ i ] , arr [ j ] ] = [ arr [ j ] , arr [ i ] ] ;
84- i ++ ;
85- }
86- }
87- // swap p to its right position and returns its idx
88- [ arr [ 0 ] , arr [ i - 1 ] ] = [ arr [ i - 1 ] , arr [ 0 ] ] ;
89- return i - 1 ;
90- } ;
91-
92- // Returns the ith smallest element of arr
93- const selection = ( arr : number [ ] , i : number , chooseP = 0 ) :number | boolean => {
94- // out of bounds
95- if ( i > arr . length - 1 ) return false ;
96- if ( arr . length === 1 ) return arr [ 0 ] ;
97- // j is the index of p
98- const j = partition ( arr , chooseP ) ;
99- if ( j === i ) return arr [ j ] ;
100- if ( j > i ) {
101- const left = arr . slice ( 0 , j ) ;
102- return selection ( left , i ) ;
103- }
104- // i < j
105- const right = arr . slice ( j + 1 ) ;
106- return selection ( right , i - j - 1 ) ;
107- } ;
108-
109- export = selection
110-
94+ }
95+ // swap p to its right position and returns its idx
96+ [ arr [ 0 ] , arr [ i - 1 ] ] = [ arr [ i - 1 ] , arr [ 0 ] ] ;
97+ return i - 1 ;
98+ } ;
99+
100+ // Returns the ith smallest element of arr
101+ const selection = ( arr : number [ ] , i : number , chooseP = 0 ) : number => {
102+ if ( arr . length === 1 ) return arr [ 0 ] ;
103+ // j is the index of the pivot
104+ const j = partition ( arr , chooseP ) ;
105+ if ( j === i ) return arr [ j ] ;
106+ if ( j > i ) {
107+ const left = arr . slice ( 0 , j ) ;
108+ return selection ( left , i ) ;
109+ }
110+ // i < j
111+ const right = arr . slice ( j + 1 ) ;
112+ return selection ( right , i - j - 1 ) ;
113+ } ;
114+
115+ export default selection ;
0 commit comments