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.
Related
I've been learning Kotlin lately and I came across something I can't understand.
import kotlin.random.Random
fun main() {
var maximumDiscountValue = 0
repeat(3) { index ->
val discount = Random.nextInt(10)
println("Attempt ${index+1}: $discount")
if (discount > maximumDiscountValue) {
maximumDiscountValue = discount
}
}
println(maximumDiscountValue)
}
val number = 3
var output = 2
repeat(5) { index ->
output += (index * number)
}
println(output)
I don't understand what "index" does in there. If someone knows what, I'll be glad to know.
The repeat function specifies a number of times (3 and 5 in your case) a specific lambada function has to be executed. Index is a zero-based number that will be incremented during each execution.
In your first repeat
repeat(5) {
... your index will be 0, 1, 2, 3 and 4
}
Here the source code of the repeat function
#kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) -> Unit) {
contract { callsInPlace(action) }
for (index in 0 until times) {
action(index)
}
}
I'm trying to get two views to move to the middle of the screen and bounce back again x number of times.
This code does that but it runs only once.
` val view = findViewById(R.id.imageView2)
val animation = SpringAnimation(view, DynamicAnimation.TRANSLATION_Y, 0f)
val view2 = findViewById<View>(R.id.imageView3)
val animation2 = SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y, 0f)
findViewById<View>(R.id.imageView2).also { img ->
SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
animation.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY)
animation.spring.stiffness = SpringForce.STIFFNESS_VERY_LOW
animation.animateToFinalPosition(50f)
}
}
findViewById<View>(R.id.imageView3).also { img ->
SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
animation2.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY)
animation2.spring.stiffness = SpringForce.STIFFNESS_VERY_LOW
animation2.animateToFinalPosition(-100f)
}
}`
So how do I get it to run x number of times?
This is obviously Spring Animation, but I'm not married to it. If there is another animation that would accomplish this I'd be totally open to changing.
You can run multiple SpringAnimations on the same View by repeatedly calling animateToFinalPosition(translation) with a sequence of translation values.
For example:
startSpringAnimations(findViewById<View>(R.id.imageView1), 300f, 6)
startSpringAnimations(findViewById<View>(R.id.imageView2), -600f, 6)
with a function
/**
* [view] will be moved using [times] SpringAnimations over a distance of abs([totalTranslation])
* If [totalTranslation] is negative, direction will be up, else down
*/
private fun startSpringAnimations(view: View, totalTranslation: Float, times: Int ) {
if(times <= 0){
return
}
val translation = totalTranslation/ times.toFloat()
SpringAnimation(view, DynamicAnimation.TRANSLATION_Y, 0f).apply{
spring.dampingRatio = SpringForce.DAMPING_RATIO_HIGH_BOUNCY
spring.stiffness = SpringForce.STIFFNESS_VERY_LOW
addEndListener(object: DynamicAnimation.OnAnimationEndListener{
private var count = 1
override fun onAnimationEnd(animation1: DynamicAnimation<*>?, canceled: Boolean, value: Float, velocity: Float) {
Log.d("SpringAnimation", "onAnimationEnd: animation $animation1 canceled $canceled value $value velocity $velocity count $count")
if (canceled) return
count++
if(count <= times){
animateToFinalPosition(translation * count)
}
}
})
animateToFinalPosition(translation)
}
}
Set android:repeatCount="infinite" in anim folder
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
The problem here return#Foreach not getting executed it always return false
on the if statement
fun check() {
var x: Int? = null
val numbers = 1..100
numbers.forEach {
x = it
if (it == 2) {
return#forEach
}
}
showingText("$x Hello World")
}
Actually, the it==2 condition is true when it is 2, and the statement return#forEach executed then. You can see it with simple logs:
fun check() {
var x: Int? = null
val numbers = 1..100
numbers.forEach {
println(it)
x = it
if (it == 2) {
println("FINISH")
return#forEach
}
}
println("$x Hello World")
}
So, the return is executed and stops the forEach method. Then the sequence of range moves to the next item (3, 4, and so on) and action is run for it consequently.
If you want to stop actions after 2 found, use simple loop:
fun check2() {
var x: Int? = null
val numbers = 1..100
for(it in numbers) {
println(it)
x = it
if (it == 2) {
println("FINISH")
break
}
}
println("$x Hello World")
}
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
}