Strings as objects kotlin - kotlin

Actually this is an easy task, but I don't know why I still get errors like this
Failed test #4 of 8. Wrong answer
this is my code
fun main() {
val input = readLine()!!
if (input.isEmpty()){
println(input)
} else if (input.first().equals('i')) {
println(input.drop(1).toInt() + 1)
} else if (input.first().equals('s')) {
println(input.drop(1).reversed())
}}
I downloaded the failed test and the result is
ft
you can check the task in this link

Here is the correct answer
fun main() {
val input = readLine()!!
// write code here
if (input.isEmpty()){
println(input)
} else if (input.first().equals('i')) {
println(input.drop(1).toInt() + 1)
} else if (input.first().equals('s')) {
println(input.drop(1).reversed())
} else {
println(input)
}
}

Related

incrementing hash map count in Kotlin

I have the function below. However, when I pass a string to it, I get the following error:
error: operator call corresponds to a dot-qualified call 'charCountMap.get(c).plus(1)' which is not allowed on a nullable receiver 'charCountMap.get(c)'. charCountMap.put(c, charCountMap.get(c) + 1)
private fun characterCount(inputString:String) {
val charCountMap = HashMap<Char, Int>()
val strArray = inputString.toCharArray()
for (c in strArray)
{
if (charCountMap.containsKey(c))
{
charCountMap.put(c, charCountMap.get(c) + 1)
}
else
{
charCountMap.put(c, 1)
}
}
}
The Kotlin Standard Library has groupingBy and eachCount for this purpose, you don't need to do any of this manually:
private fun characterCount(inputString:String) {
val charCountMap : Map<Char, Int> = inputString.groupingBy { it }.eachCount()
}
Note that I put the type on charCountMap for clarity, but it can be left off and inferred.
There is nice compute method in HashMap for this:
private fun characterCount(inputString:String) = hashMapOf<Char, Int>().also { charCountMap ->
inputString.forEach { charCountMap.compute(it) { _, v -> if (v == null) 1 else v + 1 } }
}
Both the other answers are correct. Todd's answer is right, you don't need to write a function for this. Just use the standard library. And if you are going to write a function that updates maps, Михаил Нафталь's suggestion to use compute() to handle updating existing values is also good.
However, if you're just doing this an an exercise, here are three suggestions to fix/improve your algorithm:
Instead of get(), use getValue(), which does not return null. It will raise an exception if the element does not exist, but you already checked for that.
Use the [] operator instead of put() (no need to, it's just nicer syntax).
You don't need to call toCharArray() because Strings are already iterable.
if (charCountMap.containsKey(c))
{
charCountMap[c] = charCountMap.getValue(c) + 1
}
else
{
charCountMap[c] = 1
}
Rewriting the whole thing using standard formatting:
fun characterCount(inputString: String): Map<Char, Int> {
val charCountMap = mutableMapOf<Char, Int>()
for (c in inputString) {
if (charCountMap.containsKey(c)) {
charCountMap[c] = charCountMap.getValue(c) + 1
} else {
charCountMap[c] = 1
}
}
return charCountMap
}

Kotlin, how can I make my code shorter in this spaghetti code?

I'm working on readlines now and can I make this few if's shorter? I'm making a validation to what user is sending to me. The filed cant be empty or null. I have 3 important things that user has to write in field and every three times I have to check the same... .
fun readlinesToAddEntryAndValidation(): List<String> {
println(ENTER_DESCRIPTION_ID_TEKST)
val entryId: String? = readLine()
if (!entryId.isNullOrEmpty()) {
println(ENTER_DESCRIPTION_NAME_TEKST)
val name: String? = readLine()
if (!name.isNullOrEmpty()) {
println(ENTER_DESCRIPTION_TEKST_TEKST)
val tekst: String? = readLine()
if (!tekst.isNullOrEmpty()) {
return listOf(entryId, name, tekst)
} else {
println(EMPTY_READLINE_ERROR)
return readlinesToAddEntryAndValidation()
}
} else {
println(EMPTY_READLINE_ERROR)
return readlinesToAddEntryAndValidation()
}
} else {
println(EMPTY_READLINE_ERROR)
return readlinesToAddEntryAndValidation()
}
}
Try to avoid cognitive complexity one of the things is avoid nesting. Also when an if always returns something. An else statement is not needed
fun readlinesToAddEntryAndValidation(): List<String> {
println(ENTER_DESCRIPTION_ID_TEKST)
val entryId: String? = readLine()
if (entryId.isNullOrEmpty()) {
println(EMPTY_READLINE_ERROR)
return readlinesToAddEntryAndValidation()
}
println(ENTER_DESCRIPTION_NAME_TEKST)
val name: String? = readLine()
if (!name.isNullOrEmpty()) {
println(ENTER_DESCRIPTION_TEKST_TEKST)
val tekst: String? = readLine()
if (!tekst.isNullOrEmpty()) {
return listOf(entryId, name, tekst)
}
}
println(EMPTY_READLINE_ERROR)
return readlinesToAddEntryAndValidation()
}
You could do something like this:
fun readlinesToAddEntryAndValidation() : List<String> {
fun read(message: String): String? {
println(message)
val line = readLine()
return if (line.isNullOrEmpty()) null else line
}
read(ENTER_DESCRIPTION_ID_TEKST)?.let { entryId ->
read(ENTER_DESCRIPTION_NAME_TEKST)?.let { name ->
read(ENTER_DESCRIPTION_TEKST_TEKST)?.let { tekst ->
return listOf(entryId, name, tekst)
}
}
}
println(EMPTY_READLINE_ERROR)
return readlinesToAddEntryAndValidation()
}
I wouldn't normally recommend nesting too much, but I feel like that's fairly readable with only three parameters, and the null checking means it short-circuits as soon as you run into a problem.
Making user to reenter all previous (independent!) values after his mistake in the middle of the input is a bad UI.
If user failed to correctly input some entry, you need to ask him to reenter only this single item (until he eventually do it right):
fun read(inputMessage: String, errorMessage: String = EMPTY_READLINE_ERROR): String {
println(inputMessage)
var line: String? = readLine()
while (line.isNullOrEmpty()) {
println(errorMessage)
println(inputMessage)
line = readLine()
}
return line
}
With this auxilary function, whole program become a single-liner:
fun readlinesToAddEntryAndValidation() =
listOf(
ENTER_DESCRIPTION_ID_TEKST,
ENTER_DESCRIPTION_NAME_TEKST,
ENTER_DESCRIPTION_TEKST_TEKST
).map { read(it) }

Parking lot project error: when using a scanner. NoSuchElementException

I'll appreciate all your help.
I've been working on a course project where I have to make a parking lot that registers cars. When I use it in my IDE it works fine but when I run it through the platforms tests, in the first one, there's no problem but when the second iteration reaches the "when (val command = scanner.next())" in the createOrder fun, it crashes with the error:
java.lang.AssertionError: Exception in test #1
Probably your program run out of input (Scanner tried to read more than expected).
java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at parking.ParkingLot.createOrder(Main.kt:39)
at parking.ParkingLot.start(Main.kt:31)
at parking.MainKt.main(Main.kt:6)
at parking.MainKt.main(Main.kt)
Please find below the output of your program during this failed test.
Note that the '>' character indicates the beginning of the input line.
---
> park KA-01-HH-1234 White
White car parked in spot 1.
the idea is that the test inputs many cars but it crashes when trying to do the second input
this is my code (sorry if my code is messy, I'm still learning)
import java.util.*
fun main() {
ParkingLot.start()
}
class Car(val regNumber: String = "", val color: String = "") {
}
class Order(val command: String) {
lateinit var regNum: String
lateinit var color: String
lateinit var spot: String
lateinit var status: String
}
object ParkingLot {
val spaces: Array<Pair<String?, Car?>> = Array(20) { Pair(null, null) }
const val occupied = "occupied"
const val park = "park"
const val leave = "leave"
const val exit = "exit"
fun start() {
val scanner = Scanner(System.`in`)
do {
val order = createOrder(scanner)
interaction(order, scanner)
} while (order.command != exit)
}
fun createOrder(scanner: Scanner): Order {
when (val command = scanner.next()) {
park -> {
val parkOrder = Order(command)
parkOrder.regNum = scanner.next()
parkOrder.color = scanner.next()
parkOrder.status = "valid"
return parkOrder
}
leave -> {
val retrieveOrder = Order(command)
retrieveOrder.spot = scanner.next()
retrieveOrder.status = "valid"
return retrieveOrder
}
exit -> {
val exitOrder = Order(command)
exitOrder.status = "valid"
return exitOrder
}
else -> {
val incorrectOrder = Order(command)
incorrectOrder.status = "invalid"
return incorrectOrder
}
}
}
fun interaction(order: Order, scanner: Scanner) {
if (order.command == park) {
// val toParkCar = Car(order.regNum, order.color)
park(Car(order.regNum, order.color))
}
if (order.command == leave) {
leave(order)
}
if (order.command == exit) return
//TODO update the error msg to include exit command
if (order.status == "invalid") println("\"${order.command}\" isn't a valid , either use \"park\" or \"leave\"")
// scanner.close()
}
fun park(car: Car) {
for ((index, item) in spaces.withIndex()) {
if (item.first == null) {
spaces[index] = Pair(occupied, car)
println("${car.color} car parked in spot ${index + 1}.")
return
}
}
println("Sorry, the parking lot is full.")
}
fun leave(order: Order) {
if (spaces[order.spot.toInt() - 1].first == occupied) {
spaces[order.spot.toInt() - 1] = Pair(null, null)
println("Spot ${order.spot} is free.")
} else {
println("There is no car in spot ${order.spot}.")
}
}
}
Ok so I noticed this is a problem for the JetBrains plugin. I don't know why but the solution was taking the scanner out of the function and directly in the main loop.

How can i call an interface in kotlin?

I do not have a project in my work and they have asked me to give me a pass, but after passing the whole project, there is a part that has given me a code error at the moment. Clearly it's my first time in Kotlin and I have no idea, but I do have an idea. I tried to solve it and I have not succeeded. So I was asking for help. I get an error right at the beginning of the
= SpeechService.Lintener {
Here the code
private val mSpeechServiceListener = SpeechService.Listener { text: String?, isFinal: Boolean ->
if (isFinal) {
mVoiceRecorder!!.dismiss()
}
if (mText != null && !TextUtils.isEmpty(text)) {
runOnUiThread {
if (isFinal) {
if (mText!!.text.toString().equals("hola", ignoreCase = true) || b == true) {
if (b == true) {
mText!!.text = null
mTextMod!!.text = text
repro().onPostExecute(text)
random = 2
} else {
b = true
mText!!.text = null
val saludo = "Bienvenido, ¿que desea?"
mTextMod!!.text = saludo
repro().onPostExecute(saludo)
}
}
} else {
mText!!.text = text
}
}
}
}
and here the interface
interface Listener {
fun onSpeechRecognized(text: String?, isFinal: Boolean)
}
Please, help me. the error is "Interface Listener does not have constructor"
The SpeechService.Listener { } syntax for SAM interfaces is only possible when the interface is written i Java (see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions). Because the interface is written in Kotlin, you have to write it like this:
private val mSpeechServiceListener = object : SpeechService.Listener {
override fun onSpeechRecognized(text: String?, isFinal: Boolean) {
// Code here
}
}
You don't really need the SpeechService.Listener interface in Kotlin though. You could just use a lambda function. This depends on whether the interface comes from a library or if you've written it yourself though.
private val mSpeechServiceListener: (String?, Boolean) -> Unit = { text, isFinal ->
// Code here
}

Kotlin KCallable illegalArgumentException

I have the following Kotlin function:
fun invokeSync(typedArguments : List<Any?>): Any?{
var returnedValue : Any?
try {
returnedValue = callable.call(this, typedArguments);
} catch (e:Exception) {
logInvocationError(e, typedArguments);
throw IllegalArgumentException(e);
}
}
It doesn't matter how much arguments are in this list, I will always get an IllegalArgumentException saying "Callable expects 3 arguments, but 1 were provided".
The function is a simple isGreater-function with 2 arguments of type Int.
I have checked the list of arguments and there are 2 arguments of type Int in there.
Here the function in context:
open class TypedJavaScriptFunction(name: String) : SelfRegisteringJavascriptFunction(MessageFormat.format(JS_NAME_CONVENTION, name)) {
val callable = getCallable(this::class)
override fun function(arguments: Array<Any?>): Any? {
try {
val typedArguments = getTypedArguments(arguments)
val annotations = callable.annotations
for (a in annotations) {
if (a is BrowserFunction) {
if (a.value == Policy.ASYNC) {
invokeAsync(typedArguments);
return null
} else {
return invokeSync(typedArguments)
}
}
}
} catch (e: IllegalArgumentException) {
// this Exception is only for signaling the error; it has already
// been logged before
JavaScriptAPI.showError(browser, "Internal Error (" + callable.name + ")");
}
return null
}
fun getTypedArguments(arguments: Array<Any?>): List<Any?> {
var typedArguments = mutableListOf<Any?>()
val argTypes = callable.valueParameters
if (arguments.size != argTypes.size) {
LOG.error(getName()
+ ": given arguments don't match signature. Given: "
+ arguments.size + ", expected: " + argTypes.size);
throw IllegalArgumentException()
}
for (i in 0 until arguments.size) {
typedArguments.add(TypeRefinery.refine(arguments[i], argTypes[i].type.classifier as KClass<Any>))
}
return typedArguments
}
// ...
fun invokeSync(typedArguments: List<Any?>): Any? {
var returnedValue: Any?
try {
returnedValue = callable.call(this, typedArguments);
} catch (e: Exception) {
logInvocationError(e, typedArguments);
throw IllegalArgumentException(e);
}
// ...
}
}
Did anyone can help me and tell me whats wrong or can give me a hint?
Since call takes a vararg you need to use the spread operator * and toTypedArray() to pass in the List like that:
returnedValue = callable.call(this, *typedArguments.toTypedArray());
The first argument is the instance you are calling the function on and the other two parameters come from the spreaded List, under the condition that List has exactly two elements.