【问题标题】:Finding 'tidy numbers' in Scala在 Scala 中寻找“整齐的数字”
【发布时间】:2019-01-19 14:44:21
【问题描述】:

一个整齐的数字是一个数字按非递减顺序排列的数字,例如1234. 这是一种查找用 Ruby 编写的整齐数字的方法:

def tidy_number(n)
  n.to_s.chars.sort.join.to_i == n
end

p tidy_number(12345678)     # true
p tidy_number(12345878)     # false

我尝试在 Scala 中编写相同的东西,结果如下:

object MyClass {
def tidy_number(n:Int) = n.toString.toList.sorted.mkString.toInt == n;

    def main(args: Array[String]) {
      println(tidy_number(12345678))        // true
      println(tidy_number(12345878))        // false
    }
}

我可以在 Scala 中做到这一点的唯一方法是将整数转换为字符串到列表,然后对列表进行排序并再次返回。我的问题:有没有更好的方法?从某种意义上说,“更好”的转化次数更少。我主要是在寻找一个简洁的 Scala,但如果有人指出在 Ruby 中更简洁的方法,我将不胜感激。

【问题讨论】:

  • "The methods .toList and .mkString are not needed".sorted == " ..LSTaaddddeeeeeeghhiikmmnnnnooorrssttttt"
  • “我在 Scala 中做到这一点的唯一方法是将整数转换为字符串到列表,然后对列表进行排序并再次返回”这正是 Ruby 代码正在做的事情跨度>

标签: ruby scala integer


【解决方案1】:

你可以在 Scala 中对字符串使用sorted,所以

def tidy_number(n: Int) = {
  val s = n.toString
  s == s.sorted
}

分两部分进行也可以避免额外的 toInt 转换。

我从未使用过 ruby​​,但 this post 建议您这样做是最好的方法

【讨论】:

    【解决方案2】:

    您可以检查每对相邻的数字以确保第一个值是

      def tidy_number(n:Int) =
        n.toString.sliding(2,1).forall(p => p(0) <= p(1))
    

    从有用的 cmets 更新以下内容

    正如 cmets 中所指出的,这对于个位数的数字会失败。把这个和另一个评论放在一起给出了这个:

      def tidy_number(n:Int) =
        (" "+n).sliding(2,1).forall(p => p(0) <= p(1))
    

    更加迂腐,最好在比较之前转换回Int,这样您就不必依赖代表数字的字符的排序顺序与数字本身的排序顺序相同。

      def tidy_number(n:Int) =
        (" "+n).sliding(2,1).forall(p => p(0).toInt <= p(1).toInt)
    

    【讨论】:

    • 这看起来像一个非常奇怪的相等检查:) p =&gt; p(0) &lt;= p(1)。不过技术不错
    • 不适用于字符串表示小于 2 的数字。但可以在线性时间而不是对数线性时间内完成工作!
    • (" " + n)... 解决了个位数问题并节省了键入 toString 的时间
    • ...在 Ruby 中是n &lt; 10 || n.digits.each_cons(2).all? { |n,m| n &gt;= m }。它是n &lt;= m,而不是n &lt;= m,因为Integer#digits 返回一个数组,其第一个元素是n 的个位。另见Enumerable#each_cons|| 是逻辑或。
    • toInt 会为" " 出错,因此更彻底的版本不适用于它。如果重复数字没问题,"0" + n更好
    【解决方案3】:

    我可以在 Scala 中做到这一点的唯一方法是将整数转换为字符串到列表,然后对列表进行排序并再次返回。我的问题:有没有更好的方法?

    String不需要转换和排序。

    def tidy_number(n :Int) :Boolean =
      Iterator.iterate(n)(_/10)
              .takeWhile(_>0)
              .map(_%10)
              .sliding(2)
              .forall{case Seq(a,b) => a >= b
                      case _ => true} //is a single digit "tidy"?
    

    更好?很难说。一个小优势是数学运算(/%)在第一个false 之后停止。因此,对于Int1234567890,在返回结果之前只有 3 个操作(2 个模和 1 个除)。 (以相反的顺序比较数字。)

    但是看到 Int 最多只有 10 位数字,我会选择 Joel Berkeley 的答案,只是为了简洁。

    【讨论】:

      【解决方案4】:
       def tidyNum(n:Int) = {
        var t =n; var b = true;
        while(b && t!=0){b=t%10>=(t/10)%10;t=t/10};b  
       }
      

      在 Scala REPL 中:

      scala> tidyNum(12345678)
      res20: Boolean = true
      
      scala> tidyNum(12343678)
      res21: Boolean = false
      
      scala> tidyNum(12)
      res22: Boolean = true
      
      scala> tidyNum(1)
      res23: Boolean = true
      
      scala> tidyNum(121)
      res24: Boolean = false
      

      这可以适用于任何大小,只需在函数签名中修改类型,例如 LongBigInt,如 tidyNum(n:Long)tidyNum(n:BigInt),如下所示:

       def tidyNum(n:BigInt) = {
        var t =n; var b = true;
        while(b && t!=0){b=t%10>=(t/10)%10;t=t/10};b
      }
      
      scala> tidyNum(BigInt("123456789"))
      res26: Boolean = true
      
      scala> tidyNum(BigInt("1234555555555555555555555567890"))
      res29: Boolean = false
      
      scala> tidyNum(BigInt("123455555555555555555555556789"))
      res30: Boolean = true
      

      BigInt 也可以用于类型 Int, Long

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-18
        • 2012-01-31
        • 1970-01-01
        • 2011-08-01
        • 1970-01-01
        • 2011-05-05
        • 1970-01-01
        • 2022-06-16
        相关资源
        最近更新 更多