how to increase the size limit of a mutable list in kotlin? - kotlin
I was attempting to solve the multiset question (https://codeforces.com/contest/1354/problem/D) on codeforces using Fenwick Tree Data structure. I passed the sample test cases but got the memory limit error after submitting, the testcase is mentioned below.
(Basically the testcase is:
1000000 1000000
1.............1 //10^6 times
-1...........-1 //10^6 times).
I tried similar testcase in my IDE and got the below mentioned error.
(Similar to above, the testcase I provided is:
1000000 1
1.............1 //10^6 times
-1
)
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 524289 out of bounds for length 524289
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:373)
at java.base/java.util.ArrayList.get(ArrayList.java:426)
at MultisetKt.main(multiset.kt:47)
at MultisetKt.main(multiset.kt)
Here is my code:
private fun readInt() = readLine()!!.split(" ").map { it.toInt() }
fun main() {
var (n, q) = readInt()
var list = readInt() //modify the list to store it from index 1
var finalList = listOf(0) + list
val query = readInt()
var bit = MutableList(n+1){0}
fun update(i:Int, value:Int) {
var index = i
while(index < n){
bit.set (index , bit[index] + value)
index += (index and -index)
}
}
fun rangefunc(i:Int): Int {
var su = 0
var index = i
while(index > 0){
su += bit[index]
index -= (index and -index)
}
return su
}
fun find(x:Int):Int {
var l = 1
var r = n
var ans = n
var mid = 0
while (l <= r) {
mid = (l + r) / 2
if (rangefunc(mid) >= x) {
ans = mid
r = mid - 1
} else {
l = mid + 1
}
}
return ans
}
for (i in 1..n) {
update(finalList[i], 1)
}
for (j in 0..q - 1) {
if (query[j] > 0) {
update(query[j], 1)
} else {
update(find(-query[j]), -1)
}
}
if(rangefunc(n) == 0){
println(0)
}else{
println(find(1))
}
}
I believe this is because the BITlist is not able to store 10^6 elements but not sure. Please let me know what changes should I make in my code also any additional advice on how to deal with such cases in the future.
Thank you in advance :)
An ArrayList can store over 2 billion items (2 * 10^9). That is not your issue. ArrayIndexOutOfBoundsException is for trying to access an index of an ArrayList that is less than zero or greater than or equal to its size. In other words, an index that it doesn't yet contain.
There's more code there than I have time to debug. But I would start at the line that the stack trace points to and see how it's possible for you to attempt to call bit[index] with an index that equals the size of the ArrayList.
To answer your literal question, you can use LinkedList explicitly as your type of MutableList to avoid the size restriction, but it is heavier and it is slower when accessing elements by index.
Related
Can someone explain why the below Kotlin code produces incorrect expected result?
Can someone explain why the below code produces [2,3,5,6,7,8,9,10,11,12]? I know it has something to do with filter function is deferred to the last element but I don't see the picture. It would even be better if you can visualise it. Thank you so much. val primes: Sequence<Int> = sequence { var numbers = generateSequence(2) { it + 1 } var prime: Int while (true) { prime = numbers.first() yield(prime) numbers = numbers.drop(1).filter { it % prime != 0 } } } print(primes.take(10).toList())
it's because you change prime variable in filter closure. For example, on the second step you have numbers as .filter { it % prime != 0 }.filter { it % prime != 0 } but the prime is one variable, and it is equal to 3 Correct version: val primes: Sequence<Int> = sequence { var numbers = generateSequence(2) { it + 1 } while (true) { val prime = numbers.first() yield(prime) numbers = numbers.drop(1).filter { it % prime != 0 } } } print(primes.take(10).toList())
Kotlin - The caracter literal does not conform expect type Int
I'm struggling with types with my program, I've been asked to do it in JS first and it worked fine but now I can't achieve the result. Do you think I should make another 'algorithm' ? In advance, thank you for your time. fun main(){ // the idea is to put numbers in a box // that cant be larger than 10 val data = "12493419133" var result = data[0] var currentBox = Character.getNumericValue(data[0]) var i = 1 while(i < data.length){ val currentArticle = Character.getNumericValue(data[i]) currentBox += currentArticle println(currentBox) if(currentBox <= 10){ result += Character.getNumericValue(currentArticle) }else{ result += '/' //var resultChar = result.toChar() // result += '/' currentBox = Character.getNumericValue(currentArticle) result += currentArticle } i++ } print(result) //should print 124/9/341/91/33 }
The result is actually of a Char type, and the overload operator function + only accepts Int to increment ASCII value to get new Char. public operator fun plus(other: Int): Char In idomatic Kotlin way, you can solve your problem: fun main() { val data = "12493419133" var counter = 0 val result = data.asSequence() .map(Character::getNumericValue) .map { c -> counter += c if (counter <= 10) c.toString() else "/$c".also{ counter = c } } .joinToString("") // terminal operation, will trigger the map functions println(result) } Edit: If the data is too large, you may want to use StringBuilder because it doesn't create string every single time the character is iterated, and instead of using a counter of yourself you can use list.fold() fun main() { val data = "12493419133" val sb = StringBuilder() data.fold(0) { acc, c -> val num = Character.getNumericValue(c) val count = num + acc val ret = if (count > 10) num.also { sb.append('/') } else count ret.also { sb.append(c) } // `ret` returned to ^fold, next time will be passed as acc } println(sb.toString()) }
If you want a result in List<Char> type: val data = "12493419133" val result = mutableListOf<Char>() var sum = 0 data.asSequence().forEach { val v = Character.getNumericValue(it) sum += v if (sum > 10) { result.add('/') sum = v } result.add(it) } println(result.joinToString(""))
runtime using measureTimeMillis
I'm attempting to compare different run-times for simple blocks of code, but continue to get 0 returned. What can I do to get a better approximation for the execution time? private var trackConstantTime: Long? = null this.trackConstantTime = measureTimeMillis { /* determine if a given number is even or odd */ var n = (0..(Int.MAX_VALUE)).random() if(n % 2 == 0) "Even" else "Odd" } println("O(1), Constant Time for fxConstantTime(...):${TimeUnit.MILLISECONDS.toSeconds(trackConstantTime!!)}") Similarly if I'll attach another example that's returning 0 for the runtime. private var trackLinearTime: Long? = null private var uL: MutableList<Int> = mutableListOf() for(i in 0..100){ this.uL.add( ((0)..(100)).random() ) } this.trackLinearTime = measureTimeMillis { /* determine the maximum value in an unsorted array */ var max: Int = 0 for(i in 0 until uL.size) { if (uL[i] > max) max = uL[i] println(max) } } println("O(n), Linear Time for fxLinearTime(...):${TimeUnit.MILLISECONDS.toSeconds(trackLinearTime!!)}")
Maybe try to measure time in nanoseconds: this.trackLinearTime = measureNanoTime { ... }
Kotlin decomposing numbers into powers of 2
Hi I am writing an app in kotlin and need to decompose a number into powers of 2. I have already done this in c#, PHP and swift but kotlin works differently somehow. having researched this I believe it is something to do with the numbers in my code going negative somewhere and that the solution lies in declaring one or more of the variable as "Long" to prevent this from happening but i have not been able to figure out how to do this. here is my code: var salads = StringBuilder() var value = 127 var j=0 while (j < 256) { var mask = 1 shl j if(value != 0 && mask != 0) { salads.append(mask) salads.append(",") } j += 1 } // salads = (salads.dropLast()) // removes the final "," println("Salads = $salads") This shoud output the following: 1,2,4,8,16,32,64 What I actually get is: 1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,-2147483648,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,-2147483648,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,-2147483648,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,-2147483648,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,-2147483648,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,-2147483648,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,-2147483648,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,-2147483648, Any ideas?
This works for the one input that you specified, at the very least: fun powersOfTwo(value :Long): String { val result = ArrayList<String>() var i = 0 var lastMask = 0 while (lastMask < value) { val mask = 1 shl i if (value != 0.toLong() && mask < value) { result.add(mask.toString()) } lastMask = mask i += 1 } return result.joinToString(",") } Ran it in a unit test: #Test fun addition_isCorrect() { val result = powersOfTwo(127) assertEquals("1,2,4,8,16,32,64", result) } Test passed.
You can get a list of all powers of two that fit in Int and test each of them for whether the value contains it with the infix function and: val value = 126 val powersOfTwo = (0 until Int.SIZE_BITS).map { n -> 1 shl n } println(powersOfTwo.filter { p -> value and p != 0}.joinToString(",")) // prints: 2,4,8,16,32,64 See the entire code in Kotlin playground: https://pl.kotl.in/f4CZtmCyI
Hi I finally managed to get this working properly: fun decomposeByTwo(value :Int): String { val result = ArrayList<String>() var value = value var j = 0 while (j < 256) { var mask = 1 shl j if ((value and mask) != 0) { value -= mask result.add(mask.toString()) } j += 1 } return result.toString() } I hope this helps someone trying to get a handle on bitwise options!
Somehow you want to do the "bitwise AND" of "value" and "mask" to determine if the j-th bit of "value" is set. I think you just forgot that test in your kotlin implementation.
Time/Space-Complexity method
I got a question to answer with the best complexity we can think about. We got one sorted array (int) and X value. All we need to do is to find how many places in the array equals the X value. This is my solution to this situation, as i don't know much about complexity. All i know is that better methods are without for loops :X class Question { public static int mount (int [] a, int x) { int first=0, last=a.length-1, count=0, pointer=0; boolean found=false, finish=false; if (x < a[0] || x > a[a.length-1]) return 0; while (! found) **//Searching any place in the array that equals to x value;** { if ( a[(first+last)/2] > x) last = (first+last)/2; else if ( a[(first+last)/2] < x) first = (first+last)/2; else { pointer = (first+last)/2; count = 1; found = true; break; } if (Math.abs(last-first) == 1) { if (a[first] == x) { pointer = first; count = 1; found = true; } else if (a[last] == x) { pointer = last; count = 1; found = true; } else return 0; } if (first == last) { if (a[first] == x) { pointer = first; count = 1; found = true; } else return 0; } } int backPointer=pointer, forwardPointer=pointer; boolean stop1=false, stop2= false; while (!finish) **//Counting the number of places the X value is near our pointer.** { if (backPointer-1 >= 0) if (a[backPointer-1] == x) { count++; backPointer--; } else stop1 = true; if (forwardPointer+1 <= a.length-1) if (a[forwardPointer+1] == x) { count++; forwardPointer++; } else stop2 = true; if (stop1 && stop2) finish=true; } return count; } public static void main (String [] args) { int [] a = {-25,0,5,11,11,99}; System.out.println(mount(a, 11)); } } The print command count it right and prints "2". I just want to know if anyone can think about better complexity for this method. Moreover, how can i know what is the time/space-complexity of the method? All i know about time/space-complexity is that for loop is O(n). I don't know how to calculate my method complexity. Thank a lot! Editing: This is the second while loop after changing: while (!stop1 || !stop2) //Counting the number of places the X value is near our pointer. { if (!stop1) { if ( a[last] == x ) { stop1 = true; count += (last-pointer); } else if ( a[(last+forwardPointer)/2] == x ) { if (last-forwardPointer == 1) { stop1 = true; count += (forwardPointer-pointer); } else forwardPointer = (last + forwardPointer) / 2; } else last = ((last + forwardPointer) / 2) - 1; } if (!stop2) { if (a[first] == x) { stop2 = true; count += (pointer - first); } else if ( a[(first+backPointer)/2] == x ) { if (backPointer - first == 1) { stop2 = true; count += (pointer-backPointer); } else backPointer = (first + backPointer) / 2; } else first = ((first + backPointer) / 2) + 1; } } What do you think about the changing? I think it would change the time complexity to O(long(n)).
First let's examine your code: The code could be heavily refactored and cleaned (which would also result in more efficient implementation, yet without improving time or space complexity), but the algorithm itself is pretty good. What it does is use standard binary search to find an item with the required value, then scans to the back and to the front to find all other occurrences of the value. In terms of time complexity, the algorithm is O(N). The worst case is when the entire array is the same value and you end up iterating all of it in the 2nd phase (the binary search will only take 1 iteration). Space complexity is O(1). The memory usage (space) is unaffected by growth in input size. You could improve the worst case time complexity if you keep using binary search on the 2 sub-arrays (back & front) and increase the "match range" logarithmically this way. The time complexity will become O(log(N)). Space complexity will remain O(1) for the same reason as before. However, the average complexity for a real-world scenario (where the array contains various values) would be very close and might even lean towards your own version.