+shiffle
+List.binarySearch
This commit is contained in:
		
							parent
							
								
									0ec0ed96ee
								
							
						
					
					
						commit
						dc837e2095
					
				
							
								
								
									
										37
									
								
								docs/Array.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								docs/Array.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					# Array
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It's an interface if the [Collection] that provides indexing access, like `array[3] = 0`.
 | 
				
			||||||
 | 
					Array therefore implements [Iterable] too. The well known implementatino of the `Array` is
 | 
				
			||||||
 | 
					[List].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Array adds the following methods:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Binary search
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When applied to sorted arrays, binary search allow to quicly find an index of the element in the array, or where to insert it to keep order:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val coll = [1,2,3,4,5]
 | 
				
			||||||
 | 
					    assertEquals( 2, coll.binarySearch(3) )
 | 
				
			||||||
 | 
					    assertEquals( 0, coll.binarySearch(1) )
 | 
				
			||||||
 | 
					    assertEquals( 4, coll.binarySearch(5) )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val src = (1..50).toList().shuffled()
 | 
				
			||||||
 | 
					    val result = []
 | 
				
			||||||
 | 
					    for( x in src ) {
 | 
				
			||||||
 | 
					        val i = result.binarySearch(x)
 | 
				
			||||||
 | 
					        assert( i < 0 )
 | 
				
			||||||
 | 
					        result.insertAt(-i-1, x)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    assertEquals( src.sorted(), result )
 | 
				
			||||||
 | 
					    >>> void
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					So `binarySearch(x)` returns:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- index of `x`, a non-negative number
 | 
				
			||||||
 | 
					- negative: `x` not found, but if inserted at position `-returnedValue-1` will leave array sorted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To pre-sort and array use `Iterable.sorted*` or in-place `List.sort*` families, see [List] and [Iterable] docs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Collection]: Collection.md
 | 
				
			||||||
 | 
					[Iterable]: Iterable.md
 | 
				
			||||||
 | 
					[List]: List.md
 | 
				
			||||||
@ -95,6 +95,7 @@ These, again, does the thing:
 | 
				
			|||||||
| sortedBy(predicate)    | sort by comparing results of the predicate function                             |
 | 
					| sortedBy(predicate)    | sort by comparing results of the predicate function                             |
 | 
				
			||||||
| joinToString(s,t)      | convert iterable to string, see (2)                                             |
 | 
					| joinToString(s,t)      | convert iterable to string, see (2)                                             |
 | 
				
			||||||
| reversed()             | create a list containing items from this in reverse order                       |
 | 
					| reversed()             | create a list containing items from this in reverse order                       |
 | 
				
			||||||
 | 
					| shuffled()             | create a listof shiffled elements                                               |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(1)
 | 
					(1)
 | 
				
			||||||
: throws `NoSuchElementException` if there is no such element
 | 
					: throws `NoSuchElementException` if there is no such element
 | 
				
			||||||
 | 
				
			|||||||
@ -128,8 +128,9 @@ List could be sorted in place, just like [Collection] provide sorted copies, in
 | 
				
			|||||||
| `[Range]`                     | get slice of the array (copy)                | Range       |
 | 
					| `[Range]`                     | get slice of the array (copy)                | Range       |
 | 
				
			||||||
| `+=`                          | append element(s) (2)                        | List or Obj |
 | 
					| `+=`                          | append element(s) (2)                        | List or Obj |
 | 
				
			||||||
| `sort()`                      | in-place sort, natural order                 | void        |
 | 
					| `sort()`                      | in-place sort, natural order                 | void        |
 | 
				
			||||||
| 'sortBy(predicate)`           | in place sort bu `predicate` call result (3) | void        |
 | 
					| `sortBy(predicate)`           | in-place sort bu `predicate` call result (3) | void        |
 | 
				
			||||||
| `SortWith(comparator)         | in place sort using `comarator` function (4) | void        |
 | 
					| `sortWith(comparator)`        | in-place sort using `comarator` function (4) | void        |
 | 
				
			||||||
 | 
					| `shiffle()`                   | in-place shiffle contents                    |             |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(1)
 | 
					(1)
 | 
				
			||||||
: optimized implementation that override `Array` one
 | 
					: optimized implementation that override `Array` one
 | 
				
			||||||
@ -143,7 +144,7 @@ instance is appended. If you want to append an Iterable object itself, use `add`
 | 
				
			|||||||
order, e.g. is same as `list.sortWith { a,b -> predicate(a) <=> predicate(b) }`
 | 
					order, e.g. is same as `list.sortWith { a,b -> predicate(a) <=> predicate(b) }`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(4)
 | 
					(4)
 | 
				
			||||||
: comparator callable takes tho arguments and must return: negative value when first is less, 
 | 
					: comparator callable takes tho arguments and must return: negative value when first is less,
 | 
				
			||||||
positive if first is greater, and zero if they are equal. For example, the equvalent comparator
 | 
					positive if first is greater, and zero if they are equal. For example, the equvalent comparator
 | 
				
			||||||
for `sort()` will be `sort { a, b -> a <=> b }
 | 
					for `sort()` will be `sort { a, b -> a <=> b }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -324,10 +324,8 @@ open class Obj {
 | 
				
			|||||||
            addFn("apply") {
 | 
					            addFn("apply") {
 | 
				
			||||||
                val body = args.firstAndOnly()
 | 
					                val body = args.firstAndOnly()
 | 
				
			||||||
                (thisObj as? ObjInstance)?.let {
 | 
					                (thisObj as? ObjInstance)?.let {
 | 
				
			||||||
                    println("apply in ${thisObj is ObjInstance}, ${it.instanceScope}")
 | 
					 | 
				
			||||||
                    body.callOn(ApplyScope(this, it.instanceScope))
 | 
					                    body.callOn(ApplyScope(this, it.instanceScope))
 | 
				
			||||||
                } ?: run {
 | 
					                } ?: run {
 | 
				
			||||||
                    println("apply on non-instance $thisObj")
 | 
					 | 
				
			||||||
                    body.callOn(this)
 | 
					                    body.callOn(this)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                thisObj
 | 
					                thisObj
 | 
				
			||||||
 | 
				
			|||||||
@ -50,5 +50,26 @@ val ObjArray by lazy {
 | 
				
			|||||||
        addFn("indices") {
 | 
					        addFn("indices") {
 | 
				
			||||||
            ObjRange(0.toObj(), thisObj.invokeInstanceMethod(this, "size"), false)
 | 
					            ObjRange(0.toObj(), thisObj.invokeInstanceMethod(this, "size"), false)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        addFn("binarySearch") {
 | 
				
			||||||
 | 
					            val target = args.firstAndOnly()
 | 
				
			||||||
 | 
					            var low = 0
 | 
				
			||||||
 | 
					            var high = thisObj.invokeInstanceMethod(this, "size").toInt() - 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            while (low <= high) {
 | 
				
			||||||
 | 
					                val mid = (low + high) / 2
 | 
				
			||||||
 | 
					                val midVal = thisObj.getAt(this, ObjInt(mid.toLong()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                val cmp = midVal.compareTo(this, target)
 | 
				
			||||||
 | 
					                when {
 | 
				
			||||||
 | 
					                    cmp == 0 -> return@addFn (mid).toObj()
 | 
				
			||||||
 | 
					                    cmp > 0 -> high = mid - 1
 | 
				
			||||||
 | 
					                    else -> low = mid + 1
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Элемент не найден, возвращаем -(точка вставки) - 1
 | 
				
			||||||
 | 
					            (-low - 1).toObj()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -141,6 +141,5 @@ val ObjIterable by lazy {
 | 
				
			|||||||
            list.list.reverse()
 | 
					            list.list.reverse()
 | 
				
			||||||
            list
 | 
					            list
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -269,6 +269,10 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
 | 
				
			|||||||
                thisAs<ObjList>().quicksort { a, b -> comparator.call(this, a, b).toInt() }
 | 
					                thisAs<ObjList>().quicksort { a, b -> comparator.call(this, a, b).toInt() }
 | 
				
			||||||
                ObjVoid
 | 
					                ObjVoid
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            addFn("shuffle") {
 | 
				
			||||||
 | 
					                thisAs<ObjList>().list.shuffle()
 | 
				
			||||||
 | 
					                ObjVoid
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -131,6 +131,10 @@ fun Iterable.sortedBy(predicate) {
 | 
				
			|||||||
    sortedWith { a, b -> predicate(a) <=> predicate(b) }
 | 
					    sortedWith { a, b -> predicate(a) <=> predicate(b) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fun Iterable.shuffled() {
 | 
				
			||||||
 | 
					    toList().apply { shuffle() }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun List.toString() {
 | 
					fun List.toString() {
 | 
				
			||||||
    "[" + joinToString(",") + "]"
 | 
					    "[" + joinToString(",") + "]"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3188,7 +3188,8 @@ class ScriptTest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    fun testSort() = runTest {
 | 
					    fun testSort() = runTest {
 | 
				
			||||||
        eval("""
 | 
					        eval(
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
            val coll = [5,4,1,7]
 | 
					            val coll = [5,4,1,7]
 | 
				
			||||||
            assertEquals( [1,4,5,7], coll.sortedWith { a,b -> a <=> b })
 | 
					            assertEquals( [1,4,5,7], coll.sortedWith { a,b -> a <=> b })
 | 
				
			||||||
            assertEquals( [1,4,5,7], coll.sorted())
 | 
					            assertEquals( [1,4,5,7], coll.sorted())
 | 
				
			||||||
@ -3200,7 +3201,8 @@ class ScriptTest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    fun testListSortInPlace() = runTest {
 | 
					    fun testListSortInPlace() = runTest {
 | 
				
			||||||
        eval("""
 | 
					        eval(
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
            val l1 = [6,3,1,9]
 | 
					            val l1 = [6,3,1,9]
 | 
				
			||||||
            l1.sort()
 | 
					            l1.sort()
 | 
				
			||||||
            assertEquals( [1,3,6,9], l1)
 | 
					            assertEquals( [1,3,6,9], l1)
 | 
				
			||||||
@ -3212,6 +3214,35 @@ class ScriptTest {
 | 
				
			|||||||
            // 1 3 2 1
 | 
					            // 1 3 2 1
 | 
				
			||||||
            // we hope we got it also stable:
 | 
					            // we hope we got it also stable:
 | 
				
			||||||
            assertEquals( [1,9,6,3], l1)
 | 
					            assertEquals( [1,9,6,3], l1)
 | 
				
			||||||
        """)
 | 
					        """
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun binarySearchTest() = runTest {
 | 
				
			||||||
 | 
					        eval(
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					            val coll = [1,2,3,4,5]
 | 
				
			||||||
 | 
					            assertEquals( 2, coll.binarySearch(3) )
 | 
				
			||||||
 | 
					            assertEquals( 0, coll.binarySearch(1) )
 | 
				
			||||||
 | 
					            assertEquals( 4, coll.binarySearch(5) )
 | 
				
			||||||
 | 
					        """.trimIndent()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun binarySearchTest2() = runTest {
 | 
				
			||||||
 | 
					        eval(
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					            val src = (1..50).toList().shuffled()
 | 
				
			||||||
 | 
					            val result = []
 | 
				
			||||||
 | 
					            for( x in src ) {
 | 
				
			||||||
 | 
					                val i = result.binarySearch(x)
 | 
				
			||||||
 | 
					                assert( i < 0 )
 | 
				
			||||||
 | 
					                result.insertAt(-i-1, x)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            assertEquals( src.sorted(), result )
 | 
				
			||||||
 | 
					            """.trimIndent())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -327,4 +327,9 @@ class BookTest {
 | 
				
			|||||||
        runDocTests("../docs/serialization.md")
 | 
					        runDocTests("../docs/serialization.md")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun testArray() = runBlocking {
 | 
				
			||||||
 | 
					        runDocTests("../docs/Array.md")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user