package test
fun main() {
val x= readLine()!!.toInt()
for (i in 1..x) {
repeat(x) { print("#") }
println()
}
}
This is my edited code after your suggestions, stiill, the output remains the same despite my input. It says the source code finished with exit code 0
You answer is already here in the comment of Nikolai Shevchenko, you don't need that TestStringGen object wrapped around the main class, you can't even actually run it at all with it there.
I'm just adding this here as an addition, you don't need the second loop. Since the digit itself represents the number of # you need, you could just take advantage of repeat:
val myNumber = readLine()!!.toInt()
for (digit in 1..myNumber) {
repeat(digit) { print("#") }
println()
}
Also, no need to start the range of the loop from 1 because that will always be an empty line. Unless you need the spacing for whatever reason.
Related
So the question is giving a BIG string, break it up, find the palindromes and then find the shortest length within those sets of palindromes. Here's the code
Main Function
fun main(){
val bigArray = "Simple, given a string of words, return the length of acdca the " +
"shortest valav words String will never be empty and you do not need dad to account for different data types."
println(leastP(bigArray))
}
The Custom Function
fun leastP(s: String): Int {
val sSplit = listOf(s.split(""))
val newArray = listOf<String>()
for (i in sSplit){
for (j in i.indices){
if (isPalindrome3(i[j])) newArray.plus(j)
}
}
return newArray.minOf { it.length }
}
private fun isPalindrome3(s: String): Boolean {
var i = 0
var j = s.length -1
while (i < j){
if (s[i++].lowercaseChar() != s[j--].lowercaseChar()) return false
}
return true
}
}
I get this error
Not sure whats going on or where I messed up. Any help is appreciated.
In addition to the array problem identified in Tenfour04's answer, the code has an additional problem:
split("") splits the string into individual characters, not just individual words.
If you debug it, you'll find that isPalindrome3() is being called first on an empty string, then on "S", then on "i", and so on.
That's because the empty string "" matches at every point in the input.
The easiest fix is to call split(" "), which will split it at space characters.
However, that might not do exactly what you want, for several reasons: it will include empty strings if the input has runs of multiple spaces; it won't split at other white space characters such as tabs, newlines, non-breaking spaces, en spaces, etc.; and it will include punctuation such as commas and full stops. Splitting to give only words is harder, but you might try something like split(Regex("\\W") to include only letters, digits, and/or underscores. (You'll probably want something more sophisticated to include hyphens and apostrophes, and ensure that accented letters etc. are included.)
There's a further issue that may or may not be a problem: you don't specify a minimum length for your palindromes, and so words like a match. (As do empty strings, if the split produces any.) If you don't want the result to be 0 or 1, then you'll also have to exclude those.
Also, the code is currently case-sensitive: it would not count "Abba" as a palindrome, because the first A is in upper case but the last a isn't. If you wanted to check case-insensitively, you'd have to handle that.
As mentioned in a comment, this is the sort of thing that should be easy to test and debug. Short, self-contained functions with no external dependencies are pretty easy to write unit tests for. For example:
#Test fun testIsPalindrome3() {
// These should all count as palindromes:
for (s in listOf("abcba", "abba", "a", "", "DDDDDD"))
assertTrue(isPalindrome3(s))
// But these shouldn't:
for (s in listOf("abcbb", "Abba", "a,", "abcdba"))
assertFalse(isPalindrome3(s))
}
A test like that should give you a lot of confidence that the code actually works. (Especially because I've tried to include corner cases that would spot all the ways it could fail.) And it's worth keeping unit tests around once written, as they can verify that the code doesn't get broken by future changes.
And if the test shows that the code doesn't work, then you have to debug it! There are many approaches, but I've found printing out intermediate values (whether using a logging framework or simply println() calls) to be the simplest and most flexible.
And for reference, all this can be rewritten much more simply:
fun String.leastP() = split(Regex("\\W"))
.filter{ it.length >= 2 && it.isPalindrome() }
.minOfOrNull{ it.length }
private fun String.isPalindrome() = this == reversed()
Here both functions are extension functions on String, which makes them a bit simpler to write and to call. I've added a restriction to 2+ characters. And if the input is empty, minOfOrNull() returns null instead of throwing a NoSuchElementException.
That version of isPalindrome() isn't quite as efficient as yours, because it creates a new temporary String each time it's called. In most programs, the greater simplicity will win out, but it's worth bearing in mind. Here's one that's longer but as efficient as in the question:
private fun String.isPalindrome()
= (0 until length / 2).all{ i -> this[i] == this[length - i - 1]}
Your newArray is a read-only list. When you call plus on it, the function does not modify the original list (after all, it is read-only). The List.plus() function returns a new list, which you are promptly discarding by not assigning it to any variable or property.
Then it crashes because it is unsafe to call minOf on an empty list.
Two different ways to fix this:
Make the newArray variable a var and replace newArray.plus(j) with newArray += j. The += operator, when used on a read-only list that is assigned to a mutable var variable, calls plus() on it and assigns the result back to the variable.
Initialize newArray as a MutableList using mutableListOf() and replace newArray.plus(j) with newArray += j. The += operator, when used with a MutableList, calls add() or addAll() on the MutableList, so it directly changes the original instance.
I didn’t check any of your logic. I’m only answering the question about why it’s crashing.
But as Gidds points out, the logic can be simplified a ton to achieve the same thing you’re trying to do using functions like filter(). A few odd things you’re doing:
Putting the result ofstring.split("") in a list for no reason
Using "" to split your string so it’s just a list of one-character Strings instead of a list of words. And you’re ignoring punctuation.
Filling newArray with indices so minOf will simply give you the first index that corresponded with being a palindrome, so it will always be 0.
Here’s how I might write this function (didn’t test it):
fun leastP(s: String): Int {
return s.split(" ")
.map { it.filter { c -> c.isLetter() } }
.filter { isPalindrome3(it) }
.minOfOrNull { it.length } ?: 0
}
I'm trying to write a code that prints out whatever the user inputted into the console, but when I insert a while loop that use the readLine() function as its condition before it, the code would always return with nothing even if the user inputted something into the console. The code is here below:
fun main() {
while(readLine()=="A") print("A is inputted")
print(readLine()+" 123")
}
My intention was for when the user inputted (into the first readLine()) anything besides "A", the code would proceed to the next line, then prints out the next string inputted (into the second readLine()) joined with " 123".
For example: "asdfasdfaf 123", but in actuality it would just prints " 123" instead
Can anyone tell me why this is the case? And what would be the code that'll get the expected behavior? Any help will be appreciated since I'm new to this, thanks :)
EDIT:
I've found the solution a while after posting this and it's kind of weird.
fun main(args: Array<String>) {
while(readln()=="A") print("A is inputted")
readLine() // throwaway readLine()
print("${readLine()} 123")
}
I might be wrong but from what I've gathered here, after the while loop is stopped, the code somehow inputted nothing --which I assume is a null-- into the second readLine(). So I just put a throwaway readLine() between those two. I still don't know why this is the case though
By using readLine() twice, you are effectively asking for 2 pieces of input. This is what your code is currently doing:
You are reading the input (using a while loop? Do you mean to use an if statement instead?)
You are reading a second piece of input, and appending " 123" to the second piece of input.
Try this instead:
fun main() {
//Some kind of for or while loop if you want to constantly take input
val input = readLine()
if (input == "A") {
println("A has been input")
println("$input 123")
}
}
The way it's written, you have to type your "other" input twice - once so it's seen as not "A", and again when you try to print it - you hit two readLine() calls when you type something that isn't "A"
At a guess, you're getting " 123" because you type "asdfasdfaf", which exits the while loop, but then you hit the second readLine() and you're probably just hitting Return again, wondering why it hasn't printed. So the print statement reads in the empty line you just typed, and you get " 123"
If you want to have access to the non-"A" input, you need to store it - that way you can check it during your if condition, and use it in your print statement later. Here's a way you can do it
fun main() {
// do-while runs the loop -at least once- and checks the repeat condition at the end
do {
val input = readLine()
if (input == "A") print("A is inputted")
// this prints inside the loop, now we just need to exit it
else print("$input 123")
} while (input == "A") // stops looping the first time you get non-"A" input
}
which is what Cloudate9 was getting at
I am not exactly sure what you are looking to do, but the way I read and understand your post, this is what I came up with:
fun main() {
val input = readLine()
if (input == "A") {
println("A has been inputted")
} else {
println("$input 123")
}
}
Below is the piece of code which I was trying out. there are two blocks of code. the first one creates a million threads/coroutines asynchronously in map and then later adds them up. the second block creates the million coroutines and adds them in the for loop and then prints in out.
According to me the first one should be faster as it creates them in parallel . the second one should be slow as you are creating million in one coroutine.
if my question makes sense at all I would like to get some understanding of this.
fun main() {
//first block
val elapsed1 = measureTimeMillis {
val deferred = (1..1000000).map { n->
GlobalScope.async{
n
}
}
runBlocking {
val sum = deferred.sumByDouble { it.await().toDouble() }
println(sum)
}
}
//second block
val elapsed2 = measureTimeMillis {
val def2 = GlobalScope.async{
var j = 0.0;
for(i in 1..1000000) {
j+=i
}
j
}
runBlocking {
val s = def2.await()
println(s)
}
}
println("elapsed1 $elapsed1")
println("elapsed2 $elapsed2")
}
Please note that, for above small block of code, it is very difficult determine which one is faster than another.
Also, the result of above execution may vary from system to system.
Hence, we cannot confirm which block of code is faster just by running above steps.
Also, I request you to please refer to the following article to get more clarity around this area:
What is microbenchmarking?
Let me first put the code then explain:
fun main() {
loop# while (true){
println("Input the action (add, remove, import, export, ask, exit):")
val userInput = scanner.nextLine()
when (userInput){
"add" -> add()
"remove" -> remove()
"import" -> import()
"export" -> export()
"ask" -> ask()
"exit" -> {
print("Bye bye!")
break#loop
}
}
}
}
This is the main function where the user chooses what he wants to do. First he adds some cards that contain terms and definitions as pairs, but thats irrelevant. The problem lies after that, when using the function ask().
fun ask() {
println("How many times to ask?")
for (i in 0 until scanner.nextInt()){
for ((key,value) in map){
println("Print the definition of \u0022$key\u0022:")
var userAnswer = (readLine() ?: "exit").toString()
if (userAnswer == value) {
println("Correct answer.")
continue
}
else {
loop# for ((key2,value2) in map){
if(map.containsValue(userAnswer) && userAnswer == value2){
println("Wrong answer. The correct one is \u0022$value\u0022, you've just written the definition of \u0022$key2\u0022")
break#loop
}else if (!map.containsValue(userAnswer)) {
println("Wrong answer. The correct one is \u0022$value\u0022.")
break#loop
}
}
}
}
}
}
The code works and everything, but after doing the ask() function, just when the program loops back to main(), it prints "Input the action (add, remove, import, export, ask, exit):" twice instead of once. A friend of mine told me it could be an empty input left in cache that triggers this, so that it goes once through main() without actually taking user input.
Please, if anyone has experience with this I would really appreciate it to hear and learn about it and how to prevent it, cause it hinders me from finishing the project. Would changing the way how I take in users input help?
I encountered the strangest thing.
Lets say I have a text file called "lines.txt". This file contains lines in key value pairs.
test:100
test1:200
test2:300
test3:400
If I read this file in Kotlin the list is not empty however the loop inside the output stream does not get called.
object App {
#JvmStatic
fun main(args: Array<String>) {
// file containing lines of text
val lines = Files.readAllLines(Paths.get("./hashes.txt"))
// not empty
println(lines.size)
// write back a modified version
PrintWriter(FileWriter(File("./lines2.txt"))).use { out -> {
// this doesn't get called
println(lines.size)
lines.forEach {
out.println(it.split(":")[0])
}
}
}
}
}
I don't understand why this is so if anyone can enlighten me that would be awesome.
The list is not empty. A single println(lines.size) will shown you that, because that println is never called.
You simply have one pair of curly braces too much.
change your code to
...
PrintWriter(FileWriter(File("./lines2.txt"))).use { out ->
// list is empty??
println(lines.size)
lines.forEach {
out.println(it.split(":")[0])
}
}
...
The reason is, that a lambda doesn't need its block in curly braces.
So don't write
out -> { ... }
just write
out -> ...
guenther already told you what is wrong with your code, but I think an explanation of what happened is missing.
Consider the following:
val x = { println("y") }
Will it print out y? No, the lamda is never invoked. You have to call x().
Let's take a look at what you did:
val x = { { println("y") } }
x()
Will it print out y? No, because you don't invoke the lambda that prints y.
To make things more clear, let's specify the types explicitely.
val x:() -> (() -> Unit) = { { println("y") } }
Now we can see that the first lambda invoked by x() returns a lambda as well so you would have to call x()() in order to invoke the returned lambda as well.
So using a second pair a curly braces is not just not optional but gives the code a whole new meaning.
But this means that there would be also another solution to your problem.
PrintWriter(FileWriter(File("./lines2.txt"))).use { out -> {
println(lines.size)
lines.forEach {
out.println(it.split(":")[0])
}
}() // <-- add braces here to invoke the lambda
}
So, you can either remove two brackets are add two more. Choice is yours.
Disclaimer: Removing two braces is the way to go. The other option is just to prove a point.