Soy nuevo en scala e intento convertir el código de Java para encontrar números que tengan dígitos únicos (o distintos) en scala. por ejemplo

Input : 10 20
Output : 10 12 13 14 15 16 17 18 19 20  (Except 11)

El código java es

class Test 
{ 
    // Method to print unique digit numbers 
    // in range from l to r. 
    static void printUnique(int l, int r) 
    { 
        // Start traversing the numbers 
        for (int i=l ; i<=r ; i++) 
        { 
            int num = i; 
            boolean visited[] = new boolean[10]; 

            // Find digits and maintain its hash 
            while (num != 0) 
            { 
                // if a digit occcurs more than 1 time 
                // then break 
                if (visited[num % 10]) 
                    break; 

                visited[num%10] = true; 

                num = num/10; 
            } 

            // num will be 0 only when above loop 
            // doesn't get break that means the 
            // number is unique so print it. 
            if (num == 0) 
                System.out.print(i + " "); 
        } 
    } 

Aquí l y r son los rangos.

Mi código scala equivalente es

def printUnique(l:int,r:int)
     | for(i <- l to r)
     | {
     | num=i
     | val z = new Array[Boolean](10)
     | while (num != 0)
     | {
     | if(z[num % 10])
<console>:8: error: identifier expected but integer literal found.
       if(z[num % 10])

No estoy seguro acerca del error. ¿Puedo obtener ayuda para convertir este código a scala de manera optimizada?

-2
pooja 17 sep. 2018 a las 14:37

5 respuestas

La mejor respuesta

Este es un predicado que determina si un número tiene dígitos repetidos:

def distinctDigits(n: Int): Boolean = {
   val s = n.toString
   s.length == s.distinct.length
 }

Eso se puede usar con filter para dar la lista que desea

(10 to 20).filter(distinctDigits)
3
Tim 17 sep. 2018 a las 12:03
// this returns a stream of the number's digits,
// from right to left. It's lazily evaluated.
def digits(n: Int): Stream[Int] =
  if (n == 0) Stream.Empty
  else (n % 10) #:: digits(n / 10)

// Counts the number of a digit occurences instead of
// storing a flag in Array[Boolean]. In the latter case
// it would require `if`, while we don't need any here.
// It's lazy as well, so will not need excessive evaluations.
def copies(d: Stream[Int]) = {
  val z = new Array[Int](10)
  d.map { i => z(i) = z(i) + 1; z(i) }
}

// Here we check if any digit has more than 1 occurence. The
// evaluation will stop as soon as such a digit found.
def test(n: Int) = copies(digits(n)).exists(_ > 1)

10 to 20 filterNot (test) foreach (println)
0
Alexander Azarov 17 sep. 2018 a las 17:13

Creo que el error en su código es que en Scala acceder a un elemento de un Array o cualquier otra colección no se hace con corchetes, sino con los normales:

// wrong:
// array[index]

// correct:
array(index)

De todos modos, una solución alternativa en Scala, que no se basa en métodos String y es similar en espíritu a su código original, podría verse así:

def getDigits(number: Int): Iterator[Int] =
  Iterator.iterate(number)(_ / 10).takeWhile(_ != 0).map(_ % 10)

def hasUniqueDigits(number: Int): Boolean = {
  val visited = Array.ofDim[Boolean](10)
  getDigits(number).forall {
    digit =>
      if (visited(digit)) false
      else {
        visited(digit) = true
        true
      }
  }
} 

def getUniqueDigitNumbers(left: Int, right: Int): IndexedSeq[Int] =
  left to right filter hasUniqueDigits

def printUnique(left: Int, right: Int): Unit =
  getUniqueDigitNumbers(left, right) foreach println
1
Kolmar 17 sep. 2018 a las 12:35

Esto debería resolverlo

def getDistinctNumbers(start: Int, end: Int): List[Int] = {
  if (start > end) return List.empty
  val hasUniqueDigits: Int => Boolean = a => {
    val str = a.toString
    str.split("").distinct.size == str.length
  }

 // From the range filter only the elements which have unique digits
 (start to end).toList.filter(hasUniqueDigits)
}
0
gaurav.singharoy 18 sep. 2018 a las 07:06
 def isUniqueDigits(n:Long):Boolean={
 import scala.annotation.tailrec
  @tailrec
  val x = if(n<0) -n else n
  val list:List[Int] = x match{
   case x if(x>=0 && x<10) => List(x.toInt)
   case x if(x>=10)  =>toDig(x/10):+(x%10).toInt
   }
  list == list.distinct
  }

En Scala REPL:

scala> (738 to 778).filter(isUniqueDigits(_))
res14: scala.collection.immutable.IndexedSeq[Int] = Vector(738, 739, 740, 741, 742, 743, 745, 746, 748, 749, 750, 751, 752,
753, 754, 756, 758, 759, 760, 761, 762, 763, 764, 765, 768, 769)
0
RAGHHURAAMM 26 sep. 2018 a las 16:06