I am learning Kotlin by doing exercises on exercism.com. I am currently working on triangles. Part of my solution is like this:
class Triangle<out T : Number>(a: T, b: T, c: T) {
init {
require (a != 0 && b != 0 && c != 0)
}
}
On the line with require(), IntelliJ gives the warning:
Condition 'a != 0 && b != 0' is always false
Condition 'a != 0 && b != 0 && c != 0' is always false
I have the following tests:
class TriangleTest {
#Test
fun `equilateral - all sides are equal`() {
assertTrue(Triangle(2, 2, 2).isEquilateral)
}
#Test(expected = IllegalArgumentException::class)
fun `equilateral - all zero sides is not a triangle`() {
assertFalse(Triangle(0, 0, 0).isEquilateral)
}
}
Both of these pass. If IntelliJ's warning were correct, then one of these would fail. Why does IntelliJ give this incorrect warning?
Related
The problem I'm working on accepts a number string and will output the product of the odd or even numbers in the string. While the product of purely number string is working fine, my code should also accept strings that is alphanumeric (ex: 67shdg8092) and output the product. I'm quite confused on how I should code the alphanumeric strings, because the code I have done uses toInt().
Here's my code:
fun myProd(Odd: Boolean, vararg data: Char): Int {
var bool = isOdd
var EvenProd = 1
var OddProd = 1
for (a in data)
{
val intVal = a.toString().toInt()
if (intVal == 0)
{
continue
}
if (intVal % 2 == 0)
{
EvenProd *= intVal
}
else
{
OddProd *= intVal
}
}
if(bool == true) return OddProd
else return EvenProd
}
Use toIntOrNull instead of toInt. It only converts numeric string
val intVal = a.toString().toIntOrNull()
if (intVal == null || intVal == 0) {
continue
}
Starting from Kotlin 1.6 you can also use a.digitToIntOrNull().
P.S. Your method could be also rewritten in functional style
fun myProd(isOdd: Boolean, input: String): Int {
return input.asSequence()
.mapNotNull { it.toString().toIntOrNull() } // parse to numeric, ignore non-numeric
.filter { it > 0 } // avoid multiplying by zero
.filter { if (isOdd) it % 2 != 0 else it % 2 == 0 } // pick either odd or even numbers
.fold(1) { prod, i -> prod * i } // accumulate with initial 1
}
open class Test1 {
fun name(a: Int, b: Int): Int {
if (a % 2 == 0 && b % 2 == 0) return (a * b)
if (a % 2 == 1 && b % 2 == 1) return (a + b)
if ((a % 2 == 0).xor(b % 2 == 0)) return if (a > b) (a - b) else (b - a)
}
}
class Test2 : Test1() {
}
val obj1 = Test2()
print(obj1.name(7 , 8))
I'm trying to learn inheritance in Kotlin, but when I call name function from father class and try to print the result I get error below.
error: a return expression required in a function with a block body ('{...}') }
If the first and the second condition is false, the third one must be true so you can remove the last condition. The compiler does not seem to be able to draw this conclusion, so it suspects a case where there is no return.
fun name(a: Int, b: Int): Int {
if (a % 2 == 0 && b % 2 == 0) return (a * b)
if (a % 2 == 1 && b % 2 == 1) return (a + b)
return if (a > b) (a - b) else (b - a)
}
You can also simplify this method as follows
fun name(a: Int, b: Int): Int {
if (a % 2 != b % 2) return if (a > b) (a - b) else (b - a);
return if (a % 2 == 0) (a * b) else (a + b)
}
Your last line of the function
if ((a % 2 == 0).xor(b % 2 == 0)) return if (a > b) (a - b) else (b - a)
if you add brackets for clarity, it would look like:
if ((a % 2 == 0).xor(b % 2 == 0)) {
return if (a > b) (a - b) else (b - a)
}
So if the if test is false, the code won't run, which means you've reached the end of the function and still haven't returned something. You have to return an Int.
As already answered, in order for your code to compile your function must return an int from all execution paths, your function doesn't satisfy that condition. what happens if all the if conditions eveluate to false?
And second thing is that in kotlin return is an expression, so you can lift it out like so
fun name(a: Int, b: Int): Int {
return if (a % 2 == 0 && b % 2 == 0) { (a * b) }
else if (a % 2 == 1 && b % 2 == 1) { (a + b) }
else if ((a % 2 == 0).xor(b % 2 == 0)) { if (a > b) (a - b) else (b - a) }
else SOME_DEFAULT_INT
}
What should I use instead of the whats_there parameter so the value of x will be 0?
val x =
if (true) {
for (i in 1..5)
if (i == 4)
return#whats_there 0
1
}
else 2
val x = if (ok) run {
for (i in 1..5) {
if (i == someValue)
return#run 10
}
5
} else 2
or
val x = if (ok) {
if (someValue in 1..5) 10 else 5
} else 2
Using a return like that is hard to read and prone to error. This example is probably too simplified to show your real problem, but it looks like you could use any(), e.g.:
val x =
if (true) {
if ((1..5).any{ it == 4 })
0
else
1
} else
2
That probably expresses your intent better than a loop would.
You might find it even clearer to re-order the cases, so you can use a when:
val x = when {
!true -> 2
(1..5).any{ it == 4 } -> 0
else -> 1
}
in order to solve my problem i used #IR42 first solution, but i had to use it a bit differently:
val x = run {
if (ok){
for (i in 1..5)
if (i == someValue)
return#run 10
5
}
else 2
}
In the below code, both the variables are vals, but the smart cast doesn't work even after the null check. Why?
fun SLLNode?.sumListWith(node: SLLNode?, carry: Int = 0): SLLNode? =
when {
this == null && node == null -> if (carry == 0) null else SLLNode(carry)
this == null -> node.also { it!!.value += carry } // Smart cast doesn't work here.
node == null -> this.also { value += carry } // Works here.
else -> {
...
}
}
Smart cast is working!, just make sure that value property is var in class SLLNode:
class SLLNode(var value: Int) // Not val
fun SLLNode?.sumListWith(node: SLLNode?, carry: Int = 0): SLLNode? =
when {
this == null && node == null -> if (carry == 0) null else SLLNode(carry)
this == null -> node.also { it!!.value += carry } // Smart cast doesn't work here.
node == null -> this.also { value += carry } // Works here.
else -> {
...
}
}
"value" can only either be 0, 60, 120, 180, 240 or 300.
When I try to count each change that "value" has using iterations I'm not getting values of +1. It gives values which are stepping by 10000. Also I do not wish to iterate when a value is reached, I only wish to iterate when it has changed one of the 6 values.
#include <stdio.h>
int angles;
int counter[6] = {0, 60, 120, 180, 240, 300};
if (a == 1 && b == 1 && c == 0)
{
value = 0;
}
if (a == 1 && b == 0 && c == 0)
{
value = 60;
}
if (a == 1 && b == 0 && c == 1)
{
value = 120;
}
if (a == 0 && b == 0 && c == 1)
{
value = 180;
}
if (a== 0 && b == 1 && c == 1)
{
value= 240;
}
if (a == 0 && b == 1 && c == 0)
{
value = 300;
}
2**3 == 8
You are missing conditions for some of the possible combinations of values.
I would put the conditions into a function and return the desired value as soon as it has been determined because that allows to sort out the conditions. Doing that, you will inevitably notice that you do not know what to return in some cases.
Other than that, it´s not clear to me what you are trying to achieve.
Something like this:
#define ERROR -1
int get_value(int a, int b, int c)
{
if(a)
{
if(b)
{
return c ? ERROR : 0;
}
else
{
return c ? 60 : 120;
}
}
else
{
if(b)
{
return c ? 240 : 300;
}
else
{
return c ? 180 : ERROR;
}
}
return ERROR;
}
I would probably avoid all this, consider each of the three values as one bit and use bit operators to get to the desired value.