ScalaでProject Euler(59)

Problem 32

この問題は9の剰余で考えるとかなり絞れるのですが、めんどうなので省略です。

10進の各桁を列挙するIteratorは次のように書けます。

def digits(n :Int) :Iterator[Int] =
    if(n == 0) Iterator() else Iterator(n % 10) ++ digits(n / 10)

その上でこう書くと、桁の途中で数字の重複検出できます。

    val it = digits(m) ++ digits(n) ++ digits(m * n)

今のところ、だいたいIteratorを使うとうまく行くようです。

def digits(n :Int) :Iterator[Int] =
    if(n == 0) Iterator() else Iterator(n % 10) ++ digits(n / 10)

def is_pandigital(m :Int, n :Int) = {
    def add_flag(f :Int, it :Iterator[Int]) :Boolean =
        if(!it.hasNext)
            true
        else {
            val d = it.next
            if((f & (1 << d)) == 0)
                add_flag(f | (1 << d), it)
            else
                false
        }
    
    val it = digits(m) ++ digits(n) ++ digits(m * n)
    add_flag(1, it)
}

val v1 = for(m <- 1 to 9; n <- 1000 to 10000 / m if is_pandigital(m, n))
            yield m * n
val v2 = for(m <- 10 to 99; n <- 100 to 10000 / m if is_pandigital(m, n))
            yield m * n
println ((v1 ++ v2).toSet.sum)