Kotlin how do I stop the program with the response output on the screen? - kotlin

I have an endless cycle going on. How do I stop the program to output the answer? The meaning of my program: reads all characters (including enter) and outputs the sum of only numbers.
fun main() {
fun StrToSum(str: String): Long {
var sum : Long = 0
var next = ""
for (symbol in str + " ") {
if (symbol == '-') {
if ((next != "-") && (next != "")) {
sum += next!!.toLong()
}
next = symbol.toString()
} else if (symbol.isDigit()) {
next += symbol
} else if (next != "") {
if (next != "-") {
sum += next!!.toLong()
}
next = ""
}
}
return sum
}
var string: String = ""
while (1<2) { //How stop it ?
var str = readLine()!!.toString()
string += " " + str
}
println (StrToSum(string)) //answer
}
maybe there is some kind of keyboard shortcut ? I work for IntelliJ from Jetbrains

You can terminate the currently running program, but that will kill it - it won't be able to output the answer. You need to code that handling as part of your design, so you enable the user to finish and print your result.
The usual way people do this is to have some kind of cancel input, like entering an x or something:
// while (true) is a typical way to create an infinite loop
while (true) {
var str = readLine()!!.toString()
// look for the cancel token, break out of the loop if you see it
if (str.lowercase() == "x") break
string += " " + str
}
If you don't want to do that (remember you can make the cancel token anything, like the word "cancel" if you like, and put a prompt on the screen telling the user to type it to finish) then you'd have to do something like detecting other keycodes like Ctrl+Z or whatever - and I'm not sure how you'd do that from a basic command-line program reading from standard input. Maybe someone knows some tricks you could use! It's not something I've ever had to do, so I can't help you there
edit If you're happy to just look for control characters like ^D in the lines of standard input, you could do this kind of thing
if (str.firstOrNull().code == 4) break // char value for ^D
But that still requires the user to press Enter after the Ctrl+D, so the line including that character can be sent from the terminal to standard input. That's just how it works, outside of the solutions in the discussion I linked which involve OS-level interaction or building a GUI so you have access to the raw keypresses.

Related

Removing a loop to make code run faster (Kotlin) (Big O)

I'm trying a leetcode challenge and am struggling to pass the challenge due to the speed of my code:
class Solution {
fun longestPalindrome(s: String): String {
var longestPal = ""
var substring = ""
for (i in 0..s.length) {
for (j in i + 1..s.length) {
substring = s.substring(i, j)
if (substring == substring.reversed() && substring.length > longestPal.length) {
longestPal = substring
}
}
}
return longestPal
}
}
I'm a newb and not familiar with Big O notation.
I imagine if I could use just one loop I would be able to speed this code up significantly but am not sure how I would go about this.
(Not saying this is the best approach, but that is a start)
Palindromes can only be found between two same letters. So one idea is to go through the string once, and keep track of letter indexes. When you encounter a letter you already saw before, and the difference in indexes is longer than the current longest palindrome, you check for a palindrome:
fun longestPal(s: String): String {
val letters = mutableMapOf<Char, MutableList<Int>>()
var longest = ""
s.indices.forEach { index ->
val indicesForCurrentChar = letters[s[index]] ?: mutableListOf()
for (i in indicesForCurrentChar) {
if ((index - i) < longest.length) break // (1) won't be the longest anyway
val sub = s.substring(i, index + 1)
if (sub == sub.reversed()) longest = sub
}
indicesForCurrentChar.add(index)
letters[s[index]] = indicesForCurrentChar
}
return longest
}
What is costly here is the palindrome check itself (sub == sub.reversed). But the check in (1) should contain it (think of a string which is the repetition of the same letter).
I would be curious to know what other suggest online.
Your code runs in O(n^3) time, a loop within a loop within a loop, because that reversed() call iterates up to the size of the input string. You can look up Manacher's algorithm for an explanation of how to do it in linear time (O(n)), no nested iteration at all.

Can you retry a Zig function call when it returns an error?

Zig's documentation shows different methods of error handling including bubbling the error value up the call stack, catching the error and using a default value, panicking, etc.
I'm trying to figure out how to retry functions which provide error values.
For example, in the below snippet from ziglearn, is there a way to retry the nextLine function in the event that a user enters greater than 100 characters?
fn nextLine(reader: anytype, buffer: []u8) !?[]const u8 {
var line = (try reader.readUntilDelimiterOrEof(
buffer,
'\n',
)) orelse return null;
// trim annoying windows-only carriage return character
if (#import("builtin").os.tag == .windows) {
return std.mem.trimRight(u8, line, "\r");
} else {
return line;
}
}
test "read until next line" {
const stdout = std.io.getStdOut();
const stdin = std.io.getStdIn();
try stdout.writeAll(
\\ Enter your name:
);
var buffer: [100]u8 = undefined;
const input = (try nextLine(stdin.reader(), &buffer)).?;
try stdout.writer().print(
"Your name is: \"{s}\"\n",
.{input},
);
}
This should do what you want.
const input = while (true) {
const x = nextLine(stdin.reader(), &buffer) catch continue;
break x;
} else unreachable; // (see comment) fallback value could be an empty string maybe?
To break it down:
instead of try, you can use catch to do something in the case of an error, and we're restarting the loop in this case.
while loops can also be used as expressions and you can break from them with a value. they also need an else branch, in case the loop ends without breaking away from it. in our case this is impossible since we're going to loop forever until nextLine suceeds, but if we had another exit condition (like a limit on the number of retries), then we would need to provide a "fallback" value, instead of unreachable.
You can also make it a one-liner:
const input = while (true) break nextLine(stdin.reader(), &buffer) catch continue else unreachable;
Hopefully the new self-hosted compiler will be able to pick up on the fact that the else branch is not necessary, since we're going to either break with a value loop forever.

How to set a Kotlin while loop stop after 3 times?

I'm new to Kotlin, I want to condition my while loop stop after 3 times, please, help! Also it should ask user to quit game or continue
val randomNumber: String = Random().nextInt(10).toString()
var guess= true
println("Welcome to the Number Guess Game")
println("Please guess number between 1 to 10")
do{
val User=readLine()!!.toString()
if(User==randomNumber){
guess=false
}
else{"Sorry Please Try Again"}
}while(guess)
println("Congratulation You have guessed the right number.")
Try this.
var correct = false
var tries = 0
val randomNumber = Random().nextInt(10) + 1
println("Welcome to the number guess game")
println("Please guess a number between 1 to 10")
do {
val input = readLine() ?: break
val guess = input.toIntOrNull()
tries += 1
correct = guess == randomNumber
if (!correct) {
println("Sorry please try again!")
}
} while (!correct && tries < 3)
if (correct) {
println("Congratulation You have guessed the right number.")
} else {
println("Sorry. The answer was $randomNumber")
}
Things to note:
Random.nextInt(10) will actually return a number between 0 and 9 so you need to add 1.
If readLine() returns null, there is nothing more to read, so readLine() ?: break will either return a string or stop the loop immediately if readLine() is null.
while (!correct && tries < 3) means continue while the guess is not correct and tries has not reached 3. tries is increased by 1 (tries += 1) on each guess. correct keeps track of whether the correct number has been guessed (guess == randomNumber).
toIntOrNull turns a String to an Int but returns null if it is not actually a number.
$randomNumber puts the value of randomNumber directly in a string so you can print it as part of a message.

How to run two loops at the same time?

I have been developing a very simple text game using Objective C and Xcode. It is almost done but I am having a problem, the scanf method stops the loop and asks for user input while I need the computer to be running the rest of the loop, the solution I came up with was running two while loops at the same time, one being the logic loop and another being a loop for user input.
I have been doing my research and it looks like using threads are the way to go, I just have not found a tutorial that will break it down for a n00b in Objective C (I am decent in java, I just have never worked with threads). If anybody could explain them or link me to a very broken down tutorial that would be great. Or if anybody has another idea I am open to anything else.
Necessary Code (The scanf I am having a problem with has asterisks on the line):
while(running != 0)
{
if(gameState == 1)
{
if(timeToGenerateNum == true)
{
while(randNumber < 10000000)
{
randNumber = arc4random() % 100000000;
}
NSLog(#"%i", randNumber);
timeToGenerateNum = false;
}
else
{
while(time <= 2500)
{
NSLog(#"Testing");
time++;
******************scanf("%i", &userNum);************************
if(userNum == randNumber)
{
score += time;
time = 0;
timeToGenerateNum = true;
}
}
NSLog(#"Game Over! Your score was %i!", score);
running = 0;
}
}
else if(gameState == 2)
{
NSLog(#"To play, simply type in the number that appears on the screen.");
NSLog(#"But be careful, you only have a short amount of time before GAME OVER!");
NSLog(#"The quicker you type in the number the more score you get!");
NSLog(#"Are you ready to start, if so type '1' and press enter!");
scanf("%i", &gameState);
}
}
You're going to have to learn a bit about BSD (Unix, Linux) input/output to pull this off: replace your call to scanf with a non-blocking function you write to acquire input from the user's keyboard.
This function should immediately return whatever the user typed, or immediately return with a zero character count if she didn't type anything.
Read up on the select(2) system call, and keep in mind that keyboard input (standard input) is the first file descriptor, file descriptor zero.

AutoHotKey key SEQUENCE, not just single-key hotkey

I'm not stupid... really.
How do you map a key SEQUENCE (ie: Ctrl + Q , F) in AutoHotKey.
I've got Ctrl + Q down:
^q::
I've even got F:
f::
The examples in the help files even show how to do two keystrokes in a row:
Numpad0 & Numpad1::
But it just will not work with:
^q & f ::
Or any of these either:
LCtrl & q & f::
^q & ^f::
^q^f::
^qf::
How do I accomplish a Key SEQUENCE triggering something, when one of those keys is the Ctrl key? I looked into using a HOTSTRING instead, but couldn't work out how to include the Ctrl character, in that context!
Alright; The answer seems to be:
^q::
Input Key, L1
if Key=f
...some code here...
return
In case someone's looking for a similar thing, but actually want CtrlQ + CtrlF and only if Ctrl is held throughout (so, to some, this might seem like CtrlQ + F), then here's how to do that:
$Ctrl::Send {Ctrl Down}
$Ctrl UP::
ChordIsBroken := True
Send {Ctrl Up}
Return
^q::
ChordIsBroken := False
Input, OutputVar, L1 M
If (!ChordIsBroken && Asc(OutputVar) = 6)
{
MsgBox "Hello, World!"
}
Else
{
SendInput %OutputVar%
}
Return
See https://superuser.com/a/725303/145431 for my explanation.
Or you can do it like this:
q & f::
if GetKeyState("Control") {
; Do something
return
}
return
I think this is a bit more readable than using Input Key, L1 as in above.
This catches CTRL+F. If Q is held down at that moment, your code fires.
^f::
If GetKeyState("q", "p") {
MsgBox test
} Else {
Send ^f
}
return
The selected answer works fine, but I spend the whole night writing me own solution before I found this answer, so...
Here is my over engineered solution -
SequenceRegister() {
registeredHook := 0
inputLen := 0
actions := Map()
return SequenceClosure
SequenceClosure(seq := "", ActionCb := () => true) {
if (!registeredHook) {
h := InputHook("BI")
h.KeyOpt("{All}", "N")
h.OnKeyDown := KeyDownHandler
h.Start()
registeredHook := h
}
actionKey := actions.Count
actions.Set(actionKey, Action)
Action(hook, VK, SC) {
if (SubStr(seq, 1, inputLen) = hook.Input && inputLen < StrLen(seq)) {
return
}
if (hook.Input = seq && inputLen = StrLen(seq)) {
ActionCb()
return
}
actions.delete(actionKey)
if (actions.Count = 0) {
Send("{Blind}" . Format("{{}vk{:x}sc{:x}{}}", VK, SC))
hook.Stop()
return
}
}
}
KeyDownHandler(hook, VK, SC) {
inputLen++
for key, value in actions.Clone() {
value(hook, VK, SC)
}
}
}
Use it like this -
Capslock & s::{
CreateSequence := SequenceRegister()
CreateSequence("sleep", () => MsgBox("I sleep"))
CreateSequence("sleed", SleedCb)
SleedCb() {
MsgBox("I sleed")
}
}
This allows to register any number of sequences and if none of the sequences match - the pressed key is replayed.
Note, that this code works only in AHK v2