How to convert digit to character in Kotlin? - kotlin

I'm trying to find the simplest way to convert a digit (0..9) into the respective character '0'..'9' in Kotlin.
My initial attempt was to write the following code:
fun convertToCharacter() {
val number = 0
val character = number.toChar()
println(character)
}
Of course, after running, I quickly saw that this produces \u0000, and not '0' like I expected. Then, remembering from how to do this in Java, I modified the code to add '0', but then this would not compile.
fun convertToCharacter() {
val number = 0
val character = number.toChar() + '0'
println(character)
}
What is the appropriate way to convert a number into its respective character counterpart in Kotlin? Ideally, I'm trying to avoid pulling up the ASCII table to accomplish this (I know I can add 48 to the number since 48 -> '0' in ASCII).

val character = '0' + number
is the shortest way, given that the number is in range 0..9

Kotlin stdlib provides this function since 1.5.0.
fun Int.digitToChar(): Char
Returns the Char that represents this decimal digit. Throws an exception if this value is not in the range 0..9.
If this value is in 0..9, the decimal digit Char with code '0'.code + this is returned.
Example
println(5.digitToChar()) // 5
println(3.digitToChar(radix = 8)) // 3
println(10.digitToChar(radix = 16)) // A
println(20.digitToChar(radix = 36)) // K

Like you said, probably the easiest way to convert an Int to the Char representation of that same digit is to add 48 and call toChar():
val number = 3
val character = (number + 48).toChar()
println(character) // prints 3
If you don't want to have the magic 48 number in your program, you could first parse the number to a String and then use toCharArray()[0] to get the Char representation:
val number = 3
val character = number.toString().toCharArray()[0]
println(character) // prints 3
Edit: in the spirit of the attempt in your question, you can do math with '0'.toInt() and get the result you were expecting:
val number = 7
val character = (number + '0'.toInt()).toChar()
println(number) // prints 7

How about 0.toString() instead of 0.toChar() ? If you are specifically after single digits, then 0.toString()[0] will give you a Char type

You can use an extension like this:
fun Int.toReadableChar(): Char {
return ('0'.toInt() + this).toChar()
}
You can apply this to any other class you want :)
Example:
println(7.toReadableChar())
>> 7

Related

Input out of range for Int datatype, not passing a testcase

I am trying to solve the following question on LeetCode; Write a function that takes an unsigned integer and returns the number of '1' bits it has. Constraints: The input must be a binary string of length 32.
I have written the following code for that which works fine for inputs 00000000000000000000000000001011 and 00000000000000000000000010000000 (provided internally by the website) but give output 0 for input 11111111111111111111111111111101 and in my local compiler for the last input it says "out of range"
class Solution {
// you need treat n as an unsigned value
fun hammingWeight(n:Int):Int {
var num = n
var setCountBit = 0
while (num > 0) {
setCountBit++
num= num and num-1
}
return setCountBit
}
}
To correctly convert binary string to Int and avoid "out of range error", you need to do the following (I believe LeetCode does the same under the hood):
fun binaryStringToInt(s: String): Int = s.toUInt(radix = 2).toInt()
"11111111111111111111111111111101" is equivalent to 4294967293. This is greater than Int.MAX_VALUE, so it will be represented as negative number after .toInt() convertion (-3 in this case).
Actually, this problem could be solved with one-liner in Kotlin 1.4:
fun hammingWeight(n: Int): Int = n.countOneBits()
But LeetCode uses Kotlin 1.3.10, so you need to adjust your solution to handle negative Ints as well.
Please change the type of your input variable from Int to a type like Double .At the moment The given value is bigger than the maximum value that a type Int number can store.

scanner in kotlin to read in 2 lines

Here is the code. n continually outputs 50 and not 2:
import java.util.*
fun main(args: Array<String>) {
val scanner = Scanner(System.`in`)
val n = scanner.next().first().toInt()
val array1 = readLine()!!.split(" ").map { it.toInt() }
var product:Int=0
println(n)
println(array1[0])
println(array1[1])
if (n ==2) {
product = array1[0] * array1[1]
}
println(product)
}
Sample Input:
2
5 3
Output:
2
5 3
50
5
3
0
How do I use scanner in kotlin to read in 2 lines?
Short form
Use scanner.nextInt() instead of scanner.next().first().toInt().
Explanation
By calling scanner.next() you receive the next complete token of the Scanner as a String. Then you take the first character using first(). The problem is, that calling toInt() on a Char will not parse the string as an integer value but return the ASCII char code of the char.
Example: '2'.toInt() returns 50 and not 2 since the ASCII char code of 2 is 50. (See https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html)
Conclusion: In your case, directly read the integer value from the Scanner using scanner.nextInt(), but if you want to convert a char to an integer by "parsing", convert it to a string first: '2'.toString().toInt() will return an integer with the value 2
Addition
It is probably nice to know that you can also use this the other way round: 50.toChar() returns a character with the value '2'.
👍

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'

What happens with toInt()

I currently start to learn Kotlin and I was making this code
val a = "1"
val b = a[0]
val c = b.toInt()
println(c)
When I run the code, the result is 49. What really happened? Because I think the result will be 1.
a is a String, which is a CharSequence. That is why you can access a[0] in the first place. a.get(0) or a[0] then returns a Char. Char on the other hand returns its character value when calling toInt(), check also the documentation of toInt().
So your code commented:
val a = "1" // a is a String
val b = a[0] // b is a Char
val c = b.toInt() // c is (an Int representing) the character value of b
If you just want to return the number you rather need to parse it or use any of the answers you like the most of: How do I convert a Char to Int?
(one simple way being b.toString().toInt()).
a is String,
when you get a[index] return type is char,
in kotlin char.toInt method return ASCII code of the character and it's 49
if you want to get the integer value of "1" just use toString method
val a = "1"
val b = a[0].toString()
val c = b.toInt()
println(c)
prints:1
In your example a is a String, but String. String is under the hood an Array of Char. And by accessing your String using a[0] operator, you get first element of this Char Array. So you get Char '1', not String "1". And now, when you run '1'.toInt() function on Char - it will return ASCII code of that Char. When you run "1".toInt() on String - it will convert this String into Int "1". When you need to get Int value of first letter in your String, you need to convert it first into String:
val a = "123"
val b = a[0].toString() // returns first Char of String "123" and converts to String
val c = b.toInt() // returns Int: 1
or in one line:
"123"[0].toString().toInt()

Why single char and "single char String" not equal when converted to long (.toLong())

I wanted to sum the digits of Long variable and add it to the variable it self, I came with the next working code:
private fun Long.sumDigits(): Long {
var n = this
this.toString().forEach { n += it.toString().toLong() }
return n
}
Usage: assert(48.toLong() == 42.toLong().sumDigits())
I had to use it.toString() in order to get it work, so I came with the next test and I don't get it's results:
#Test
fun toLongEquality() {
println("'4' as Long = " + '4'.toLong())
println("\"4\" as Long = " + "4".toLong())
println("\"42\" as Long = " + "42".toLong())
assert('4'.toString().toLong() == 4.toLong())
}
Output:
'4' as Long = 52
"4" as Long = 4
"42" as Long = 42
Is it a good practice to use char.toString().toLong() or there is a better way to convert char to Long?
Does "4" represented by chars? Why it is not equal to it char representation?
From the documentation:
class Char : Comparable (source) Represents a 16-bit Unicode
character. On the JVM, non-nullable values of this type are
represented as values of the primitive type char.
fun toLong(): Long
Returns the value of this character as a Long.
When you use '4' as Long you actually get the Unicode (ASCII) code of the char '4'
As mTak says, Char represents a Unicode value. If you are using Kotlin on the JVM, you can define your function as follows:
private fun Long.sumDigits() = this.toString().map(Character::getNumericValue).sum().toLong()
There's no reason to return Long rather than Int, but I've kept it the same as in your question.
Non-JVM versions of Kotlin don't have the Character class; use map {it - '0'} instead.