KOTLIN - For loop argument is not support function - Looking for alternatives - kotlin

The code below is for calculating exam results. 5 subject names and 5 points received from those subjects are recorded by the user in empty arrays created.
I have solved everything here. But I want to add "th" "st" "rd" "nd" after "cycle". Which is written "Please type lesson" and "Please type point"
For Example:
"Please type 1st point"
But with my code I can:
"Please type 1 point"
I tried to execute this process with the "When" condition, but I cannot because the loop argument "cycle" do not support the last() function
For example:
when (cycle.last()) {
1 -> "st"
2 -> "nd"
}
It will give me a result if worked 11st, 531st, 22nd, 232nd, etc. That's I want
fun main() {
var subject = Array<String>(5){""}
var point = Array<Int>(5){0}
for (cycle in 0 until subject.count()) {
println("Please type ${cycle+1} lesson")
var typeLesson = readLine()!!.toString()
subject[cycle] = typeLesson
println("Please type ${cycle+1} point")
var typePoint = readLine()!!.toInt()
point[cycle] = typePoint
}
var sum = 0
for (cycle in 0 until point.count()) {
println("${subject[cycle]} : ${point[cycle]}")
sum = sum + point[cycle]/point.count()
}
println("Average point: $sum")
}

You can divide the number by 10 and get the remainder using %. That is the last digit.
fun Int.withOrdinalSuffix(): String =
when (this % 10) {
1 -> "${this}st"
2 -> "${this}nd"
3 -> "${this}rd"
else -> "${this}th"
}
Usage:
println("Please type ${(cycle+1).withOrdinalSuffix()} lesson")
Note that in English, 11, 12, 13 have the suffix "th", so you might want to do:
fun Int.withOrdinalSuffix(): String =
if ((this % 100) in (11..13)) { // check last *two* digits first
"${this}th"
} else {
when (this % 10) {
1 -> "${this}st"
2 -> "${this}nd"
3 -> "${this}rd"
else -> "${this}th"
}
}
instead.

Related

print n times number from 1. Need print (1 2 2 3 3 3 4)

I can't figure out how to solve the following problem: there is a number n. Output the numbers to the console in order separated by a space, but so that the next digit in the iteration is output as many times as it is a digit, and at the same time so that there are no more than n digits in the output. Сan anyone suggest the correct algorithm?
example: have n = 7, need print (1 2 2 3 3 3 4) in kotlin
what i try:
var n = 7
var count = 1
var i = 1
for (count in 1..n) {
for (i in 1..count) {
print(count)
}
}
}
var n = 11
var count = 1
var i = 1
var size = 0
// loop# for naming a loop in kotlin and inside another loop we can break or continue from outer loop
loop# for (count in 1..n) {
for (i in 1..count) {
print(count)
size++
if (size == n){
break#loop
}
}
}
You can use "#" for naming loops and if you want to break from that loop, you can use this syntax in kotlin. It worked for me.
For kotlin labeled break you can look at this reference: link
var count = 1
var n = 7
for(count in 1..n) {
print(count.toString().repeat(count))
}
count.toString() converts an integer to a string, .repeat() function repeats count times the string.
In case you need to add a space between each number, you can add the following:
print(" ")
Using generateSequence and Collections functions:
val n = 7
println(generateSequence(1) {it + 1}
.flatMap{e -> List(e){e}}
.take(n)
.joinToString(" "))
Your example is correct, You have to put a space between the printing
you can follow the code from this link
Kotlin lang code snippet
or the following code snippet
fun main() {
var n = 7
var count = 1
var i = 1
for (count in 1..n) {
for (i in 1..count) {
print(count)
print(' ')
}
}
}
For completeness, here's another approach where you write your own sequence function which produces individual values on demand (instead of creating intermediate lists)
sequence {
var digit = 1
while (true) {
for (i in 1..digit) yield(digit)
digit++
}
}.take(7)
.joinToString(" ")
.run(::print)
Not a big deal in this situation, but good to know!

Conditional loop repetitively printing wrong output

I wasn't sure how to phrase the title sorry.
Basically I'm writing a code that draws up a cinema and seating.
The program asks input for how many rows in the cinema and how many seats and returns this:
Cinema:
1 2 3 4 5 6 7 8 9
1 S S S S S S S S S
2 S S S S S S S S S
3 S S S S S S S S S
4 S S S S S S S S S
5 S S S S S S S S S
6 S S S S S S S S S
7 S S S S S S S S S
8 S S S S S S S S S
9 S S S S S S S S S
The program then asks the user to select a row and seat and should out put the same seating as above but with a 'B' marking their seat:
1 2 3 4 5 6 7 8 9
1 S S S S S S S S S
2 S S S S S S S S S
3 S S S S S S S S S
4 S S S B S S S S S
5 S S S S S S S S S
6 S S S S S S S S S
7 S S S S S S S S S
8 S S S S S S S S S
9 S S S S S S S S S
This is working fine unless the user selects row 1 and seat 1 then this is the returned seating:
1 2 3 4 5 6 7 8 9
1 B S S S S S S S S
2 B S S S S S S S S
3 B S S S S S S S S
4 B S S S S S S S S
5 B S S S S S S S S
6 B S S S S S S S S
7 B S S S S S S S S
8 B S S S S S S S S
9 B S S S S S S S S
I'm positive this is to do with my for and if conditionals at the end of the code but am confused as to why it will repetitively print the 'B'.
Also I understand that i've attempted this in a bad way but just want to understand why I'm having this issue.
here is the whole code so you can test on your IDEA:
fun main(args: Array<String>) {
println("Enter the number of rows:")
val rows = readln().toInt()
println("Enter the number of seats in each row:")
val seats = readln().toInt()
val total = rows * seats
var s = 'S'
var cinemaLayout = mutableListOf<MutableList<Char>>()
val cinemaSeats = mutableListOf<Char>()
for (x in 1..seats) {
cinemaSeats.add(s)
}
for (x in 1..rows) {
cinemaLayout.add(cinemaSeats.toMutableList())
}
println("Cinema:")
print(" ")
for (x in 1..seats) {
print(x)
print(" ")
}
println()
var cleanLayout1 = " ${cinemaLayout[0].joinToString().replace("]", "\n").replace("[", "").replace(",", "")}"
for (i in 1..rows) {
println("$i$cleanLayout1")
}
println("Enter a row number:")
val selectedRow = readln().toInt()
println("Enter a seat number in that row:")
val selectedSeat = readln().toInt()
if (total < 60) {
println("Ticket price: $10")
} else if (total > 60 && selectedRow % 2 === 0 && selectedRow <= rows / 2) {
println("Ticket price: $10")
} else {
println("Ticket price: $8")
}
var indexRow = selectedRow - 1
var indexSeat = selectedSeat - 1
cinemaLayout[indexRow][indexSeat] = 'B'
println("Cinema:")
print(" ")
for (x in 1..seats) {
print(x)
print(" ")
}
println()
for (i in 0 until rows) {
if (i === indexRow) {
println(
"${i + 1} ${
cinemaLayout[indexRow].joinToString().replace("]", "\n").replace("[", "").replace(",", "")
}"
)
} else {
println(
"${i + 1} ${
cinemaLayout[0].joinToString().replace("]", "\n").replace("[", "").replace(",", "")
}"
)
}
}
}
It's because you're always printing the first row, when it's not indexRow
for (i in 0 until rows) {
if (i === indexRow) {
println("...cinemaLayout[indexRow]...")
} else {
println("...cinemaLayout[0]...")
}
}
So when i is your target row, you print that row - otherwise you print row 0 instead of the row number that i currently represents. This means that when indexRow is the first row, you're just printing row 0 every single time, and that's why you see it repeated. When it's not the first row, you're still printing row 0 for everything but that row - it's just more obvious when row 0 has a change in it.
You should be printing the current row instead of the first one:
} else {
// i not 0
println("...cinemaLayout[i]...")
}
but really, why do you need to care about what indexRow is at this point? Your code is the same for both cases here, and you've added the 'B' to your data - you can just print everything as it is
for (i in 0 until rows) {
println("${i + 1} ${ cinemaLayout[i].joinToString().replace("]", "\n").replace("[", "").replace(",", "") }")
}
or better
cinemaLayout.forEachIndexed { index, row ->
val seats = row.joinToString()
.replace("]", "\n")
.replace("[", "")
.replace(",", "")
println("${index + 1} $seats")
}
(and even better ways to things like replacing with the standard library - just showing you how you can do things like looping more cleanly!)
The main issue here comes from bad organization of the code. You should extract functions, and separate business logic from printing logic.
Then you might be able to notice more easily things like the last line which prints cinemaLayout[0] no matter what i we are inspecting.
Also, joinToString takes arguments, you don't have to replace things a posteriori: joinToString(separator = "", prefix = "", postfix = "\n").

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
}

Need help in creating ' Guesing Game ' in Kotlin. Unable to check for previous input number and match it with current input number

I hope you all hear about ' Guessing Game '. The user has to guess a number and then the match goes on with generated Random number.
Now, I have written code for this, but there is a glitch and that is I am unable to understand how to write the condition for -> count variable not getting increased by 1 if just previous input number is same as the current input number by the user.
I am putting my code here:
import java.util.*
import kotlin.random.Random.Default.nextInt
fun main() {
val randomNumber = (1..100).random()
println(randomNumber)
var count: Int = 0
while (true){
val reader = Scanner(System.`in`)
var inputNumber: Int = reader.nextInt()
println("input number: $inputNumber")
if (randomNumber == inputNumber) {
println("You guessed it correct")
count += 1
print("You took $count guesses")
break
} else if (randomNumber > inputNumber) {
println("You guessed it too small")
} else {
println("You guessed it too large")
}
count += 1
print("Guess count: $count")
}
Desired output:
input number: 12
You guessed it too small
Guess count: 1
input number: 25
You guessed it too large
Guess count: 2
input number: 25
You guessed it too large
Guess count: 2
input number: 20
You guessed it right
Guess count: 3
My output:
input number: 12
You guessed it too small
Guess count: 1
input number: 25
You guessed it too large
Guess count: 2
input number: 25
You guessed it too large
Guess count: 3
input number: 20
You guessed it right
Guess count: 4
You can add a variable for tracking the previous input. It should have an initial value of null so it's not possible to accidentally have it tell you your first guess is a repeated one. Before adding to the count, check for the repeated value and continue the loop if it's a repeat. I'd also put the count += 1 before you check whether the guess is correct so it doesn't have to appear in two places in your code. I also moved the creation of the Scanner before the loop so you aren't redundantly recreating it each time it's used.
fun main() {
val randomNumber = (1..100).random()
println(randomNumber)
var count: Int = 0
var previousInput: Int? = null
val reader = Scanner(System.`in`)
while (true) {
val inputNumber: Int = reader.nextInt()
if (inputNumber == previousInput) {
println("That is the same as your previous guess.")
continue
}
count += 1
previousInput = inputNumber
if (randomNumber == inputNumber) {
println("You guessed it correct")
print("You took $count guesses")
break
} else if (randomNumber > inputNumber) {
println("You guessed it too small")
} else {
println("You guessed it too large")
}
println("You've taken $count guess(es)")
}
}

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