2

I am doing some of CodeWars challenges recently and I've got a problem with this one.

"You are given an array (which will have a length of at least 3, but could be very large) containing integers. The array is either entirely comprised of odd integers or entirely comprised of even integers except for a single integer N. Write a method that takes the array as an argument and returns this "outlier" N."

I've looked at some solutions, that are already on our website, but I want to solve the problem using my own approach.

The main problem in my code, seems to be that it ignores negative numbers even though I've implemented Math.abs() method in scala.

If you have an idea how to get around it, that is more than welcome.

Thanks a lot

object Parity {

  var even = 0
  var odd = 0
  var result = 0

  def findOutlier(integers: List[Int]): Int = {

    for (y <- 0 until integers.length) {
      if (Math.abs(integers(y)) % 2 == 0)
        even += 1
      else
        odd += 1
    }

    if (even == 1) {
      for (y <- 0 until integers.length) {
        if (Math.abs(integers(y)) % 2 == 0)
          result = integers(y)
      }
    } else {
      for (y <- 0 until integers.length) {
        if (Math.abs(integers(y)) % 2 != 0)
          result = integers(y)
      }
    }
    result
  }
The Archetypal Paul
  • 41,321
  • 20
  • 104
  • 134
Mateusz Woś
  • 333
  • 2
  • 10
  • 2
    The "main problem" with your code is the use of mutable variables (`var`s) and the fact that you traverse the complete collection multiple times. Very inefficient and totally unnecessary. (And you might try to format the code to make it more readable.) – jwvh Jun 13 '19 at 18:13
  • What's the problem with the code? Does it fail on a particular input? If yes - please include it in the question. Or does it crash or run out of time? – simpadjo Jun 13 '19 at 18:47
  • Why do you need to take the absolute value? x%2==0 still gives the correct parity results for negative numbers. Can you give us the specific test cases and results where your code is failing? – Ethan Jun 13 '19 at 19:13
  • Yes, here are the tests – Mateusz Woś Jun 13 '19 at 19:26
  • Here is the sample: – Mateusz Woś Jun 13 '19 at 19:27
  • import org.scalatest._ class ParityTest extends FlatSpec with Matchers { val tests = List( (List(2, 4, 6, 8, 10, 3), 3), (List(2, 4, 0, 100, 4, 11, 2602, 36), 11), (List(160, 3, 1719, 19, 11, 13, -21), 160) ) tests.foreach { case (input, expected) => s"findOutlier($input)" should s"return $expected" in { Parity.findOutlier(input) should be (expected) } } } – Mateusz Woś Jun 13 '19 at 19:27
  • And here are the results: ParityTest findOutlier(List(2, 6, 8, 10, 3)) should return 3 findOutlier(List(2, 6, 8, 200, 700, 1, 84, 10, 4)) should return 1 findOutlier(List(17, 6, 8, 10, 6, 12, 24, 36)) should return 17 findOutlier(List(2, 1, 7, 17, 19, 211, 7)) should return 2 Test Failed Some(Even in the front) 7 was not equal to 2 Stack Trace Completed in 20ms findOutlier(List(1, 1, 1, 1, 1, 44, 7, 7, 7, 7, 7, 7, 7, 7)) should return 44 Test Failed Some(Even in the middle) 7 was not equal to 44 – Mateusz Woś Jun 13 '19 at 19:30
  • There are more but obviously I cannot include it all, as it is too long. – Mateusz Woś Jun 13 '19 at 19:31
  • Also guys, I am new to SO so any tips how to format the next questions, what can be done better are welcome. – Mateusz Woś Jun 13 '19 at 19:32
  • 2
    the main complaint with your formatting is the inconsistent style withing the code itself. Generally you should have lines indented based on how deep in the structure you are. Check the Scala Style Guide entries on indentation, nesting, and control structure for advice on how to format this better: https://docs.scala-lang.org/style/ – Ethan Jun 13 '19 at 19:36
  • 1
    You can hit the edit button under the question to clean up your code a bit, and add your tests to the question. – Ethan Jun 13 '19 at 19:40
  • 1
    Hint: You can work out from the first three numbers if you're looking for an odd or an even. That's why it has length at least 3 – The Archetypal Paul Jun 14 '19 at 14:41

1 Answers1

4

Your code handles negative numbers just fine. The problem is that you rely on mutable sate, which leaks between runs of your code. Your code behaves as follows:

val l = List(1,3,5,6,7)
println(Parity.findOutlier(l)) //6
println(Parity.findOutlier(l)) //7
println(Parity.findOutlier(l)) //7

The first run is correct. However, when you run it the second time, even, odd, and result all have the values from your previous run still in them. If you define them inside of your findOutlier method instead of in the Parity object, then your code gives correct results.

Additionally, I highly recommend reading over the methods available to a Scala List. You should almost never need to loop through a List like that, and there are a number of much more concise solutions to the problem. Mutable var's are also a pretty big red flag in Scala code, as are excessive if statements.

Ethan
  • 821
  • 4
  • 12