NumberFormatException in Kotlin - string

I was solving a question on CodeChef. A specific line to take input like:
10 232 4543
I was willing to store it in variables and then perform the calculation.
The following is the line of code I am using to achieve this.
val (d,l,r) = readLine()!!.split(" ").map{ it -> it.toInt()}
This line worked for previous question but is not working for the current question. I am inserting my code and the link to the question.
fun main(){
var t = readLine()!!.toInt()
for(i in 0 until t){
val (d,l,r) = readLine()!!.split(" ").map{ it -> it.toInt()}
if(d<l){
println("Too Early")
}
else if(d>r){
println("Too Late")
}
else{
println("Take second dose now")
}
}
}
This is the link to the question: https://www.codechef.com/LP1TO201/problems/VDATES
The following is the error I am receiving.
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:678)
at java.base/java.lang.Integer.parseInt(Integer.java:786)
at ProgKt.main(prog.kt:4)
at ProgKt.main(prog.kt)

An empty string is not a number. There are two easy ways to solve this:
Filter empty strings using isEmpty():
val (d,l,r) = readLine()!!.split(" ").filterNot { it.isEmpty() }.map { it -> it.toInt() }
Use toIntOrNull() and only take non-null elements:
val (d,l,r) = readLine()!!.split(" ").mapNotNull { it -> it.toIntOrNull() }

Related

How to format string to phone number kotlin alghorithm

I get a string containing a phone number as input. This string looks like this:
79998886666
But I need to convert it to this form:
+7 999 888-66-66
I tried several ways, but the most recent one I got looks like this:
private fun formatPhone(phone: String): String {
val prefix = "+"
val countryCode = phone.first()
val regionCode = phone.dropLast(7).drop(1)
val firstSub = phone.dropLast(4).drop(4)
val secondSub = phone.dropLast(2).drop(7)
val thirdSub = phone.drop(9)
return "$prefix$countryCode $regionCode $firstSub-$secondSub-$thirdSub"
}
But it seems to me that this method looks rather strange and does not work very efficiently.
How can this problem be solved differently?
You could use a regex replacement here:
val regex = """(\d)(\d{3})(\d{3})(\d{2})(\d{2})""".toRegex()
val number = "79998886666"
val output = regex.replace(number, "+$1 $2 $3-$4-$5")
println(output) // +7 999 888-66-66
You could create a helper function that returns chunks of the String at a time:
private fun formatPhone(phone: String): String {
fun CharIterator.next(count: Int) = buildString { repeat(count) { append(next()) } }
return with(phone.iterator()) {
"+${next(1)} ${next(3)} ${next(3)}-${next(2)}-${next(2)}"
}
}
Your original code could be simplified and made more performant by using substring instead of drop/dropLast.

How can I make Spinner function stop crashing my app when trying to get the selected item?

I'm having Trouble getting string values from a spinner without it crashing my app , I want to make a choice according to the 2 pair of selected items in the when Function
val convertFrom = spnConvertFrom.selectedItem.toString()
val convertTo = spnConvertTo.selectedItem.toString()
val value = initialAmount.toString()
var valor2= value.toDouble()
when {
//Condicion
(convertFrom.equals("NIO") && convertTo.equals("USD")) -> currencyConverted.apply {
text = "Something"
}
else -> Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show()
}
I've tried to switch the syntax a bit from = to .equals() (Same thing) Read something about it being null at the moment of the comparison but have no idea how to check it , I'm quite new to Kotlin and programing in android
There are several lines which could case an NPE
The lines where you are retrieving the selectedItem. You can handle those by adding the ? operator after the spinner instances
The line where you convert value to a Double. You can avoid the error by using toDoubleOrNulland providing a default value in case thatvalue` is not numeric
The line where you set the text of currencyConverted. If it is optional you should add the ? operator there as well:
val convertFrom = spnConvertFrom?.selectedItem.toString()
val convertTo = spnConvertTo?.selectedItem.toString()
val value = initialAmount.toString()
var valor2 = value.toDoubleOrNull() ?: 0.0
when {
//Condicion
(convertFrom.equals("NIO") && convertTo.equals("USD")) -> currencyConverted?.text = "Something"
else -> Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show()
}

Making sure every Alphabet is in a string (Kotlin)

So I have a question where I am checking if a string has every letter of the alphabet in it. I was able to check if there is alphabet in the string, but I'm not sure how to check if there is EVERY alphabet in said string. Here's the code
fun isPangram (pangram: Array<String>) : String {
var panString : String
var outcome = ""
for (i in pangram.indices){
panString = pangram[i]
if (panString.matches(".^*[a-z].*".toRegex())){
outcome = outcome.plus('1')
}
else {outcome = outcome.plus('0')}
}
return outcome
}
Any ideas are welcomed Thanks.
I think it would be easier to check if all members of the alphabet range are in each string than to use Regex:
fun isPangram(pangram: Array<String>): String =
pangram.joinToString("") { inputString ->
when {
('a'..'z').all { it in inputString.lowercase() } -> "1"
else -> "0"
}
}
Hi this is how you can make with regular expression
Kotlin Syntax
fun isStrinfContainsAllAlphabeta( input: String) {
return input.lowercase()
.replace("[^a-z]".toRegex(), "")
.replace("(.)(?=.*\\1)".toRegex(), "")
.length == 26;
}
In java:
public static boolean isStrinfContainsAllAlphabeta(String input) {
return input.toLowerCase()
.replace("[^a-z]", "")
.replace("(.)(?=.*\\1)", "")
.length() == 26;
}
the function takes only one string. The first "replaceAll" removes all the non-alphabet characters, The second one removes the duplicated character, then you check how many characters remained.
Just to bounce off Tenfour04's solution, if you write two functions (one for the pangram check, one for processing the array) I feel like you can make it a little more readable, since they're really two separate tasks. (This is partly an excuse to show you some Kotlin tricks!)
val String.isPangram get() = ('a'..'z').all { this.contains(it, ignoreCase = true) }
fun checkPangrams(strings: Array<String>) =
strings.joinToString("") { if (it.isPangram) "1" else "0" }
You could use an extension function instead of an extension property (so it.isPangram()), or just a plain function with a parameter (isPangram(it)), but you can write stuff that almost reads like English, if you want!

Trying to create a Map[String, String] from lines in a text file, keep getting errors [duplicate]

This question already has an answer here:
Most efficient way to create a Scala Map from a file of strings?
(1 answer)
Closed 4 years ago.
Hi so I'm trying to create a Map[String, String] based on a text file, in the textfile there are arbritrary lines that begin with ";;;" that I ignore with the function and the lines that i dont ignore are the key-> values. they are separated by 2 spaces.
whenever i run my code i get an error saying the expected type Map[String,String] isn't the required type, even though my conversions seem correct.
def createMap(filename: String): Map[String,String] = {
for (line <- Source.fromFile(filename).getLines) {
if (line.nonEmpty && !line.startsWith(";;;")) {
val string: String = line.toString
val splits: Array[String] = string.split(" ")
splits.map(arr => arr(0) -> arr(1)).toMap
}
}
}
I expect it to return a (String -> String) map but instead i get a bunch of errors. how would i fix this?
Since your if statement is not an expression in the for-loop. You should use the if as a filter when yielding your results. To return a result, you must make it a for-comprehension. After the for-comprehension filters the results. You can map this structure to a Map.
import scala.io.Source
def createMap(filename: String): Map[String,String] = {
val keyValuePairs = for (line <- Source.fromFile(filename).getLines; if line.nonEmpty && !line.startsWith(";;;")) yield {
val string = line.toString
val splits: Array[String] = string.split(" ")
splits(0) -> splits(1)
}
keyValuePairs.toMap
}
Okay, so I took a second look. It looks like the file has some corrupt encodings. You can try this as a solution. It worked in my Scala REPL:
import java.nio.charset.CodingErrorAction
import scala.io.{Codec, Source}
def createMap(filename: String): Map[String,String] = {
val decoder = Codec.UTF8.decoder.onMalformedInput(CodingErrorAction.IGNORE)
Source.fromFile(filename)(decoder).getLines()
.filter(line => line.nonEmpty && !line.startsWith(";;;"))
.flatMap(line => {
val arr = line.split("\\s+")
arr match {
case Array(key, value) => Some(key -> value)
case Array(key, values#_*) => Some(key -> values.mkString(" "))
case _ => None
}
}).toMap
}

Scala: convert each digit in a string to an integer

I want to convert each digit in a number to an int. Here is my code
for (in <- lines) {
for (c <- in) {
val ci = c.toInt
if (ci == 0) {
// do stuff
}
}
}
The result I get is the ascii code, i.e. a 1 gives 49. I'm looking for the value 1.
The answer is trivial, I know. I'm trying to pull myself up with my own bootstraps until my Scala course begins in two weeks. Any assistance gratefully accepted.
One possible solution is:
for(in <- lines) {
in.toString.map(_.asDigit).foreach { i =>
if(i == 1) {
//do stuff
}
}
}
And more compact w/ output:
lines.foreach(in => in.toString.map(_.asDigit).filter(_ == 1).foreach(i => println(s"found $i in $in.")))
If lines is already a collection of Strings, omit the .toString on in.toString.
You can have this:
val number = 123456
//convert Int to String and do transformation for each character to Digit(Int)
val digitsAsList = number.toString.map(_.asDigit)
This will result to digitizing the number. Then with that Collection, you can do anything from filtering, mapping, zipping: you can checkout the the List api on this page: http://www.scala-lang.org/api/2.11.8/#scala.collection.immutable.List
Hope that's help.

Resources