長さ1からはじめて、N/2までのパターンを列挙します。
1 : [ 0 ]
次に長さ2ですが、0に長さ2をあてはめます。[ 0, 0 ]は特別として、0が続いてそこから0以外が続く、というのは[ 0, 1 ]のみです。[ 0, 2 ]のような抜けがあるというのは無しです。
2 : [ 0, 0 ], [ 0, 1 ]
3も同じで、
3 : [ 0, 0, 0 ], [ 0, 0, 1 ], [ 0, 1, 1 ], [ 0, 1, 2 ], [ 0, 2, 1 ]
4もまずは1に長さ4をあてはめるパターンがあって、[ 0, 0, 0, 0 ], ... , [ 0, 3, 2, 1 ]です。それと長さ2に2つずつあてはめる方法もあります。[ 0, 0 ]は[ 0, 1, 0, 1 ]しかありません。[ 0, 1 ]も[ 0, 1, 0, 2 ]のみです。
4 : [ 0, 0, 0, 0 ], ... , [ 0, 3, 2, 1 ], [ 0, 1, 0, 1 ], [ 0, 1, 0, 2 ]
前回の手順で縮約してみるとわかりやすいかもしれません。
このように、再帰的に各長さのパターンが全て求められます。
これに分配した長さを、今度は[ 0, 1, 2, ... ]ではなく[ 1, 3, 7, 9 ]であてはめます。
次のコードはひどいので見ないでください。相当苦労しています。N = 6までは確認しました。
def is_prime(n :Int) = Iterator.from(2).takeWhile(m => m * m <= n).forall(n % _ != 0) def number(a :List[Int]) = a.foldLeft(0)(_ * 10 + _) def pow(n :Int, e :Int) = Iterator.range(0, e).foldLeft(1)((x, y) => x * n) // aより大きい長さlen以下のリストを生成する def gen_greater(a :List[Int], ds :List[Int], len :Int) = { // eq : aとここまで等しいか first : 最小の数字が続いているか def gen(b :List[Int], res :Int, eq :Boolean, first :Boolean) :Iterator[List[Int]] = { val ds2 = (if(b == Nil) if(first) ds else ds.tail else if(eq) ds.filter(b.head <=) else ds.tail).toIterator val it = (b, res, first) match { case (_, 0, _) => Iterator() case (Nil, _, _) => for(d <- ds2; c <- gen(Nil, res - 1, false, d == ds.head)) yield d :: c case (h :: t, _, _) => for(d <- ds2; c <- gen(t, res - 1, eq && d == h, d == ds.head)) yield d :: c } if(eq || first) it else Iterator(Nil) ++ it } val tail = if(a == Nil) Nil else a.tail gen(tail, len - 1, a != Nil, true).map(ds.head :: _) } def is_less_jump(a :List[Int]) = { val b = a.foldLeft(0)((x, y) => x | (1 << y)) (b & (b + 1)) == 0 } def count_freq(a :List[Int]) = { val b = new Array[Int](a.max + 1) for(i <- a) b(i) += 1 b.toList } def repeat(d :Int, n :Int) = Iterator.range(0, n).foldLeft(Nil :List[Int])((x, y) => d :: x) def divide(freq :List[Int], n :Int) :Iterator[List[Int]] = freq match { case Nil => Iterator() case h :: Nil if n % h == 0 && n / h >= 2 => Iterator(List(n / h)) case h :: Nil => Iterator() case h :: t => for(m <- Iterator.range(2, n / h + 1); a <- divide(t, n - h * m)) yield m :: a } //def extend(a :List[Int], len :Int) :Iterator[List[Int]] = { // val freq = count_freq(a) // val ds = List.range(0, len - a.size + 1) // for(ns <- divide(freq, len); // bs <- extend_core(Nil, ds, ns)) // yield bs.map(b => a.foldLeft(List[Int]())(_ ++ b(_))).filter(is_less_jump) //} def extend(a :List[Int], len :Int) :Iterator[List[Int]] = { val freq = count_freq(a) val ds = List.range(0, len - a.size + 1) val bs = extend_core(Nil, ds, a.max + 1, len) bs.map(b => a.foldLeft(List[Int]())(_ ++ b(_))).filter(is_less_jump) } def extend_core(b :List[Int], ds :List[Int], n :Int, res_len :Int) :Iterator[List[List[Int]]] = if(n == 1) gen_greater(b, ds, res_len).map(x => List(x)) else for(m <- Iterator.range(2, res_len - 2 * n + 3); c <- gen_greater(b, ds, m); cs <- extend_core(c, ds, n - 1, res_len - m)) yield c :: cs // 最後用 def extend2(a :List[Int], ds :List[Int], ns :List[Int]) :Iterator[List[Int]] = { val freq = count_freq(a) val bs = extend_core2(Nil, ds, ns) bs.map(b => a.foldLeft(List[Int]())(_ ++ b(_))) } def extend_core2(b :List[Int], ds :List[Int], ns :List[Int]) :Iterator[List[List[Int]]] = ns match { case Nil => Iterator(Nil) case (n :: t) => for(c <- gen_greater(b, ds, n).filter(c => c.size == n); cs <- extend_core2(c, ds, t)) yield c :: cs } def gen_min_rotate(N :Int) :Iterator[Int] = { val M = N / 2 val a = new Array[List[List[Int]]](M + 1) a(1) = List(List(0)) for(i <- Iterator.range(2, M + 1)) { a(i) = Iterator.range(1, i / 2 + 1). map(k => a(k).map(b => extend(b, i))). reduceLeft(_ ++ _).reduceLeft(_ ++ _).toList a(i) = a(i) ++ List(repeat(0, i)) a(i) = a(i).filter(x => x.size == i) } val it = for(d <- Iterator(1, 3, 7, 9); n <- Iterator.range(2, N + 1)) yield (pow(10, n) - 1) / 9 * d for(n <- Iterator.range(2, N + 1); ds <- List(1, 3, 7, 9).tails.take(4); i <- Iterator.range(1, n / 2 + 1); b <- a(i); freq = count_freq(b); ns <- divide(freq, n); c <- extend2(b, ds, ns)) println (number(c), n, ds, i, b, freq, ns) val it2 = for(n <- Iterator.range(2, N + 1); ds <- List(1, 3, 7, 9).tails.take(4); i <- Iterator.range(1, n / 2 + 1); b <- a(i); freq = count_freq(b); ns <- divide(freq, n); c <- extend2(b, ds, ns)) yield number(c) it ++ it2 } def is_min_rotate(a :List[Int]) = { val front = number(a) val it = Iterator.iterate(a)(rotate).slice(1, a.size).map(number) it.forall(front <=) } def rotate(a :List[Int]) = a.tail ++ List(a.head) def digits(n :Int) :List[Int] = if(n == 0) Nil else (n % 10) :: digits(n / 10) val N = 6 val a = gen_min_rotate(N) println (a.sum)