4
\$\begingroup\$

I am trying to implement ugly number sequence generation in Scala.

Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15...

I have implemented using var keyword like java implementation and it is working fine. Here is the ideone link of complete code.

Can someone suggest better of implementing it using Scala idioms and without using mutable values?

/**
 * Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence
 * 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15,
 * shows the first 11 ugly numbers. By convention, 1 is included.
 * Write a program to find and print the 150th ugly number.
 *
 */
object UglyNumbers extends App {
  var uglyNumbers = List(1)
  val n = 11

  var i2 = 0;
  var i3 = 0;
  var i5 = 0;

  // initialize three choices for the next ugly numbers
  var next_multiple_2 = uglyNumbers(i2) * 2;
  var next_multiple_3 = uglyNumbers(i3) * 3;
  var next_multiple_5 = uglyNumbers(i5) * 5;

  for (i <- 0 to n) {
    val nextUglyNumber = min(next_multiple_2, next_multiple_3, next_multiple_5)
    uglyNumbers = uglyNumbers :+ nextUglyNumber

    if (nextUglyNumber == next_multiple_2) {
      i2 = i2 + 1
      next_multiple_2 = uglyNumbers(i2) * 2
    }

    if (nextUglyNumber == next_multiple_3) {
      i3 = i3 + 1
      next_multiple_3 = uglyNumbers(i3) * 3
    }

    if (nextUglyNumber == next_multiple_5) {
      i5 = i5 + 1
      next_multiple_5 = uglyNumbers(i5) * 5
    }
  }

  for (uglyNumber <- uglyNumbers)
    print(uglyNumber + "   ")

  def min(a: Int, b: Int, c: Int): Int = (a, b, c) match {
    case _ if (a <= b && a <= c) => a
    case _ if (b <= a && b <= c) => b
    case _ => c
  }
}
\$\endgroup\$
1

1 Answer 1

1
\$\begingroup\$

First off, I'd like to mention, that my Scala experience is limited, so please do point out any errors.

You should implement your algorithm in it's own class implementing an appropriate interface/trait (probably Iterator, but there may be better ones).

That would also avoid having the awkward hard-coded limit to 11 elements in the main algorithm.

I'm not a fan of the repeated code for the three base numbers. Off the top of my head I'm not sure how to avoid it, but would assume it would include using case classes.

You should also have a look at your variable names. You have a mixture of short cryptic names (n, i3, etc.) and two different styles (camel case and underlines). You should always use descriptive names (maxIterations, index3) and use a single style (preferably camel case as this is the convention for Scala).

BTW, List has a min method, so there is no need to roll your own:

val nextUglyNumber = List(next_multiple_2, next_multiple_3, next_multiple_5).min;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.