Kotlin. Function does not exit recursion after return - kotlin

I need to decompose the number l into prime factors. For this I use recursion. And when l = 1, the function must exit their recursion and return the string in which the prime factors are located, however, the function continues to work and already according to a principle incomprehensible to me. Please explain what is the problem with my code?
fun factors(l: Int): String {
return if (l == 1) {
answer
} else {
for (i in 2..l) {
if (l % i == 0) {
answer += "$i "
factors(l / i)
}
}
return factors(l)
}
}

Let's first mention some issues in your current code:
You're mixing semantics, here. What is the contract of your function? Does it return a value, or does it modify a global variable? Pick one, don't do both.
You should not use a global variable because it's way harder to follow. Instead, construct your values locally from the current information + whatever the recursive call returns to you
You're already using an if expression with the syntax return if (condition) { ... } else { ... }. This means each branch of the if should just end with an expression, you don't need to use return again. That said, in this case the first branch is rather a special case that you want to get out of the way before doing the bulk of the general work. In this kind of situation, I would rather use a statement like if (condition) { return X } at the beginning and then have the rest of the body of the function unnested, instead of using an if expression (but that is a personal preference).
It is strange to compute the list of factors as a string. You likely want to avoid duplicates and maybe sort them, so a List<Int> or a Set<Int> would likely be more appropriate. You can always format after the fact using things like joinToString(" ")
I'm not sure I get the math correctly, but it seems you really will be getting all factors here, not just the prime factors.
Now, the actual cause of the behaviour you're seeing is that you're calling your function recursively with the same number at the end: return factors(l). This means that calling factors(l) with any l > 1 will end up calling itself with the same value over and over. Recursive calls need to change some arguments to the function if you don't want it to be infinite.

fun factors(value: Int, list: MutableList<Int> = mutableListOf()): MutableList<Int> {
if (value > 1) {
for (i in 2..value) {
if (value % i == 0) {
list.add(i)
list.addAll(factors(value / i))
break
}
}
}
return list
}
(2..25).forEach {
val factors = factors(it)
val result = factors.reduce { acc, i -> acc * i }.toString() + " = " + factors.joinToString(" × ")
println(result)
}
Edit: this version is based on #Joffrey's comment below. Plus I decided to wrap the recursive function, now called fn, into a function in order to have a clean parameter list for factors():
fun factors(value: Int): List<Int> {
fun fn(value: Int, list: MutableList<Int>) {
if (value > 1) {
for (i in 2..value) {
if (value % i == 0) {
list.add(i)
fn(value / i, list)
break
}
}
}
}
val list = mutableListOf<Int>()
fn(value, list)
return list
}
Output:
2 = 2
3 = 3
4 = 2 × 2
5 = 5
6 = 2 × 3
7 = 7
8 = 2 × 2 × 2
9 = 3 × 3
10 = 2 × 5
11 = 11
12 = 2 × 2 × 3
13 = 13
14 = 2 × 7
15 = 3 × 5
16 = 2 × 2 × 2 × 2
17 = 17
18 = 2 × 3 × 3
19 = 19
20 = 2 × 2 × 5
21 = 3 × 7
22 = 2 × 11
23 = 23
24 = 2 × 2 × 2 × 3
25 = 5 × 5

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").

Why does this function return the correct height of a binary tree?

I am trying to unravel this recursive function, but I haven't been able to find out why it returns the value 3:
Here's the tree:
1 (2)
/ \
(1) 3 9 (-1)
/ \
(-1) 4 5 (0)
/
6 (-1)
Here's the function to find the height:
fun height(node: BinaryNode<T>? = this): Int {
return node?.let {
1 + max(height(node.leftChild), height(node.rightChild))
} ?: -1
}
When I traced the function back to the place when the very first node 1 was called, you can see that the value is 2. But I print the value and it's always 3. Here's the call:
println(tree.height())
where does this extra 1 sneek in?
For a leaf node, 4, 6 or 9 in your example, it returns
node?.let {
1 + max(height(null), height(null))
} ?: -1
When node is null, the block of let won't be executed, thus the value returned is -1.
So
node?.let {
1 + max(-1, -1)
} ?: -1
is 0.
Please trace your code to understand it.

Find all numbers adding up to given number and range to use

This is not homework, but a real world application I'm getting stumped on.
The best way I can explain my problem is as follows:
Imagine you have 3 pig pens A, B, and C and 10 pigs to be kept.
The pens have restrictions in that each pen must contain at least 1 pig and A.pigs <= B.pigs <= C.pigs. List all the possible pen configurations.
The REAL application can have anywhere between 1 and 7 pens, and anywhere between numPens and numPens*30 pigs and no pen may contain more than 30 pigs. So essentially this translates into "what numbers between 1 and 30 (repeats allowed) add up to X using Y numbers"
This could be solved simply with nested loops, but thats a terrible inefficient solution especially knowing the scope of the real application:
var cnt = 0
val target = 10
for (a in 1..30) {
for (b in a..30) {
val c = target - a - b
cnt++
if (a <= b && b <= c && a + b + c == target) {
println("$a $b $c")
}
}
}
println(cnt)
output:
1 1 8
1 2 7
1 3 6
1 4 5
2 2 6
2 3 5
2 4 4
3 3 4
465
I'm sure there is a recursive solution to this problem. But I'm having trouble even finding the starting point for this one.
It seems easy to start with an array of [1, 1, 8] where each index represents a pen. Just put all the pigs in 1 pen and move them around 1 at a time while following the constraints.
Subtract from C, add to B as much as you can while keeping constraints gets us [1, 2, 7], [1, 3, 6], [1, 4, 5] but at that point I'm stuck code wise.
What I have currently:
fun main(vararg args: String) {
val list = arrayOf(1, 1, 8)
list.forEach { print("$it\t") }
println()
rec(list, list.lastIndex - 1)
}
fun rec(list: Array<Int>, index: Int) {
if (index == list.lastIndex || index < 0) {
return
}
while (list[index] + 1 <= list[index + 1] - 1) {
list[index]++
list[index + 1]--
list.forEach { print("$it\t") }
println()
}
}
Obviously I need to call rec somewhere within itself and probably need some conditionals to call rec correctly (possibly adding more parameters to it). The question is where and how? Normally not bad with recursion, but this one is stumping me.
Solution:
I got so hung up on the idea I needed recursion. This loop seems to work pretty well.
for (a in 1..30) {
// we know a and c must be at least b, so cap range
var b = a
while(b < min(target - a - b, 30)){
val c = target - a - b
cnt++
if (a <= b && b <= c && a + b + c == target) {
println("$a $b $c")
}
b++
}
}
Some inefficiencies to note:
Once you know a and b, the only value for c that could make a solution would be 10-a-b, so you don't need the innermost loop at all.
Since a<=b, the second loop should start at a, not 1.
You can also limit the top of the second loop's range based on the value of a

Calculate sum of 2D Arrays

I want to write a program to calculate the sum of 2 matrices(2D Arrays) based on the user input.
Two matrices must have an equal number of rows and columns to be added. The sum of two matrices A and B will be a matrix that has the same number of rows and columns as do A and B.
The first line of standard input is a number of rows n and number of columns m of matrix A. Next n lines are A matrix’s elements. The next line after the empty line is a number of rows n and a number of columns m of matrix B. Next n lines are B matrix’s elements.
I want to output the result of a sum of A and B matrices or ERROR message if it’s impossible. The input contains only integers.
Example
Input:
4 5
1 2 3 4 5
3 2 3 2 1
8 0 9 9 1
1 3 4 5 6
4 5
1 1 4 4 5
4 4 5 7 8
1 2 3 9 8
1 0 0 0 1
Output:
2 3 7 8 10
7 6 8 9 9
9 2 12 18 9
2 3 4 5 7
My Code:
package processor
import java.util.*
val scanner = Scanner(System.`in`)
fun main() {
MatrixProcessor().addition()
}
class MatrixProcessor {
private fun createMatrix(): Array<Array<Int>> {
val rows = scanner.nextInt()
val columns = scanner.nextInt()
return Array(rows) {Array(columns) { scanner.nextInt()} }
}
fun addition() {
val firstMatrix = createMatrix()
val secondMatrix = createMatrix()
val sum = Array(4) { IntArray(5) }
for (i in 0 until 4) {
for (j in 0 until 5) {
sum[i][j] = firstMatrix[i][j] + secondMatrix[i][j]
}
}
printSolution(sum)
}
private fun printSolution(matrix: Array<IntArray>) {
for (array in matrix) {
for (value in array) {
print("$value ")
}
println()
}
}
}
My main problem lies with sum in the addition function since I do not know how to fill it with dynamic row and column size and currently inserted a standard value of 4 and 5.
fun addition() {
val firstMatrix = createMatrix()
val secondMatrix = createMatrix()
val sum = Array(4) { IntArray(5) }
for (i in 0 until 4) {
for (j in 0 until 5) {
sum[i][j] = firstMatrix[i][j] + secondMatrix[i][j]
}
}
printSolution(sum)
}
It looks like you're storing your matrices in row-major order: you have individual arrays representing rows, and then an outer array holding all the rows.  So the size of the outer array gives you the number of rows, and the size of any of the inner arrays (such as the first) gives you the number of columns.
So you can create the sum like this:
val sum = Array(firstMatrix.size) { IntArray(firstMatrix[0].size) }
for (i in sum.indices)
for (j in sum[0].indices)
sum[i][j] = firstMatrix[i][j] + secondMatrix[i][j]
(I've used .indices instead of an explicit range, for simplicity.)
An alternative approach is to specify the values when creating the arrays, instead of filling them in afterwards.  (It doesn't make too much difference here, as numeric arrays get a default value of 0; but it can simplify things a lot when creating arrays of a non-nullable reference type.)
val sum = Array(firstMatrix.size) { row ->
IntArray(firstMatrix[0].size) { column ->
firstMatrix[row][column] + secondMatrix[row][column]
}
}
The Array() and IntArray() constructors pass the index into the lambda; while the first version ignores it, here we call it row or columns so we can use it to index the arrays we're summing.
The above assumes that all the inner arrays have the same size.  That's probably reasonable in this case, where you've created the arrays yourself — but in general you'd probably want to verify that.
Certainly, it would be a good idea to verify that the two matrices you're adding are the same size, and throw an IllegalArgumentException with a helpful message if not.  Otherwise, you'd either get an ArrayIndexOutOfBoundsException (if the first were larger), or values would get silently truncated (if the second were larger) — both of which would be much harder to track down.
(The underlying issue here is that, like most languages, Kotlin doesn't have true two-dimensional arrays.  What it does have is arrays of arrays, which are more flexible — and therefore more dangerous.  If you were doing this properly, you'd probably wrap the array-of-arrays into your own Matrix class, which would always ensure that the data was properly rectangular, provide access to the row and column counts, and make all the necessary checks.)
From what i've understood your problem is the fact that you must set a fixed size for Array. I suggest you to use ArrayList instead to solve the problem.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-array-list/
With this solution you don't need to set a size for sum anymore.
Once you'll use ArrayLists you'll never get back to Arrays.