Kotlin - Problems with while() - error-handling

I was making a calculator in Kotlin and I'm having trouble solving an issue that I'm having with while().On this particular part of the code, I'm trying to find the first operator in the equation, but I need to exclude the ones that indicate whether a number is negative - (or positive +, optional), which need to be indicated between parentheses like so: (-5)
var charay = charArrayOf('+', '-', '*', '/')
var op = 0
var reference = 0
var bol = false
while( bol == false && op != -1){
println(op)
println(bol)
println(bol == false && op != -1)
op = input.indexOfAny(charay, reference)
if (!input.get(op - 1).equals('(')){
bol = true
}else{
reference = op + 1
}
println(op)
println(bol)
println(bol == false && op != -1)
}
To test a normal equation I entered the equation 4+4 and the console looks like this:
0
false
true
1
true
false
0
false
true
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: -2
at java.lang.String.charAt(String.java:658)
at CalculatorKt.CalculateValue(Calculator.kt:67)
at CalculatorKt.CalculateValue(Calculator.kt:108)
at CalculatorKt.main(Calculator.kt:119)
Like I suspected, for some reason, the variables reset at the end of the while(), which is the reason why it never leaves said while(). Can anyone tell me why?

Read the error. You're trying to read the character of a string at an index that doesn't exist with this statement:
input.get(op - 1)
You need to check what op is first to make sure it is found. indexOfAny returns -1 if not found in the string. Because we can't see what charay is, we can't help you further.

Related

Return table value index via metatable

I'm looking for a way to retrive index value via metatable. This is my attempt:
local mt = { __index =
{
index = function(t, value)
local value = 0
for k, entry in ipairs(t) do
if (entry == value) then
value = k
end
end
return value
end
}
}
t = {
"foo", "bar"
}
setmetatable(t,mt)
print(t.index(t,"foo"))
Result is 0 instead of 1. Where I'm wrong?
My attempt:
local mt = {
__index = function(t,value)
for index, val in pairs(t) do
if value == val then
return index
end
end
end
}
t = {
"foo",
"bar",
"aaa",
"bbb",
"aaa"
}
setmetatable(t,mt)
print(t["aaa"]) -- 3
print(t["asd"]) -- nil
print(t["bbb"]) -- 4
print(t["aaa"]) -- 3
print(t["bar"]) -- 2
print(t["foo"]) -- 1
Result is 0 instead of 1. Where [am I] wrong?
The code for the index function is wrong; the problem is not related to the (correct) metatable usage. You're shadowing the parameter value when you declare local value = 0. Subsequent entry == value comparisons yield false as the strings don't equal 0. Rename either the parameter or the local variable:
index = function(t, value)
local res = 0
for k, entry in ipairs(t) do
if entry == value then
res = k
end
end
return res
end
An early return instead of using a local variable in the first place works as well and helps improve performance.
To prevent such errors from happening again, consider getting a linter like Luacheck, which will warn you if you shadow variables. Some editors support Luacheck out of the box; otherwise there are usually decent plugins available.

My while loop wont end when condition is met

So what I am trying to do is make a program that makes the user enter a password. If the password is correct, or if there attempts reach a total of 3 the program should stop... but it doesn't.
password = "password"
guess = ""
tries = 0
while guess != password or tries != 3:
guess = input("Password: ")
tries += 1
print(f"{abs(tries - 3)} Tries Remaining.")
Write like this:
password = "password"
tries = 0
while True:
if tries == 3:
break
guess = input("Password: ")
if guess == password:
break
tries += 1
print(f"{abs(tries - 3)} Tries Remaining.")
Your conditional needs to be a logical AND, not a logical OR.
while guess != password and tries != 3:
When you use a logical OR, the while loop continues if either expression evaluates to true.
So with the logical AND, when tries == 3, the second expression evaluates to false and we exit the loop.
The guess inside the while loop is a local variable , so the global variable remains unchanged. global guess is always '' and so the condition always evaluates to true.

Kotlin algorithm to reverse a given string

I'm creating an algorithm in Kotlin that should reverse a given string and output it, so, for example, the string would be "Hello World! and the output would be "olleH !dlroW. I know there's a function that does this already but I'm practising with loops and if statements so I'm doing it myself.
So far, I've got most of a working solution, the only problem with the code I have in that it only works with odd length strings, because of a while loop. I've put what I have in this post.
I'm stuck on what to change to make this program work with strings that are of an even length, currently with those strings, the program falls into an infinite loop because the condition is never met.
The exclusion part of the program will jump over characters that are included in the exclusion string, I've already tested this and it works fine, provided the string minus the skipped character is not of even length.
fun main() {
val userInput = ""
val exclusion = ""
val wordsInString = userInput.split(" ")
var wordsSize = wordsInString.size
var wordPointer = 0
while (wordPointer < wordsSize) {
var currentWord = wordsInString[wordPointer]
var charArray = currentWord.toCharArray()
var charPointerOne = 0
var charPointerTwo = currentWord.length - 1
while (charPointerOne != charPointerTwo) {
if (exclusion.contains(charArray[charPointerOne])) {
charPointerOne++
} else if (exclusion.contains(charArray[charPointerTwo])) {
charPointerTwo--
} else {
var charToSwtichOne = charArray[charPointerOne]
var charToSwitchTwo = charArray[charPointerTwo]
charArray[charPointerOne] = charToSwitchTwo
charArray[charPointerTwo] = charToSwtichOne
charPointerOne++
charPointerTwo--
}
}
wordPointer++
var outputString = String(charArray)
print(outputString + " ")
}
}
You need to change the loop control condition to use < instead of !=. because in case of even length strings they simply never meet and jump over. for example if you had a String of length two, then on first iteration charPointerOne will have value 0 and charPointerTwo will have value 1, and on the next iteration charPointerOne will be incremented to 1 and charPointerTwo will be decremented to 0 and these values still satisfy the loop control hence the loop continues. So to fix this change your code as
while (charPointerOne < charPointerTwo)

Check if a list contains at least one variable non null

I'm making my first app in Kotlin and there is a lot of syntax I don't know, and I was wondering if there is a better way to check if a list contains at least one non null entry.
For now my solution is:
var atLeastOneValue: Boolean
var i = 0
for (x in list) {
if (x != null) atLeastOneValue = true
else i++
}
if (list.size == i) atLeastOneValue = false
return atLeastOneValue
I'm working with MutableList<String>.
You can use contains function for that:
val hasNull = list.contains(null)
contains can also be called in the operator form, it corresponds to the operator in:
val hasNull = null in list
val hasNoNull = null !in list

Trying to setState using eval() function (React Native)

I'm trying to set multiple states in a for loop to be false or true depending on whether they meet the (if statement) requirement. The for loop will loop through an array of strings, each string represents a state. But I can't seem to use eval within this.setState function...
I have tried researching online but none of the solutions match my problem or what I'm trying to solve. I even tried eval(this.state.anything) = false but it still doesn't work and shows a left hand assign invalid error.
let businessState = [
"this.state.groupName",
"this.state.groupOwnerName",
"this.state.groupDesc",
"this.props.profile._id",
"this.state.businessName",
"this.state.businessDesc",
"this.state.businessRegNo",
"this.state.businessType",
"this.state.businessEmail",
"this.state.businessTel",
"this.state.businessWeChat",
"this.state.businessRegPhotoUri",
"this.state.businessSignPhotoUri"
];
var temp = ""
for (i = 0; i < businessState.length; i++) {
if (eval(businessState[i]) == ""){
temp = businessState[i]+ "Error"
this.setState({
eval(temp): true
})
}
}
As you can see from the code above, I want to evaluate the state, and if the value that this particular state holds is an empty string "", I want to set this state name + "Error" (For example, if this.state.email is empty string "" I want to set this.state.emailError to true.
Instead of this.setState({eval(temp): true}) try this.setState({[temp]: true}). The brackets will output the string value stored in temp as a variable name in setState.
This article gives a good explanation
This Stack Overflow question and the accepted answer also should help