What is the most efficient way to create a kotlin.String from a range of a ByteArray? - kotlin

In Java you have:
byte[] bytes = ...
int pos = ...
int length = ...
new String(bytes, pos, length)
This will create one additional byte[] internally in String.
What is the most efficient way to do that in Kotlin (i.e. with the least amount of additional objects)?
val bytes : ByteArray = ...
val pos : Int = ...
val length : Int = ...
???

val bytes: ByteArray = ByteArray(10) { ('a'..'z').toList()[it].code.toByte() }
val pos: Int = 3
val length: Int = 4
val result = String(bytes.sliceArray(pos until pos + length))

Related

Calculate CRC32 in Kotlin (convert C# Code to Kotlin)

Could someone help me out with converting this C# code to Kotlin?
public static UInt32 CalcCrc32(byte[] bytes, int length)
{
// GLB_u32CalcCrc32OverBytes
UInt32 Checksum = 0xFFFFFFFF;
for (int i = 0; i < length; i++)
{
byte top = (byte)(Checksum >> 24);
top ^= bytes[i];
Checksum = (Checksum << 8) ^ crc_table[top];
}
return Checksum;
}
It allows the CRC32 caluclation of the first length bytes of bytes.
I have tried different approaches to deal with the unsigned datatypes, but I cannot get it to return the correct CRC.
This was the closest I got
Generating the crc table (taken from this repo)
private val crcTable = (0 until 256).map {
crc32(it.toUByte(), 0x04C11DB7.toUInt())
}
private fun crc32(input: UByte, polynomial: UInt): UInt {
val bigEndianInput = input.toBigEndianUInt()
return (0 until 8).fold(bigEndianInput) { result, _ ->
val isMostSignificantBitOne = result and 0x80000000.toUInt() != 0.toUInt()
val shiftedResult = result shl 1
when (isMostSignificantBitOne) {
true -> shiftedResult xor polynomial
false -> shiftedResult
}
}
}
private fun UByte.toBigEndianUInt(): UInt = this.toUInt() shl 24
Converting the C# method to Kotlin
private fun calcCrc32(bytes: ByteArray, length: Int): UInt {
var checksum : UInt = 0xFFFFFFFFu
for (i in 0 until length) {
var top = (checksum shr 24).toByte()
top = top xor bytes[i]
checksum = checksum shl 8 xor crcTable[top.toInt()]
}
return checksum
}
But this code throws an IndexOutOfBoundsException, because top ends up being -1.
Unit Test
import com.google.common.truth.Truth.assertThat
import com.proregia.pump.common.CrcUtil
import org.junit.Test
class CrcUtilTest {
#Test
fun crc16_correctByteArray_returnsCorrectCrc16() {
val data = byteArrayOf(
0xe8.toByte(),
0x03.toByte(),
0x00.toByte(),
0x00.toByte(),
0x3c.toByte(),
0x00.toByte(),
0x00.toByte(),
0x00.toByte(),
0x90.toByte(),
0x01.toByte(),
0x00.toByte(),
0x00.toByte(),
0x02.toByte(),
0x00.toByte(),
0x00.toByte()
)
CrcUtil.updateCrc16(data)
assertThat(data[13]).isEqualTo(0xAD)
assertThat(data[14]).isEqualTo(0xC1)
}
}
Try toUByte() instead of toByte() in calcCrc32(), also applying it to the result of bytes[i].
private fun calcCrc32(bytes: ByteArray, length: Int): UInt {
var checksum: UInt = 0xFFFFFFFFu
val uBytes = bytes.toUByteArray()
for (i in 0 until length) {
var top = (checksum shr 24).toUByte()
top = top xor uBytes[i]
checksum = checksum shl 8 xor crcTable[top.toInt()]
}
return checksum
}
The JDK has a built-in class that allows you to compute the CRC32 of a given value: https://docs.oracle.com/javase/8/docs/api/java/util/zip/CRC32.html
You can take advantage of Kotlin's interoperability with Java to compute the CRC32 checksum of a given value:
import java.util.zip.CRC32
fun calculateCRC32(value: ByteArray): Long {
val crc32Calculator = CRC32()
crc32Calculator.update(value)
return crc32Calculator.value
}
println(calculateCRC32("Some text".toByteArray())) // prints 3444260633

Read a sequence of numbers of undefined size & print the largest number & position of its first occurrence

I need to read a sequence of numbers of undefined size & prints the largest number & the position of its first occurrence
Can anyone help with this code:
import java.util.Scanner
fun main() {
val scan = Scanner(System.`in`)
val num = scan.nextInt()
var max = Int.MIN_VALUE
var pos = 0
var i = 1
do {
if (max < num) {
max = num
pos = i
}
i++
} while (scan.hasNext())
print("$max $pos")
}
You just need to read a new number in each iteration:
import java.util.Scanner
fun main() {
val scan = Scanner(System.`in`)
var max = Int.MIN_VALUE
var pos = 0
var i = 1
while (scan.hasNext()) {
// Read a new number here
val num = scan.nextInt()
if (max < num) {
max = num
pos = i
}
i++
}
print("$max $pos")
}
My solution to this task
This is a simple task, it can be solved in a simple way without using a “java.util.Scanner”. You just need to read a new number in each iteration.
fun main() {
var pos = 0
var max = 0
var count = 1
while (true) {
val input = readlnOrNull()
if (input == null) break
val num = input.toInt()
if (pos == 0 || num > max) {
max = num
pos = count
}
count++
}
print("$max $pos")
}

Update random class attribute in Kotlin

I have a class with some attributes:
class DonutBox {
var glaze: Int = 0
var chocolate: Int = 0
var maple: Int = 0
var etc: Int = 0
}
fun addDonuts() {
val omNom = DonutBox()
}
How can I increment a random attribute of the instantiated class?
For instance, if the randomly selected attribute is chocolate, then effectively:
omNom.chocolate += 1
Because Kotlin's properties are statically declared, and you want to use them dynamically, most of the methods to do that will involve reflection, which can get pretty messy and difficult to understand.
When you want dynamic data, it's probably better to use a map:
val donutBox = mutableMapOf(
"glaze" to 0,
"chocolate" to 0,
"maple" to 0,
"etc" to 0,
)
val randomKey = donutBox.keys.random()
donutBox[randomKey] = donutBox.getValue(randomKey) + 1
println(donutBox)
Output:
{glaze=0, chocolate=0, maple=1, etc=0}
That said, if you really want to use reflection, you can do it like this:
data class DonutBox(
var glaze: Int = 0,
var chocolate: Int = 0,
var maple: Int = 0,
var etc: Int = 0,
)
fun addDonuts() {
val omNom = DonutBox()
val randomProperty = omNom::class.declaredMemberProperties.random() as KMutableProperty1<DonutBox, Int>
val existing = randomProperty.get(omNom)
randomProperty.set(omNom, existing + 1)
println(omNom)
}
fun main() {
addDonuts()
addDonuts()
addDonuts()
}
Output:
DonutBox(glaze=0, chocolate=1, maple=0, etc=0)
DonutBox(glaze=0, chocolate=0, maple=0, etc=1)
DonutBox(glaze=0, chocolate=1, maple=0, etc=0)

Reference Equality in Kotlin

I'm learning Kotlin, in the tutorial example:
fun main() {
val a: Int = 100
val boxedA: Int? = a
val anotherBoxedA: Int? = a
val b: Int = 1000
val boxedB: Int? = b
val anotherBoxedB: Int? = b
println(boxedA === anotherBoxedA) // true
println(boxedB === anotherBoxedB) // false
}
Why is the result of two comparision different?
Most likely because of the JDK implementation of Integer.valueOf
https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#valueOf(int)
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
If you decompile the method in Intellij, you'll find
public static final void main() {
int a = 100;
Integer boxedA = Integer.valueOf(a);
Integer anotherBoxedA = Integer.valueOf(a);
int b = 1000;
Integer boxedB = Integer.valueOf(b);
Integer anotherBoxedB = Integer.valueOf(b);
boolean var6 = boxedA == anotherBoxedA;
boolean var7 = false;
System.out.println(var6);
var6 = boxedB == anotherBoxedB;
var7 = false;
System.out.println(var6);
}

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(""))