I've a byte. What I want to do is access bit position to retrieve boolean (0 or 1). How can I do that in Kotlin?
fun getBit(b: Byte, bitNumber: Int): Boolean {
val shift: Int = 7 - bitNumber
val bitMask = (1 shl shift).toByte()
val masked = (b and bitMask)
return masked.toInt() != 0
}
This for some reason return incorrect value of false when it should return true
Your algorithm seems OK, I think you just made an off by one error (although you didn't say if you are counting from 0 or 1). If I change it to
val shift: Int = 8 - bitNumber
It seems to work fine for me:
fun getBit(b: Byte, bitNumber: Int): Boolean {
require(bitNumber in 1..8)
val shift: Int = 8 - bitNumber
val bitMask = (1 shl shift).toByte()
val masked = (b and bitMask)
return masked.toInt() != 0
}
fun main() {
println(getBit(0b10000000.toByte(), 1))
println(getBit(0b10000000.toByte(), 2))
println(getBit(0b01000000, 2))
}
Output:
true
false
true
Note: you can avoid the experimental Byte.and() by using Int.and() instead:
val bitMask = (0b1 shl shift)
val masked = (b.toInt() and bitMask)
return masked != 0
Related
For some reason I can't understand, when I'm parsing the buffer values, I almost never get the version as 4 (which would be the default for IPv4), and most of the time I get some random value like 10 or 0 instead. The same is true with the protocol, even though it is parsing exactly as it is specified on the wiki, it never comes up precisely with something that says it's TCP or UDP, just 0 (which would map to HOPOPT) or a random value. I believe the parsing is at least correct because when I debug, the source address resolves to the DNS I specified (8.8.4.4), which shouldn't happen if I was parsing the wrong way (at least, it seems to me that no).
val (version, internetHeaderLength) = buffer.get().toUByte().split()
// Differentiated Services Code Point, Explicit Congestion Notification (TOS)
val (dscp, ecn) = buffer.get().toUByte().extract(2)
val totalLength = buffer.short.toUShort()
val identification = buffer.short.toUShort()
val (flags, fragmentOffset) = buffer.short.toUShort().extract(3)
val timeToLive = buffer.get().toUByte()
val protocol = buffer.get().toUByte()
val headerChecksum = buffer.short.toUShort()
val sourceAddress = buffer.int
val destinationAddress = buffer.int
val options = buffer.array().sliceArray(0 until internetHeaderLength.toInt() * 4 - 20)
val data =
buffer.array().sliceArray(internetHeaderLength.toInt() * 4 until totalLength.toInt())
Below is the code I use to get the packet data
fun receivePackets(input: FileInputStream, output: FileOutputStream, buffer: ByteBuffer) {
val read = input.read(buffer.array())
if (read > 0) {
buffer.limit(read)
val packet = IpDatagram(buffer)
Log.d(Tag, "Received packet: $packet which is " +
if (packet.valid) "valid" else "invalid"
)
(the code I wrote for handling numbers bits)
fun UShort.getBit(position: Int): Int {
return (this.toInt() shr position) and 1;
}
fun UShort.setBit(position: Int, value: Int): UShort {
return (this.toInt() or (value shl position)).toUShort();
}
fun UShort.setBit(position: Int, value: Boolean): UShort {
return (this.toInt() or ((if (value) 1 else 0) shl position)).toUShort();
}
fun UShort.split(): Pair<UShort, UShort> {
return Pair((this.toInt() shr 4).toUShort(), (this.toInt() and 0x0F).toUShort());
}
fun UShort.extract(count: Int): Pair<UShort, UShort> {
return Pair(this.extractFirst(count), this.extractLast(count))
}
fun UShort.extractFirst(count: Int): UShort {
return (this.toInt() shr count).toUShort();
}
fun UShort.extractLast(count: Int): UShort {
return (this.toInt() and ((1 shl count) - 1)).toUShort();
}
I've been debugging this for a while, and I've already tried some things like decomposing the numbers that result to try to see if there are any errors in the methods I created to decompose the integers or if they present patterns like 0100 that I want for IPv4 identification.
Example of one packet after being parsed:
{
"destinationAddress":"95.53.97.33",
"dscp":9,
"ecn":0,
"flags":0,
"fragmentOffset":0,
"headerChecksum":0,
"identification":-384,
"internetHeaderLength":0,
"options":[],
"payload":[96],
"protocol":"HOPOPT" // 0,
"sourceAddress":"101.94.226.95",
"timeToLive":0,
"totalLength":1,
"valid":true,
"version":0
}
I'm working on an audio editing app, and I need to store the samples as floats in an efficient way - memory as well as performance-wise. Right now I'm using simply Kotlin's List, but I've heard about potential gains from using FloatArray type. I made a synthetic test to see the benefits and the results are a bit weird. Any advice on the techniques and collections I should use for large datasets of this nature could earn you a cookie, if I had one and knew your location.
So I have two alternative channel implementations (as in - channel in an audio file), to hold my data.
Here is my code for the channel based on FloatArray:
class ArrayChannel {
private var mData : FloatArray = FloatArray(0)
private var mLastWrittenIndex = 0
fun getSamples(startIndex : Int = 0, endIndex : Int = mLastWrittenIndex) : FloatArray
= mData.sliceArray(IntRange(0, endIndex - 1))
fun insertSamples(samples : FloatArray, startIndex : Int = mLastWrittenIndex) {
if (mData.size - mLastWrittenIndex < samples.size) {
val newData = FloatArray(mData.size + samples.size )
mData.copyInto(newData, 0, 0, startIndex)
samples.copyInto(newData, startIndex)
mData.copyInto(newData, startIndex + samples.size, startIndex)
mData = newData
} else {
mData.copyInto(mData, startIndex + samples.size, startIndex, mLastWrittenIndex)
samples.copyInto(mData, startIndex)
}
mLastWrittenIndex += samples.size
}
fun getSamplesSize(): Int = mLastWrittenIndex
}
And here is my code for the channel based on List:
class Channel {
private var mData = mutableListOf<Float>()
fun getSamples(startIndex : Int = 0, endIndex : Int = mData.size) : List<Float>
= mData.slice(IntRange(0, endIndex - 1))
fun insertSamples(samples : List<Float>, startIndex : Int = mData.size) {
mData.addAll(startIndex, samples)
}
fun getSamplesSize() : Int = mData.size
}
Here is the measuring code:
val initialValuesArray = FloatArray(1000000) {Random.nextFloat()}
val valuesToAddArray = FloatArray(1000000) {Random.nextFloat()}
val initialValuesList = MutableList(1000000) {Random.nextFloat()}
val valuesToAddList = MutableList(1000000) {Random.nextFloat()}
var startTime = System.currentTimeMillis()
val arrayChannel = ArrayChannel()
arrayChannel.insertSamples(initialValuesArray)
arrayChannel.insertSamples(valuesToAddArray, 0)
println("Array time: ${System.currentTimeMillis() - startTime}")
startTime = System.currentTimeMillis()
val listChannel = Channel()
listChannel.insertSamples(initialValuesList)
listChannel.insertSamples(valuesToAddList, 0)
println("List time: ${System.currentTimeMillis() - startTime}")
Now, the average results from a direct fun main() call in Android studio are as following:
Array time: 56
List time: 6
A change in the allocation of the array, instead of mData.size + samples.size to mData.size + samples.size * 2, makes these different, in a very weird way:
Array time: 17
List time: 48
When I run the same code inside of an Activity instead of some main Kotlin function, the results match more what I was expecting and are promising:
2020-08-17 21:15:33.325 D/ARRAY_TIME: 15
2020-08-17 21:15:33.481 D/LIST_TIME: 156
Why the code behaves this way and what do you think would be a good way of handling lots of numerical data in the Android environment?
Info
I have an Item class file as follows:
class Item(var color:String, var numValue:Int, var drawableID:Int){
init {
color = this.color
numValue = this.numValue
drawableID = this.drawableID
}
}
In the main code I create an array which contains 104 objects by default attributes:
var myItemClassArray = Array(104) { Item("", -99, -99) }
Also I have pictures in my drawable folder and I have their IDs in an array which is drawablesIDs:Array<Int>, and it contains 53 elements.
Problem
I want to assign my Item attributes as in this picture: https://i.stack.imgur.com/wFVsn.png I can do it for a similar problem (which has 106 objects and 53 drawables) with the code given in below:
for (i in 0 until 106) {
if (i < 13) {
myItemClassList[i+2].color = "kirmizi"
myItemClassList[i+2].numValue = i+1
myItemClassList[i+2].drawableID = drawablesIDs[i+1]
} else if (i in 13..25) {
myItemClassList[i+2].color = "siyah"
myItemClassList[i+2].numValue = (i+1)-13
myItemClassList[i+2].drawableID = drawablesIDs[i+1]
} else if (i in 26..38) {
myItemClassList[i+2].color = "yesil"
myItemClassList[i+2].numValue = (i+1)-26
myItemClassList[i+2].drawableID = drawablesIDs[i+1]
} else if (i in 39..51) {
myItemClassList[i+2].color = "mavi"
myItemClassList[i+2].numValue = (i+1)-39
myItemClassList[i+2].drawableID = drawablesIDs[i+1]
} else if (i in 52..64) {
myItemClassList[i+2].color = "kirmizi"
myItemClassList[i+2].numValue = (i+1)-52
myItemClassList[i+2].drawableID = drawablesIDs[(i+1)-52]
} else if (i in 65..77) {
myItemClassList[i+2].color = "siyah"
myItemClassList[i+2].numValue = (i+1)-65
myItemClassList[i+2].drawableID = drawablesIDs[i+1-65+13]
} else if (i in 78..90) {
myItemClassList[i+2].color = "yesil"
myItemClassList[i+2].numValue = (i+1)-78
myItemClassList[i+2].drawableID = drawablesIDs[i+1-78+26]
} else if (i in 91..103) {
myItemClassList[i+2].color = "mavi"
myItemClassList[i+2].numValue = (i+1)-91
myItemClassList[i+2].drawableID = drawablesIDs[i+1-91+39]
} else {
myItemClassList[0].color = "sahte"
myItemClassList[0].drawableID = drawablesIDs[0]
myItemClassList[1].color = "sahte"
myItemClassList[1].drawableID = drawablesIDs[0]
}
}
Is there a cleaner way to do this?
One can use lambda expression to create an array. For example:
val test = Array(28){i-> examples[i]}
This works fine with one "i" parameter. But if I want to try something like this:
val test = Array(28){if(i<13)-> examples[i]}
it gives me an error because of it's syntax is wrong.
More Simple Question
Let's say we have an array which has numbers from 0 to 28 like this:
val testNumbers= Array(28){i->i}
Now I want to create an array which will contain numbers from 0 to 10 using lambda.
How do I this:
val player6 = Array(10){(it<10) -> testNumbers[it]} // gives an syntax error
From what I could gather from your picture, I've made these three assumptions:
The numValue is grouped in groups of 13 items
Each group receives a color in the order: kirmizi -> siyah -> yesil -> mavi, then it cycles again
The drawable IDs cycles every 52 items
Based on this, I came up with the following solution:
data class Item(var color: String = "", var numValue: Int = -99, var drawableId: Int = -99)
fun main() {
val colors = listOf("kirmizi", "siyah", "yesil", "mavi")
val drawableIDs = (0..52).toList() // This is just a stub. in your case it will be your drawable lists
val edgeCase = arrayListOf(Item("sahte", drawableId = drawableIDs[0]), Item("sahte", drawableId = drawableIDs[0]))
val pattern = (0 until 104)
.map { index -> Pair(index, index / 13) }
.map { (index, group) ->
Item(
color = colors[group % 4],
numValue = index+1,
drawableId = drawableIDs[(index % 52) + 1]
)
}
val total = pattern + edgeCase
total.forEach { println(it) }
}
You can play around with it on this kotlin playground.
Is there a cleaner way to do this?
From what I gather, you want to initialize only the first 13 values of a contiguous array with 28 spaces, leaving the rest with either their default values or null.
The reason why your code doesn't work is because the Array initializer expects you to return an object. the if block by itself is not an expression in kotlin, so it doesn't evaluate to a value, so you need to provide an else branch for it to work.
val examples = Array(28) { if (i < 13) examples[i] else defaultExample }
This is stated in the Kotlin documentation for control flow:
If you're using if as an expression rather than a statement (for example, returning its value or assigning it to a variable), the expression is required to have an else branch.
More simple question
In this case you could just use take:
// If you don't want to modify it
val player6 = testNumbers.take(10)
.toTypedArray() // Since take returns a List, you need to turn it back into an array
// If you want to modify the items
val player6 = testNumbers.take(10)
.map { value -> modifyNumber(value) }
.toTypedArray()
Tip: In kotlin if you declare your constructor parameter with val or var they are already attributes from your class and you don't need to initialize manually in the init block.
/*
* You don't need to do this:
* class Item(var color: String, var numValue: Int, var drawableId: Int) {
* init {
* this.color = color
* this.numValue = numValue
* this.drawableId = drawableId
* }
* }
*/
// Kotlin already does it for you
class Item(var color: String, var numValue: Int, var drawableId: Int)
fun main() {
val myitem = Item("blue", 20, 100)
println(myitem.color)
println(myitem.numValue)
println(myitem.drawableId)
}
Here is a possible solution :
fun getColor(i: Int) = when (i) {
in 0..1 -> "sahte"
in 2..13, in 52..64 -> "kirmizi"
in 65..77, in 13..25 -> "siyah"
in 26..38, in 78..90 -> "yesil"
in 39..51, in 91..103 -> "mavi"
else -> ""
}
fun getNumValue(i: Int) = when (i) {
in 0..1 -> -99
in 2..13 -> i - 1
in 13..25 -> (i - 1) - 13
in 26..38 -> (i - 1) - 26
in 39..51 -> (i - 1) - 39
in 52..64 -> (i - 1) - 52
in 65..77 -> (i - 1) - 65
in 78..90 -> (i - 1) - 78
in 91..103 -> (i - 1) - 91
else -> -99
}
fun getDrawableID(i: Int) = when (i) {
in 0..1 -> drawablesIDs[0]
in 2..13, in 13..25, in 26..38, in 39..51 -> drawablesIDs[i - 1]
in 52..64 -> drawablesIDs[(i - 1) - 52]
in 65..77 -> drawablesIDs[i - 1 - 65 + 13]
in 78..90 -> drawablesIDs[i - 1 - 78 + 26]
in 91..103 -> drawablesIDs[i - 1 - 91 + 39]
else -> -99
}
val myItemClassArray = Array(104) {
Item(getColor(it), getNumValue(it), getDrawableID(it))
}
Maybe there is some mistakes in the different ranges.
The main advantages are :
each mapping is testable independently
no mutability
I am trying to get hotels to the length of the route, using REST request
The request has a parameter compressedRoute, but the conversion algorithm in Java script language.
Is there such an algorithm in Java or Kotlin? Maybe such a request is in the SDK, but I do not see it?
points to take from route.routeElements.geometry.allPoints?
I managed to compress the route. The problem was in the error of the example on JS.
First you need to go through to limit the number of points in the route, I set 120. If you do more, 414 errors may occur
fun execute(route: Route, categoryName: String, radiusInMeters: Int): Single<List<ItemPlaceByCorridor>> {
val allPointList = route.routeGeometry
val pointList = ArrayList<GeoCoordinate>()
for ((index, elem) in allPointList.withIndex()) {
if (index % (allPointList.size / POINTS_IN_ROUTE) == 0 || (index == 0) || (index == allPointList.lastIndex)) {
pointList.add(elem)
}
}
var routeStr = hereEncodePolyline(pointList)
routeStr += ";w=$radiusInMeters"
return mHereMapsApi.getPlacesByCorridor(categoryName, routeStr)
.map { response -> response.results.listItems }
}
Algorithm transferred from JS to Kotlin
private fun hereEncodePolyline(positions: List<GeoCoordinate>): String {
var lastLat = 0.0
var lastLon = 0.0
var result = ""
for (i in 1..positions.lastIndex) {
val elem = positions[i]
result += hereEncodeFloat(elem.latitude - lastLat)
result += hereEncodeFloat(elem.longitude - lastLon)
lastLat = elem.latitude
lastLon = elem.longitude
}
return result
}
private fun hereEncodeFloat(value: Double): String {
val chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
var result = ""
// convert to fixed point
var fixedPoint = Math.round(value * 100000)
// make room on the lowest bit
fixedPoint = fixedPoint shl (1)
// flip bits of negative numbers and ensure that the last bit is set
// (should actually always be the case, but for readability it is ok to do it explicitly)
if (fixedPoint < 0) {
fixedPoint = (fixedPoint.inv()) or 0x01
}
// var-length encode the number in chunks of 5 bits starting with the least significant
// to the most significant
while (fixedPoint > 0x1F) {
result += (chars[((fixedPoint and 0x1F) or 0x20).toInt()]).toString()
fixedPoint = fixedPoint shr (5)
}
result += (chars[fixedPoint.toInt()])
return result
}
I tried to use this tutorial youtube tutorial. I have a function as follows:
fun fact(x:Int):Int{
tailrec fun factTail(y:Int, z:Int):Int{
return if(y == 0) {
z
} else {
factTail(y - 1, y * z)
}
}
return factTail(x,1)
}
and this function is called in oncreate as:
var abc = fact(5)
Log.i(TAG, "5! = $abc")
When the app outputs log it shows like this:
I/MainActivity: 5! = 0
Can anyone point out what is wrong here.
You code is right and you definitely get 0 for multiple result more than MAX_SIZE of Int value. You can get Int max size with:
Int.MAX_VALUE
So if this y * x cross Int.MAX_VALUE = 2147483647, fun will return 0 to you.
For number bigger than 16 func will return minus number and for greater than 33 it will return 0. you can check this by:
for(x in 5..50){
log.i("$x! : ${fact(x)}")
}
So you can handle this by changing variable from Int to Long
fun fact(x : Long) : Long {
fun factTail(y : Long , z :Long):Long {
return if (y == 0L) z
else return factTail(y-1 ,y*z)
}
return factTail(x ,1)
}
But Long also have its limitation. Hope you get the point.