Kotlin decomposing numbers into powers of 2 - kotlin
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.
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 product of odd or even integers
The problem I'm working on accepts a number string and will output the product of the odd or even numbers in the string. While the product of purely number string is working fine, my code should also accept strings that is alphanumeric (ex: 67shdg8092) and output the product. I'm quite confused on how I should code the alphanumeric strings, because the code I have done uses toInt(). Here's my code: fun myProd(Odd: Boolean, vararg data: Char): Int { var bool = isOdd var EvenProd = 1 var OddProd = 1 for (a in data) { val intVal = a.toString().toInt() if (intVal == 0) { continue } if (intVal % 2 == 0) { EvenProd *= intVal } else { OddProd *= intVal } } if(bool == true) return OddProd else return EvenProd }
Use toIntOrNull instead of toInt. It only converts numeric string val intVal = a.toString().toIntOrNull() if (intVal == null || intVal == 0) { continue } Starting from Kotlin 1.6 you can also use a.digitToIntOrNull(). P.S. Your method could be also rewritten in functional style fun myProd(isOdd: Boolean, input: String): Int { return input.asSequence() .mapNotNull { it.toString().toIntOrNull() } // parse to numeric, ignore non-numeric .filter { it > 0 } // avoid multiplying by zero .filter { if (isOdd) it % 2 != 0 else it % 2 == 0 } // pick either odd or even numbers .fold(1) { prod, i -> prod * i } // accumulate with initial 1 }
How to try every possible permutation in Kotlin
fun main () { var integers = mutableListOf(0) for (x in 1..9) { integers.add(x) } //for or while could be used in this instance var lowerCase = listOf("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z") var upperCase = listOf('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z') println(integers) println(lowerCase) println(upperCase) //Note that for the actual program, it is also vital that I use potential punctuation val passwordGeneratorKey1 = Math.random()*999 val passwordGeneratorKey2 = passwordGeneratorKey1.toInt() var passwordGeneratorL1 = lowerCase[(Math.random()*lowerCase.size).toInt()] var passwordGeneratorL2 = lowerCase[(Math.random()*lowerCase.size).toInt()] var passwordGeneratorL3 = lowerCase[(Math.random()*lowerCase.size).toInt()] var passwordGeneratorU1 = upperCase[(Math.random()*upperCase.size).toInt()] var passwordGeneratorU2 = upperCase[(Math.random()*upperCase.size).toInt()] var passwordGeneratorU3 = upperCase[(Math.random()*upperCase.size).toInt()] val password = passwordGeneratorKey2.toString()+passwordGeneratorL1+passwordGeneratorL2+passwordGeneratorL3+passwordGeneratorU1+passwordGeneratorU2+passwordGeneratorU3 println(password) //No, this isn't random, but it's pretty close to it //How do I now run through every possible combination of the lists //lowerCase, integers, and upperCase? } How do I run through every possible permutation to eventually solve for the randomly generated password? This is in Kotlin.
I think you should append all the lists together and then draw from it by random index, this way you ensure that position of numbers, lower cases and uppercases is random too. Also you don't need to write all the characters, you can use Range which generates them for you. fun main() { val allChars = mutableListOf<Any>().apply { addAll(0..9) // creates range from 0 to 9 and adds it to a list addAll('a'..'z') // creates range from a to z and adds it to a list addAll('A'..'Z') // creates range from A to Z and adds it to a list } val passwordLength = 9 val password = StringBuilder().apply { for (i in 0 until passwordLength) { val randomCharIndex = Random.nextInt(allChars.lastIndex) // generate random index from 0 to lastIndex of list val randomChar = allChars[randomCharIndex] // select character from list append(randomChar) // append char to password string builder } }.toString() println(password) } Even shorter solution can be achieved using list methods fun main() { val password = mutableListOf<Any>() .apply { addAll(0..9) // creates range from 0 to 9 and adds it to a list addAll('a'..'z') // creates range from a to z and adds it to a list addAll('A'..'Z') // creates range from A to Z and adds it to a list } .shuffled() // shuffle the list .take(9) // take first 9 elements from list .joinToString("") // join them to string println(password) }
As others pointed out there are less painful ways to generate the initial password in the format of: 1 to 3 digits followed by 3 lowercase characters followed by 3 uppercase characters. To brute force this password, you will need to consider all 3-permutations of "a..z" and all 3-permitations of "A..Z". In both cases the number of such 3-permutations is 15600 = 26! / (26-3)!. In worst case you will have to examine 1000 * 15600 * 15600 combination, half of this on the average. Probably doable in a few hours with the code below: import kotlin.random.Random import kotlin.system.exitProcess val lowercaseList = ('a'..'z').toList() val uppercaseList = ('A'..'Z').toList() val lowercase = lowercaseList.joinToString(separator = "") val uppercase = uppercaseList.joinToString(separator = "") fun genPassword(): String { val lowercase = lowercaseList.shuffled().take(3) val uppercase = uppercaseList.shuffled().take(3) return (listOf(Random.nextInt(0, 1000)) + lowercase + uppercase).joinToString(separator = "") } /** * Generate all K-sized permutations of str of length N. The number of such permutations is: * N! / (N-K)! * * For example: perm(2, "abc") = [ab, ac, ba, bc, ca, cb] */ fun perm(k: Int, str: String): List<String> { val nk = str.length - k fun perm(str: String, accumulate: String): List<String> { return when (str.length == nk) { true -> listOf(accumulate) false -> { str.flatMapIndexed { i, c -> perm(str.removeRange(i, i + 1), accumulate + c) } } } } return perm(str, "") } fun main() { val password = genPassword().also { println(it) } val all3LowercasePermutations = perm(3, lowercase).also { println(it) }.also { println(it.size) } val all3UppercasePermutations = perm(3, uppercase).also { println(it) }.also { println(it.size) } for (i in 0..999) { println("trying $i") for (l in all3LowercasePermutations) { for (u in all3UppercasePermutations) { if ("$i$l$u" == password) { println("found: $i$l$u") exitProcess(0) } } } } }
how to increase the size limit of a mutable list in 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.
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(""))