A very basic exercise help-----Kotlin - kotlin

Im trying to do this exercise
https://www.hackerrank.com/challenges/compare-the-triplets/problem?h_r=next-challenge&h_v=zen
I already wrote the code but the result is not right and for my eyes its all good
Could somebody pls tell me whats wrong??
thx
import java.util.Scanner
fun main(){
var loop = 0
var score = Array<Int>(2){0}
val reader = Scanner(System.`in`)
var alice:String = readLine().toString()
var bob:String = readLine().toString()
val numerosa: List<String> = alice.split(" ")
val numerosb:List<String> = bob.split(" ")
for(a in 3..3) {
when (numerosa[loop].toInt()) {
in numerosb[loop].toInt() + 1..100 -> score[0] += 1
in numerosb[loop].toInt() - 1..0 -> score[1] += 1
}
loop += 1
}
println("${score[0]} ${score[1]}")
}

You could do it something like this, you have multiple variables which were not required so I cleaned up the code.
val score = Array(2) { 0 }
val aliceNumbers = readLine()!!.split(" ").map(String::toInt)
val bobNumbers = readLine()!!.split(" ").map(String::toInt)
require(aliceNumbers.size == 3 && bobNumbers.size == 3) { "There must be 3 numbers for each" }
require(!aliceNumbers.any { it !in 1..100 } || !bobNumbers.any { it !in 1..100 }) { "Numbers must be in range 1 to 100" }
for (a in 0..2) {
if(aliceNumbers[a] > bobNumbers[a]) score[0] += 1
if(aliceNumbers[a] < bobNumbers[a]) score[1] += 1
}
println("${score[0]} ${score[1]}")

Related

Read a sequence of numbers of undefined size & print the largest number & position of its first occurrence

I need to read a sequence of numbers of undefined size & prints the largest number & the position of its first occurrence
Can anyone help with this code:
import java.util.Scanner
fun main() {
val scan = Scanner(System.`in`)
val num = scan.nextInt()
var max = Int.MIN_VALUE
var pos = 0
var i = 1
do {
if (max < num) {
max = num
pos = i
}
i++
} while (scan.hasNext())
print("$max $pos")
}
You just need to read a new number in each iteration:
import java.util.Scanner
fun main() {
val scan = Scanner(System.`in`)
var max = Int.MIN_VALUE
var pos = 0
var i = 1
while (scan.hasNext()) {
// Read a new number here
val num = scan.nextInt()
if (max < num) {
max = num
pos = i
}
i++
}
print("$max $pos")
}
My solution to this task
This is a simple task, it can be solved in a simple way without using a “java.util.Scanner”. You just need to read a new number in each iteration.
fun main() {
var pos = 0
var max = 0
var count = 1
while (true) {
val input = readlnOrNull()
if (input == null) break
val num = input.toInt()
if (pos == 0 || num > max) {
max = num
pos = count
}
count++
}
print("$max $pos")
}

How to get columns of two dimesional array using functional style in kotlin

For example I have such a simple task: count all raws and columns which have all zeros in 2D array.
So for
0 0 0
0 0 0
1 0 1
answer is 2 raws and 1 column.
I can make it just like that for raws: var cntRaws = a.count { it.all { el -> el == 0 } }, but how to solve it for columns in same way?
val x = Array<IntArray>(3) { IntArray(3) { 0 } }
x[2][0] = 1
x[2][2] = 1
val raws = x.count { it.sum() == 0 }
val columns = (x.indices)
.map { columnIndex -> x.map { it[columnIndex] } }
.count { it.sum() == 0 }
println("total raws:$raws")
println("total col:$columns")
I couldn't think of any idomatic / functional style to do this, but I came up with an idea just create a lazily evaluated swapping function that swaps the columns with rows when it wants to pull without creating a new list.
fun <T> List<List<T>>.swapped() = sequence {
var index = 0
while (index < size) {
yield(map { it[index] })
index++
}
}
fun main() {
val list = listOf(
listOf(0, 0, 0),
listOf(0, 0, 0),
listOf(1, 0, 1)
)
val cntRows = list.count { it.all { el -> el == 0 } }
val cntCols = list.swapped().count { it.all { el -> el == 0 } }
println("cntRows: $cntRows")
println("cntCols: $cntCols")
}
I tried my best to optimize it and do it in same O(n*m) steps as done with the regular row counting, since Sequences are lazily evaluated.
This is a functional way of doing it that works if all rows are the same size:
fun <T>List<List<T>>.rowToColumn() = (0 until first().size).map{row -> (0 until size).map {col-> this[col][row] }}

Kotlin - The caracter literal does not conform expect type Int

I'm struggling with types with my program, I've been asked to do it in JS first and it worked fine but now I can't achieve the result.
Do you think I should make another 'algorithm' ? In advance, thank you for your time.
fun main(){
// the idea is to put numbers in a box
// that cant be larger than 10
val data = "12493419133"
var result = data[0]
var currentBox = Character.getNumericValue(data[0])
var i = 1
while(i < data.length){
val currentArticle = Character.getNumericValue(data[i])
currentBox += currentArticle
println(currentBox)
if(currentBox <= 10){
result += Character.getNumericValue(currentArticle)
}else{
result += '/'
//var resultChar = result.toChar()
// result += '/'
currentBox = Character.getNumericValue(currentArticle)
result += currentArticle
}
i++
}
print(result) //should print 124/9/341/91/33
}
The result is actually of a Char type, and the overload operator function + only accepts Int to increment ASCII value to get new Char.
public operator fun plus(other: Int): Char
In idomatic Kotlin way, you can solve your problem:
fun main() {
val data = "12493419133"
var counter = 0
val result = data.asSequence()
.map(Character::getNumericValue)
.map { c ->
counter += c
if (counter <= 10) c.toString() else "/$c".also{ counter = c }
}
.joinToString("") // terminal operation, will trigger the map functions
println(result)
}
Edit: If the data is too large, you may want to use StringBuilder because it doesn't create string every single time the character is iterated, and instead of using a counter of yourself you can use list.fold()
fun main() {
val data = "12493419133"
val sb = StringBuilder()
data.fold(0) { acc, c ->
val num = Character.getNumericValue(c)
val count = num + acc
val ret = if (count > 10) num.also { sb.append('/') } else count
ret.also { sb.append(c) } // `ret` returned to ^fold, next time will be passed as acc
}
println(sb.toString())
}
If you want a result in List<Char> type:
val data = "12493419133"
val result = mutableListOf<Char>()
var sum = 0
data.asSequence().forEach {
val v = Character.getNumericValue(it)
sum += v
if (sum > 10) {
result.add('/')
sum = v
}
result.add(it)
}
println(result.joinToString(""))

Kotlin: Run length encoding

The program works, however, I still get a logical error: the final letter doesn't run through. For example, when I enter aaaabbbbccccdddd the output I get is a4b4c4 but there is no d4.
fun main () {
val strUser = readLine()!!.toLowerCase()
val iLength = strUser!!.length
var iMatch : Int = 0
var chrMatch : Char = strUser[0]
for (i in 0..iLength) {
if (strUser[i] == chrMatch) {
iMatch += 1
}else {
print("$chrMatch$iMatch")
chrMatch = strUser[i]
iMatch = 1
}
}
}
There are many solutions, but the best is RegExp
fun encode(input: String): String =
input.replace(Regex("(.)\\1*")) {
String.format("%d%s", it.value.length, it.groupValues[1])
}
demo
Test result
println(encode("aaaabbbbccccdddd")) // 4a4b4c4d
strUser contains chars by indexes from 0 to iLength - 1 so you have to write for (i in 0 until iLength) instead of for (i in 0..iLength)
But Tenfour04 is completely right, you can just iterate strUser without indexes:
fun main() {
val strUser = readLine()!!.toLowerCase()
var iMatch: Int = 0
var chrMatch: Char = strUser[0]
for (char in strUser) {
if (char == chrMatch) {
iMatch += 1
} else {
print("$chrMatch$iMatch")
chrMatch = char
iMatch = 1
}
}
}
fun main () {
val strUser = readLine()!!.toLowerCase()
var iMatch : Int = 0
var chrMatch : Char = strUser[0]
for (char in strUser+1) {
if (char == chrMatch) {
iMatch += 1
}else {
print("$chrMatch$iMatch")
chrMatch = char
iMatch = 1
}
}
}
fun runLengthEncoding(inputString: String): String {
val n=inputString.length
var i : Int =0
var result : String =""
while(i<n){
var count =1
while(i<n-1 && inputString[i] == inputString[i+1]){
count ++
i++
}
result=result.toString()+count.toString()+inputString[i].toString()
i++
}
return result
}

Possibility to reduce nested loops

I want to bypass deep nesting of several for-loops when creating a list off all possible Transformations.
Right now, this block of code is used:
val allTransformations = ArrayList<Transformation>().apply {
for (moveZ in 0..4)
for (moveY in 0..4)
for (moveX in 0..4)
for (rotateZ in 0..3)
for (rotateY in 0..3)
for (rotateX in 0..3)
add(Transformation(rotateX, rotateY, rotateZ, moveX, moveY, moveZ))
}
Although this is quite straight forward, I was wondering if Kotlin provides other tools to write this in a single line.
I want to retrieve the same list, with less code and see if this results in less clutter.
This solution can be invoked with:
loopOverRanges(0..4, 0..4, 0..4, 0..3, 0..3, 0..3) { result ->
// result[0], result[1], result[2], result[3], result[4], result[5]
}
This is defined as such:
fun loopOverRanges(
vararg ranges: IntRange,
function: (IntArray) -> Unit
) {
val result = IntArray(ranges.size) { index -> ranges[index].first }
val productOfRangeLengths = ranges
.map { it.toList().size }
.product()
for (i in 0 until productOfRangeLengths) {
function(result)
result[0] += ranges[0].step
for (rangeIndex in 0 until ranges.size - 1) {
if (result[rangeIndex] == ranges[rangeIndex].last) {
result[rangeIndex] = ranges[rangeIndex].first
result[rangeIndex + 1] += ranges[rangeIndex].step
}
}
}
}
It's questionable to say the least if this improves readability. It removes the need for nesting, which can be useful for a large amount of ranges. It does not give the instant recognition of my initial nested loop; it also hides named parameters and may throw an IndexOutOfBounds when result[TOO_HIGH_INT] is retrieved.
It was a fun little investigation, but I lean towards not using it.
Here is how to do it with one loop. Just like incrementing a counter with 6 digits. When the first digit overflow, carry to the second digit and reset the first digit. etc.
fun loopOverRanges(a:IntRange,b:IntRange,c:IntRange,d:IntRange,e:IntRange,f:IntRange) : ArrayList<Transformation>
{
val x = a.count() * b.count() * c.count() * d.count() * e.count() * f.count()
val list : ArrayList<Transformation> = ArrayList()
var rx = f.first
var ry = e.first
var rz = d.first
var mx = c.first
var my = b.first
var mz = a.first
for(i in 0 until x)
{
list.add(Transformation(rx,ry,rz,mx,my,mz))
when{
rx < f.last -> rx += 1
ry < e.last -> {
rx = f.first
ry += 1
}
rz < d.last -> {
rx = f.first
ry = e.first
rz += 1
}
mx < c.last -> {
rx = f.first
ry = e.first
rz = d.first
mx += 1
}
my < b.last -> {
rx = f.first
ry = e.first
rz = d.first
mx = c.first
my += 1
}
mz < a.last -> {
rx = f.first
ry = e.first
rz = d.first
mx = c.first
my = b.first
mz += 1
}
}
}
}
return list
}
It can be simplified as
fun loopOverRanges(a:IntRange,b:IntRange,c:IntRange,d:IntRange,e:IntRange,f:IntRange) : ArrayList<Transformation>
{
data class Digit(var value :Int, val range:IntRange)
val list : ArrayList<Transformation> = ArrayList()
val digits = arrayOf(Digit(a.first,a),Digit(b.first,b),Digit(c.first,c),Digit(d.first,d),Digit(e.first,e),Digit(f.first,f))
val x = digits.fold(1){acc,digit -> acc * digit.range.count() }
for(i in 0 until x)
{
list.add(Transformation(digits[5].value,digits[4].value,digits[3].value,digits[2].value,digits[1].value,digits[0].value))
val j = digits.indexOfFirst { it.value < it.range.last }
if(j >= 0)
{
for(k in 0 until j )
{
digits[k].value = digits[k].range.first
}
digits[j].value += 1
}
}
return list
}