val sqCache
= (1 to
1000).
map(n
=> (Tuple2
(n
*n,
true))).
toMap def isSq
(n
:Int
):Boolean
= { sqCache.
getOrElse(n,
false) }
def helper
(cand
:List
[Int
], digits
:List
[Int
], c
:List
[Int
]):List
[Int
] = { case Nil
=> Nil
// たして平方数となる数が無いので Nil val d
= explore
(x, digits.
filter(v
=>{v
!=x
}), c
) // 題意を満す(=Nil でない)解があればそれを返し、
// なければ次の候補を探索
if (d
!=Nil
) {d
} else helper
(xs, digits, c
) }
}
}
def explore
(me
:Int, digits
:List
[Int
], c
:List
[Int
]):List
[Int
] = { // 1 から nまでの数を全て使い切れたので、
// 先頭と最終を足しても平方数ならそれが解。
// 平方数でなければ Nil とする
if(isSq
(me + c.
last)){me
::c
} else {Nil
} // たして平方数となる候補を抽出して、
// 題意をみたす切り方ができるか探索
val candidates
= digits.
filter(n
=> isSq
(me+n
)) helper(candidates, digits, me::c)
}
}
def solve
(n
:Int
= 2):Tuple2
[Int, List
[Int
]] = { val q
= explore
(1,
(2 to n
).
toList, Nil
) if (q
!=Nil
){Tuple2
(n, q
)} else {solve
(n+
1)} }
}
println("%d: %s".format(ret._1, ret._2.reverse.mkString(",")))
}
b2JqZWN0IE1haW4gZXh0ZW5kcyBBcHAgewoKb2JqZWN0IFExMTE5ewoKICB2YWwgc3FDYWNoZSA9ICgxIHRvIDEwMDApLm1hcChuID0+IChUdXBsZTIobipuLCB0cnVlKSkpLnRvTWFwCiAgZGVmIGlzU3EobjpJbnQpOkJvb2xlYW4gPSB7CiAgICBzcUNhY2hlLmdldE9yRWxzZShuLCBmYWxzZSkKICB9CgogIGRlZiBoZWxwZXIoY2FuZDpMaXN0W0ludF0sIGRpZ2l0czpMaXN0W0ludF0sIGM6TGlzdFtJbnRdKTpMaXN0W0ludF0gPSB7CiAgICBjYW5kIG1hdGNoIHsKICAgICAgY2FzZSBOaWwgPT4gTmlsIC8vIOOBn+OBl+OBpuW5s+aWueaVsOOBqOOBquOCi+aVsOOBjOeEoeOBhOOBruOBpyBOaWwKICAgICAgY2FzZSB4Ojp4cyA9PiB7CiAgICAgICAgdmFsIGQgPSBleHBsb3JlKHgsIGRpZ2l0cy5maWx0ZXIodj0+e3YhPXh9KSwgYykKICAgICAgICAvLyDpoYzmhI/jgpLmuoDjgZkoPU5pbCDjgafjgarjgYQp6Kej44GM44GC44KM44Gw44Gd44KM44KS6L+U44GX44CBCiAgICAgICAgLy8g44Gq44GR44KM44Gw5qyh44Gu5YCZ6KOc44KS5o6i57SiCiAgICAgICAgaWYgKGQhPU5pbCkge2R9IGVsc2UgaGVscGVyKHhzLCBkaWdpdHMsIGMpCiAgICAgIH0KICAgIH0KICB9CiAgZGVmIGV4cGxvcmUobWU6SW50LCBkaWdpdHM6TGlzdFtJbnRdLCBjOkxpc3RbSW50XSk6TGlzdFtJbnRdID0gewogICAgaWYgKGRpZ2l0cz09TmlsKXsKICAgICAgLy8gMSDjgYvjgokgbuOBvuOBp+OBruaVsOOCkuWFqOOBpuS9v+OBhOWIh+OCjOOBn+OBruOBp+OAgQogICAgICAvLyDlhYjpoK3jgajmnIDntYLjgpLotrPjgZfjgabjgoLlubPmlrnmlbDjgarjgonjgZ3jgozjgYzop6PjgIIKICAgICAgLy8g5bmz5pa55pWw44Gn44Gq44GR44KM44GwIE5pbCDjgajjgZnjgosKICAgICAgaWYoaXNTcShtZSArIGMubGFzdCkpe21lOjpjfSBlbHNlIHtOaWx9CiAgICB9IGVsc2UgewogICAgICAvLyDjgZ/jgZfjgablubPmlrnmlbDjgajjgarjgovlgJnoo5zjgpLmir3lh7rjgZfjgabjgIEKICAgICAgLy8g6aGM5oSP44KS44G/44Gf44GZ5YiH44KK5pa544GM44Gn44GN44KL44GL5o6i57SiCiAgICAgIHZhbCBjYW5kaWRhdGVzID0gZGlnaXRzLmZpbHRlcihuID0+IGlzU3EobWUrbikpCiAgICAgIGhlbHBlcihjYW5kaWRhdGVzLCBkaWdpdHMsIG1lOjpjKQogICAgfQogIH0KCgogIGRlZiBzb2x2ZShuOkludCA9IDIpOlR1cGxlMltJbnQsIExpc3RbSW50XV0gPSB7CiAgICB2YWwgcSA9IGV4cGxvcmUoMSwgKDIgdG8gbikudG9MaXN0LCBOaWwpCiAgICBpZiAocSE9TmlsKXtUdXBsZTIobiwgcSl9IGVsc2Uge3NvbHZlKG4rMSl9CiAgfQp9Cgp2YWwgcmV0ID0gUTExMTkuc29sdmUoKQpwcmludGxuKCIlZDogJXMiLmZvcm1hdChyZXQuXzEsIHJldC5fMi5yZXZlcnNlLm1rU3RyaW5nKCIsIikpKQp9