+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