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
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")
}
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] }}
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(""))
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
}
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
}