I'm trying to take a simple calculator in Java and convert the code to Kotlin as an example, I've never used Kotlin before and I'm lost. I'm trying to take a number from a editText and convert it to a float to do the actual conversions and then do the operations on these for the result
var value1: Float? = null
var value2: Float? = null
var suma: Boolean = false
var resta: Boolean = false
var multi: Boolean = false
var div: Boolean = false
plus.setOnClickListener {
if (expression == null) {
expression.text = ""
} else {
value1 = expression.text.toString().toFloat()
suma = true
expression.text = ""
}
}
mul.setOnClickListener {
if (expression == null) {
expression.text = ""
} else {
value1 = expression.text.toString().toFloat()
multi = true
expression.text = ""
}
}
minus.setOnClickListener {
if (expression == null) {
expression.text = ""
} else {
value1 = expression.text.toString().toFloat()
resta = true
expression.text = ""
}
}
divide.setOnClickListener {
if (expression == null) {
expression.text = ""
} else {
value1 = expression.text.toString().toFloat()
div = true
expression.text = ""
}
}
dot.setOnClickListener {
expression.text = expression.text.toString() + "."
}
clear.setOnClickListener {
expression.text = ""
value1 = null
value2 = null
}
equal.setOnClickListener {
value2 = expression.text.toString().toFloat()
if (suma) {
var s = value1 + value2
expression.text = s.toString()
}
if (resta) {
var r = value1 - value2
expression.text = r.toString()
}
if (div) {
var d = value1 / value2
expression.text = d.toString()
}
if (multi) {
var m = value1 * value2
expression.text = m.toString()
}
}
When I try to do the adding, subtracting, multiplying or dividing the code is underlined in red after the operator and the value2 as well, the suggestion is to do this value1.plus(value2) but if I do that it also is in red and says only save or non-null asserted calls are allowed on a nullable reciever of type Float? If I follow all the suggestions it gives me it still doesn't stop being underlined in red.
This is how I'm starting the values
var value1: Float? = null
var value2: Float? = null
Don't make your values nullable. It's rarely necessary to need nullable primitive properties. The error you're getting is because you're trying to use values that might be null.
Instantiate them like this.
var value1: Float = 0f
var value2: Float = 0f
And in your clear() function, set them back to 0f rather than null.
If you really have to keep them null, you could do something like this where you only add them after checking they are both non-null, and then show an error message if either value is null:
if (suma) {
val s = value1?.let { value2?.plus(it) }
expression.text = s?.toString() ?: "Invalid input value(s)"
}
//...
Edit in response to your comment:
A typical calculator just resets the operator when you press = before anything else, so I would rewrite the equal button's listener like this (with a when statement for simplicity). I'm removing the value2 member property because it's unnecessary and using a local property instead.
equal.setOnClickListener {
val value2 = expression.text.toString().toFloatOrNull()
if (value2 != null) {
val result = when {
suma -> value1 + value2
resta -> value1 - value2
div -> value1 / value2
multi -> value1 * value2
else -> value1 // Shouldn't happen but can default to not changing number
}
expression.text = result.toString()
}
// reset for next operation
suma = false
resta = false
div = false
multi = false
}
Related
I can't solve this problem, how to separate the numbers and do the required arithmetic
https://codeforces.com/group/MWSDmqGsZm/contest/219158/problem/O
This is my code , I don't know how true it is
fun main(args:Array<String>) {
val scanner = Scanner(System.`in`)
var s: String = read()!!
var c: Char? = null
var a: String = ""
var b: String = ""
var t: Boolean = true
for (i in 1..s.length) {
if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') {
c = s[i]
t = false
}else{
if(t){
a+=s[i]
}else{
b+=s[i]
}
}
}
if(c=='+'){
println(a+b)
}else if (c=='-'){
println( "$a - $b" )
}else if (c=='*'){
println("$a * $b")
}else{
println("$a / $b")
}
Try this code:
fun main() {
val str = readLine()!!
val (index, operator) = str.findAnyOf(listOf("+", "-", "*", "/"))!!
val a = str.substring(0, index).toInt()
val b = str.substring(index + 1).toInt()
val result = when (operator) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
"/" -> a / b
else -> -1
}
println(result)
}
findAnyOf documentation:
Finds the first occurrence of any of the specified [strings] in this char sequence.
Returns A pair of an index of the first occurrence of matched string from [strings] and the string matched or null if none of [strings] are found.
Rest of the logic is quite straightforward.
How to compare each char from the String with Keys from the HashMap?
I have used loops of course and change each Key to Char.
val romanNumbers = HashMap<String, Int>()
romanNumbers[""] = 0
romanNumbers["I"] = 1
romanNumbers["V"] = 5
Instead of string.get(i) I also tried string[i]
for (i in string.indices){
for ((k, v) in romanNumbers) {
if (string.length == 1) {
res1 = romanNumbers.getValue(string)
}
if (string.get(i) == k.single()) {
num1 = v
}
if (string[i + 1] == k.single()) {
num2 = v
}
}
}
error
Exception in thread "main" java.util.NoSuchElementException: Char sequence is empty.
at kotlin.text.StringsKt___StringsKt.single(_Strings.kt:223)
at CodeWars.MappingTrainingKt.decode(MappingTraining.kt:38)
at CodeWars.MappingTrainingKt.main(MappingTraining.kt:4)
at CodeWars.MappingTrainingKt.main(MappingTraining.kt)
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'm trying to make a simple calculator but the equals button doesn't perform as expected, it doesn't do any of the operations even though the if statement is true. This is the code
var value1: Float = 0f
var value2: Float = 0f
var operator: String = "n"
val input = expression.text.toString().trim()
//this is the adding button the subtracting, multiplying, and dividing are basically the exact code
plus.setOnClickListener {
if (input.isNullOrBlank()) {
expression.text = ""
} else {
operator = "sum"
value1 = expression.text.toString().toFloat()
expression.text = ""
}
}
//equals button
equals.setOnClickListener {
val input2 = expression.text.toString().trim()
if (!input2.isNullOrBlank()) {
value2 = expression.text.toString().toFloat()
// this is the textView and it always shows up as n
expression.text = operator
//it never goes in any of these, I don't know if I'm setting it up wrong in the action buttons (add, sub, multi, div)
if (operator == "sum") {
var s = value1 + value2
expression.text = s.toString()
operator = "n"
}
if (operator == "sub") {
var r = value1 - value2
expression.text = r.toString()
operator = "n"
}
if (operator == "div") {
var d = value1 / value2
expression.text = d.toString()
operator = "n"
}
if (operator == "multi") {
var m = value1 * value2
expression.text = m.toString()
operator = "n"
}
}
}
Why is this happening? I don't know if I'm setting up the operator String wrong or if it's something else I'm doing wrong.
I wanted to have it so that if the values aren't imputed than the operator or equals button won't work like on the phone calculator
val input = expression.text.toString().trim()
Here you capture the content of that edittext at view setup phase. It's likely empty at this point.
Then, in the click listener you have conditional code for that value:
plus.setOnClickListener {
if (input.isNullOrBlank()) {
expression.text = ""
} else {
operator = "sum"
value1 = expression.text.toString().toFloat()
expression.text = ""
}
}
and the input.isNullOrBlank() condition is always true so the else branch never gets executed.
You likely should read the input (val input = expression.text.toString().trim()) inside the click listener.
This is what I came up with
//operator buttons
plus.setOnClickListener {
if (expression.text.toString().trim().isNullOrBlank()) {
expression.text = ""
} else {
value1 = expression.text.toString().toFloat()
operador = "suma"
expression.text = ""
}
}
the equals button stays the same