标量中具有唯一(或不同)数字的数字

时间:2018-09-17 11:37:08

标签: scala

我是scala的新手,并尝试转换查找scala中具有唯一(或不同)数字的数字的java代码。 例如

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

java代码是

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 + " "); 
        } 
    } 

这里l和r是范围。

我等效的scala代码是

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])

我不确定该错误。能否以最佳方式将代码转换为scala

5 个答案:

答案 0 :(得分:3)

这是一个确定数字是否具有重复数字的谓词:

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

可以与filter一起使用,以提供所需的列表

(10 to 20).filter(distinctDigits)

答案 1 :(得分:1)

我认为,代码中的错误是,在Scala中,访问Array或任何其他集合的元素不是用方括号来完成的,而是用普通的方括号来完成的:

// wrong:
// array[index]

// correct:
array(index)

无论如何,它是Scala中的一种替代解决方案,它不依赖于String方法,并且在本质上与原始代码类似,可能看起来像这样:

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

答案 2 :(得分:0)

// 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)

答案 3 :(得分:0)

这应该解决

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)
}

答案 4 :(得分:0)

 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
  }

在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)