How do we round only if the number is with .0 in decimal - kotlin

Ex 10.0 = 10
10.3 = 10.3
10.7 = 10. 7
Looking for a convenient way from Kotlin Standard library

You can use the following function:
fun removeTrailingZeros(num: String): String {
if(!num.contains('.')) // Return the original number if it doesn't contain decimal
return num
return num
.dropLastWhile { it == '0' } // Remove trailing zero
.dropLastWhile { it == '.' } // Remove decimal in case it's the last character in the resultant string
}
You can verify the code here

You can try this:
double number = 23.471;
if (number % 1 != 0)
{
//round off here
System.out.print ("Decimal");
}
else
{
System.out.print ("Integer");
}

If you want to get a string, the easiest way is to work with a string like num.toString().replace(".0",""). For numbers conversion does not make sense since the resulting type is different for different inputs.

Related

Format a number to string, fill 0 when it's not enough two characters

I want to format the number to String and fill 0 when it's not enough two characters
fun formatDuration(val duration):String {
val minutes = duration.toInt() / 60
return "$minutes"
}
For example, if minutes is 6, it should displayed 06 rather than 6.
You can padStart the toString() result of minutes.
I tried your code in the Kotlin Playground and it wasn't compilable / runnable. For the following example, I had to change parts of your fun:
fun main() {
println(formatDuration(364.34))
}
fun formatDuration(duration: Double): String {
val minutes = duration.toInt() / 60
// fill the result to be of 2 characters, use 0 as padding char
return minutes.toString().padStart(2, '0')
}
Executing this results in the output 06.
Alternatively, you can simply use String.format() from Java, just
return "%02d".format(minutes)
instead of return minutes.toString().padStart(2, '0'), the result stays the same.
You can achive this with padStart
Example:
val padWithSpace = "125".padStart(5)
println("'$padWithSpace'") // ' 125'
val padWithChar = "a".padStart(5, '.')
println("'$padWithChar'") // '....a'
// string is returned as is, when its length is greater than the specified
val noPadding = "abcde".padStart(3)
println("'$noPadding'") // 'abcde'

How to properly iterate over arrays in kotlin

I am currently learning kotlin and therefore following the kotlin track on exercism. The following exercise required me to calculate the Hamming difference between two Strings (so basically just counting the number of differences).
I got to the solution with the following code:
object Hamming {
fun compute(dnaOne: String, dnaTwo: String): Int {
if (dnaOne.length != dnaTwo.length) throw IllegalArgumentException("left and right strands must be of equal length.")
var counter = 0
for ((index, letter) in dnaOne.toCharArray().withIndex()) {
if (letter != dnaTwo.toCharArray()[index]) {
counter++
}
}
return counter
}
}
however, in the beginning I tried to do dnaOne.split("").withIndex() instead of dnaOne.toCharArray().withIndex() which did not work, it would literally stop after the first iteration and the following example
Hamming.compute("GGACGGATTCTG", "AGGACGGATTCT") would return 1 instead of the correct integer 9 (which only gets returned when using toCharArray)
I would appreciate any explanation
I was able to simplify this by using the built-in CharSequence.zip function because StringimplementsCharSequence` in Kotlin.
According to the documentation for zip:
Returns a list of pairs built from the characters of this and the [other] char sequences with the same index
The returned list has length of the shortest char sequence.
Which means we will get a List<Pair<Char,Char>> back (a list of pairs of letters in the same positions). Now that we have this, we can use Iterable.count to determine how many of them are different.
I implemented this as an extension function on String rather than in an object:
fun String.hamming(other: String): Int =
if(this.length != other.length) {
throw IllegalArgumentException("String lengths must match")
} else {
this.zip(other).count { it.first != it.second }
}
This also becomes a single expression now.
And to call this:
val ham = "GGACGGATTCTG".hamming("AGGACGGATTCT")
println("Hamming distance: $ham")

Add commas or point every 3 digits using kotlin

I want to add commas or point every 3 digit in EditText input.
Example :
input : 1000. Output : 1.000
input : 11000. Output : 11.000
If you are on the JVM you can use
"%,d".format(input)
which gives 11,000 for input 11000. Replace , with any delimiter you require.
If you want to use predefined number formats, e.g. for the current locale, use:
java.text.NumberFormat.getIntegerInstance().format(input);
Be also sure to check the other format instances, e.g. getCurrencyInstance or getPercentInstance. Note that you can use NumberFormat also with other locales. Just pass them to the get*Instance-method.
Some of the second variant can also be found here: Converting Integer to String with comma for thousands
If you are using it via Javascript you may be interested in: How do I format numbers using JavaScript?
Based on Splitframe answer above, did a simplified version (without the var):
fun Int.formatDecimalSeparator(): String {
return toString()
.reversed()
.chunked(3)
.joinToString(",")
.reversed()
}
And added some tests:
#Test
fun whenFormatDecimal_thenReturnFormatted() {
mapOf(
1 to "1",
12 to "12",
123 to "123",
1234 to "1,234",
12345 to "12,345",
123456 to "123,456",
1234567 to "1,234,567",
12345678 to "12,345,678",
123456789 to "123,456,789",
1234567890 to "1,234,567,890",
).forEach { (test, expected) ->
val result = test.formatDecimalSeparator()
assertEquals(expected, result)
}
}
In my case is a KMM project, and we don't support other languages, so it does the job. A better solution I would say to create an expect Util class and each platform implement the formatter taking account of the user Locale, etc.
System.out.println(NumberFormat.getNumberInstance(Locale.US).format(35634646));
This is a simple way that able you to replace default separator with any characters:
val myNumber = NumberFormat.getNumberInstance(Locale.US)
.format(123456789)
.replace(",", "،")
I used this for a non JVM Kotlin environment:
fun formatDecimalSeperators(number :String) :String {
var index = 1
return number
.takeIf { it.length > 3 }
?.reversed()
?.map { if (index++ % 3 == 0) "$it," else it }
?.joinToString("")
?.reversed()
?.removePrefix(",")
?: number
}
You can also use #Roland answer in Android String Resources to format it:
<string name="answer_count">%,01d answers</string>
For a method without getting Locale, you can use an extension to convert your Int into a formatted String like this below :
fun Int.formatWithThousandComma(): String {
val result = StringBuilder()
val size = this.toString().length
return if (size > 3) {
for (i in size - 1 downTo 0) {
result.insert(0, this.toString()[i])
if ((i != size - 1) && i != 0 && (size - i) % 3 == 0)
result.insert(0, "\'")
}
result.toString()
} else
this.toString()
}

Can you map/reduce a String into an Int?

I was solving a problem on codeforces in which I had to sum up the digits of a big number (it can have up to 100k digits) and I'd have to repeat that process until there is only one digit left and count the number of times I did that and I came up with a working solution, however I'd like to know if some things could have been done in a more "Kotlin-ish like way", so given:
fun main(args: Array<String>) {
println(transform(readLine()!!))
}
fun transform(n: String): Int {
var count = 0
var sum : Int
var s = n
while(s.length > 1) {
sum = (0 until s.length).sumBy { s[it].toInt() - '0'.toInt() }
s = sum.toString()
count++
}
return count
}
sum = (0 until s.length).sumBy { s[it].toInt() - '0'.toInt() } is there a way to I guess map the sum of digits in the string to the sum variable, or in general a better approach than the one I used?
When converting a Char to an Int it converts it to the ASCII value so I had to add "-'0'.toInt()" is there a faster way (not that it's too much to write, asking out of curiosity)?
How to make the String n mutable without creating a new String s and manipulating it? Or is that the desired (and only) way?
P.S. I'm a beginner with Kotlin.
When converting a Char to an Int it converts it to the ASCII value so I had to add "-'0'.toInt()" is there a faster way (not that it's too much to write, asking out of curiosity)?
You can simply write s[it] - '0', because subtracting Chars in Kotlin already gives you an Int:
public class Char ... {
...
/** Subtracts the other Char value from this value resulting an Int. */
public operator fun minus(other: Char): Int
...
}
But why are looping over the indexes when you could loop over the Chars directly?
sum = s.sumBy { it - '0' }
This is a functional (and recursive) style to solve it:
private fun sum(num: String, count: Int) : Int {
return num
//digit to int
.map { "$it".toInt() }
//sum digits
.sum()
//sum to string
.toString()
//if sum's length is more than one, do it again with incremented count. Otherwise, return the current count
.let { if (it.length > 1) sum(it, count + 1) else count }
}
And you call it like this:
val number = "2937649827364918308623946..." //and so on
val count = sum(number, 0)
Hope it helps!

Error in Print prime number using high order functions in kotlin

val listNumbers = generateSequence(1) { it + 1 }
val listNumber1to100 = listNumbers.takeWhile { it < 100 }
val secNum:Unit = listNumber1to100.forEach {it}
println(listNumber1to100.asSequence().filter { it%(listNumber1to100.forEach { it })!=0 }.toList())
I have an error in reminder sign!
This is Error: None of the following functions can be called with the arguments supplied
In your first approach, the error appears in this line:
it%(listNumber1to100.forEach { it })
A Byte, Double, Float, Int, Long or Short is prefered right after the % operator, however, forEach is a function which the return type is Unit.
In your second approach, you have the correct expression in isPrime(Int). Here are some suggestions for you:
listNumber1to100 is excluding 100 in your code, if you want to include 100 in listNumber1to100, the lambda you pass to takeWhile should be changed like this:
val listNumber1to100 = listNumbers.takeWhile { it <= 100 }
listNumber1to100.asSequence() is redundant here since listNumber1too100 is itself a TakeWhileSequence which implements Sequence.
isPrime(Int) is a bit confusing since it is check for isComposite and it does not work for every input it takes(it works for 1 to 99 only). I will rewrite it in this way:
fun isPrime(num: Int): Boolean = if (num <= 1) false else !(2..num/2).any { num % it == 0 }
Since prime number must be positive and 1 is a special case(neither a prime nor composite number), it just return false if the input is smaller or equal to 1. If not, it checks if the input is divisible by a range of number from 2 to (input/2). The range ends before (input/2) is because if it is true for num % (num/2) == 0, it is also true for num % 2 == 0, vise versa. Finally, I add a ! operator before that because a prime number should not be divisible by any of those numbers.
Finally, you can filter a list by isPrime(Int) like this:
println(listNumber1to100.filter(::isPrime).toList())
PS. It is just for reference and there must be a better implementation than this.
To answer your question about it, it represents the only lambda parameter inside a lambda expression. It is always used for function literal which has only one parameter.
The error is because the expression: listNumber1to100.forEach { it } - is not a number, it is a Unit (ref).
The compiler try to match the modulo operator to the given function signatures, e.g.: mod(Byte) / mod(Int) / mod(Long) - etc.
val listNumbers = generateSequence(1) { it + 1 }
val listNumber1to100 = listNumbers.takeWhile { it < 100 }
fun isPrime(num: Int): Boolean = listNumber1to100.asSequence().any { num%it==0 && it!=num && it!=1 }
println(listNumber1to100.asSequence().filter { !isPrime(it)}.toList())
I found this solution and worked
But why can I have a non-number here in the right side of reminder