How do I fix a NullPointerException on Kotlin? - kotlin

I am a beginner in programming and I am trying to solve a math problem on Kotlin. The problem is:
"Challenge -> You must read 5 integer values. Then show how many reported values ​​are even, how many reported values ​​are odd, how many reported values ​​are positive, and how many reported values ​​are negative. Assume that the number zero is positive, but it cannot be considered positive or negative.
Input -> You will receive 5 integer values (-5, 0, -3, -4, 12).
Exit -> Display the message as shown in the output example below, being one message per line and not forgetting the end of the line after each one. The output should show (3 evens, 2 odds, 1 positive, 3 negatives)"
This was what I thought could be the solution:
fun main(args: Array<String>) {
val integers= mutableListOf<Int>()
var evens = mutableListOf<Int>()
var odds = mutableListOf<Int>()
var positives = mutableListOf<Int>()
var negatives = mutableListOf<Int>()
for (i in 1..5) { integers.add(readLine()!!.toInt()) }
for (i in integers) {
if (i % 2 == 0) { evens.add(i) }
if (i % 2 != 0) { odds.add(i) }
if (i > 0) { positives.add(i) }
if (i < 0) { negatives.add(i) }
}
println("${evens.size} even(s)")
println("${odds.size} odd(s)")
println("${positives.size} positive(s)")
println("${negatives.size} negative(s)")
}
This is returning the following message:
Exception in thread "main" java.lang.NullPointerException
at FileKt.main (File.kt:9)
at sun.reflect.NativeMethodAccessorImpl.invoke0 (NativeMethodAccessorImpl.java:-2)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
How can I fix it? What did I do wrong? What am I forgetting?

Short answer: You don't put any input.
Long answer:
If you programming in https://play.kotlinlang.org/ you gonna got that error.
Because it dont have read input.
But same example in
with input gonna be ok.

Related

Count isn't counting the amount of string items in an array in Kotlin

I just want to count the words in the array using .count but its giving the following error:
error: type mismatch: inferred type is String but (TypeVariable(T)) -> Boolean was expected
println(sentArr.count(x))
**code**:
fun main() {
var sentence = "Bob hit a ball, the hit BALL flew
far after it was hit."
var sentArr = sentence.split(" ")
var bannedWords = arrayOf("ball")
for(x in sentArr){
println(sentArr.count(x))
}
}
If I am correctly guessing what you're trying to do, this is what you're looking for:
for(x in sentArr){
println(sentArr.count { it == x })
}
This means to count how many of the Strings in the array are the same as x.
If you just want to count the words in the array, you can simply write sentArr.size or sentArr.count(). No need for a loop

Expected output to file 'numbers.txt' did not meet the requirements

Create a program that ask a user to type positive integers. Each positive integer is saved to a file called numbers.txt. When a user types -1, the program reads the file, and add numbers to a list. Finally, the program prints the count and the average of typed numbers from a list. If the typed integer is not positive, the program prints "The number must be positive" message.
So far, my program is as follows:
import java.util.*
import java.io.File
fun main(args: Array<String>) {
val list = mutableListOf<Int>()
var counter = 0
while(true){
val reader = Scanner(System.`in`)
var file = File("numbers.txt")
println("Type a positive integer (-1 to exit):")
var input_num = reader.nextInt()
if (input_num >= 0) {
list.add(input_num)
counter++
}
else if (input_num < -1){
println("The number must be positive")
}
else if (input_num == -1){
break
}
}
println("You typed $counter numbers.")
println("The average is ${list.average()}.")
}
The output is working as expected 1) counter displays the desirable number and 2) the average of the list is also displayed correctly.
Although, my issue is that no numbers were added to the actual .txt file. I am sorry for any mistake made on by behalf this is my first post and I am completely new to Kotlin language. Any feedback is very appreciated.

Write a kotlin program that prints the number that is repeated the most in a consecutive way

I'm kind of stuck, I don't know how to make the second loop to start 1 position above the first loop in Kotlin.
I have an array (named myArray) with 10 elements, I need to Write a Kotlin program that prints the number that has the most consecutive repeated number in the array and also prints the number of times it appears in the sequence.
The program must parse the array from left to right so that if two numbers meet the condition, the one that appears first from left to right will be printed.
Longest: 3
Number: 8
fun main() {
val myArray: IntArray = intArrayOf(1,2,2,4,5,6,7,8,8,8)
for((index , value) in myArray.withIndex()){
var inx = index + 1
var count = 0
var longest = 0
var number = 0
for((inx,element) in myArray.withIndex()) {
if(value == element ){
count+=
}
}
if(longest < count){
longest = count
number = value
}
}
}
I'm against just dropping answers, but it is quite late for me, so I'll leave this answer here and edit it tomorrow with more info on how each part works. I hope that maybe in the meanwhile it will help you to gain some idea to where you might be going wrong.
val results = mutableMapOf<Int, Int>()
(0..myArray.size - 2).forEach { index ->
val current = myArray[index]
if (current == myArray[index + 1]) {
results[current] = (results[current] ?: 1) + 1
}
}
val (max, occurrences) = results.maxByOrNull { it.value } ?: run { println("No multiple occurrences"); return }
println("Most common consecutive number $max, with $occurrences occurrences")
Alternatively if the intArray would be a list, or if we allowed to change it to a list myArray.toList(), you could replace the whole forEach loop with a zipWithNext. But I'm pretty sure that this is a HW question, so I doubt this is the expected way of solving it.
myList.zipWithNext { a, b ->
if (a == b) results[a] = (results[a] ?: 1) + 1
}

How to "Catch" both a non-numeric and Incomplete ArrayList capacity

I created an ArrayList that has a capacity of 5 Ints. I can get the if statement to run if its less than 5 but I can't seem to get the else statement to "Catch" Non-Numerics. For example if I enter 1,2,3,Hello; it will print "Wrong number of sales provided."
fun main(){
val stats = ArrayList<Int>(5)
println("Enter your numbers: ")
try {
while (stats.size < 5) {
stats.add(readLine()!!.toInt())
}
}catch (e: NumberFormatException){
if (stats.size != 5){
println("The wrong number of sales provided.")
}else{
println("All inputs should be numeric.")
}
exitProcess(status = 1)
}
calStats(stats)
}
fun calStats(sales: Collection<Int>){
val min = sales.minOrNull()
val max = sales.maxOrNull()
println("Min: $min\nMax: $max\nRange: ${(max!! - min!!)}\nAverage: ${(BigDecimal(sales.average()).setScale(0, RoundingMode.FLOOR))} ")
}
The problem is how you are handling your exception, in fact since you are checking the size of your array first, if you enter 1,2,3,'Hello' and there are 4 elements in this list it will output the wrong message.
You should nest your try ... catch block inside the while loop.
Actually the if (stats.size != 5) control is reduntant since the while loop will execute until stats has a size of 5, unless the NumberFormatException is thrown.
Try to edit your code like this:
fun main() {
val stats = ArrayList<Int>(5)
println("Enter your numbers: ")
while (stats.size < 5) {
try {
stats.add(readLine()!!.toInt())
} catch (e: NumberFormatException) {
println("All inputs should be numeric.")
exitProcess(status = 1)
}
}
calStats(stats)
}
Your logic loops through, reading lines and adding them until you've collected 5 values. As soon as it fails at parsing one of those lines as an Int, it throws a NumberFormatException and you hit the catch block.
The first thing the catch block does is check how many values you've successfully added to the stats list. If it's not exactly 5, it prints the "wrong number" error instead of the "inputs need to be numeric" one.
But if you think about it, the size is never going to be 5 when you hit the catch block - if you've added 5 items successfully, the while loop ends and there's no way it's going to throw. If you have 4 items and the 5th one fails, it doesn't get added, so you have 4 items when you hit the catch block.
If you need to do it this way, you probably want to keep a counter of how many lines you've read and refer to that. But you'll still throw once you hit the first non-numeric value (even if there's 5 of them to be read in total) and the counter will show how far you've got, not how many there are.
Probably the easiest way is to read in 5 lines to a list, and then transform them to Ints and add those to your collection. That way you can check if you have less than 5 before you start, and handle that case separately.
Something like
// create a list by calling readline() 5 times - produces null at EOF
val lines = List(5) { readLine() }
if (lines.contains(null)) { // handle your "not enough items" here }
// parse all lines as Ints - any that fail will be null
val stats = lines.map { it.toIntOrNull() } // or map(String::toIntOrNull)
if (stats.contains(null)) { // handle bad values here }
Kotlin's style tries to avoid exceptions, which is why you have functions like toIntOrNull alongside toInt - it lets you use nulls as a "failure value" that you can handle in normal code. But you can always throw an exception if you want (e.g. when you get a null line) and handle it in your catch block.

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