let solve() =
let permutation k ls =
let rec p a b = function
| _, [] | 0, _ -> a::b
| k, ls -> List.fold (fun x y -> p (y::a) x (k - 1, List.filter ((<>) y) ls)) b ls
p [] [] (k, ls)
let rec gcd = function x, 0 -> x | x, y -> gcd (y, x % y)
let add x xs =
seq { for i in 0 .. List.length xs ->
[Seq.take i xs; Seq.singleton x; Seq.skip i xs] |> Seq.concat |> Seq.toList }
let toNumbers x = add x >> Seq.map (List.reduce (fun x y -> x * 10 + y))
let toDigits = Seq.unfold (function 0 -> None | x -> Some(x % 10, x / 10)) >> Seq.sort >> Seq.toList
let digits = set [1 .. 9]
[for d in 2 .. 9 do
for n in 1 .. d - 1 do
if gcd (d, n) = 1 then yield! [for k in 1 .. 7 -> (n, d, k)]]
|> Seq.collect (fun (n, d, k) ->
digits
|> Set.
remove n
|> Set.
remove d
|> Set.
toList |> permutation k
|> Seq.collect (fun ps ->
let ds = d::ps |> List.sort
ps |> toNumbers n |> Seq.choose (fun nf -> if nf % n = 0 then Some(nf, nf / n * d) else None)
|> Seq.filter (fun (nf, df) -> let g = gcd (df, nf) in nf / g = n && df / g = d && toDigits df = ds)))
bGV0IHNvbHZlKCkgPQogICAgbGV0IHBlcm11dGF0aW9uIGsgbHMgPQogICAgICAgIGxldCByZWMgcCBhIGIgPSBmdW5jdGlvbgogICAgICAgICAgICB8IF8sIFtdIHwgMCwgXyAtPiBhOjpiCiAgICAgICAgICAgIHwgaywgbHMgLT4gTGlzdC5mb2xkIChmdW4geCB5IC0+IHAgKHk6OmEpIHggKGsgLSAxLCBMaXN0LmZpbHRlciAoKDw+KSB5KSBscykpIGIgbHMKICAgICAgICBwIFtdIFtdIChrLCBscykKICAgIGxldCByZWMgZ2NkID0gZnVuY3Rpb24geCwgMCAtPiB4IHwgeCwgeSAtPiBnY2QgKHksIHggJSB5KQogICAgbGV0IGFkZCB4IHhzID0KICAgICAgICBzZXEgeyBmb3IgaSBpbiAwIC4uIExpc3QubGVuZ3RoIHhzIC0+CiAgICAgICAgICAgICAgICBbU2VxLnRha2UgaSB4czsgU2VxLnNpbmdsZXRvbiB4OyBTZXEuc2tpcCBpIHhzXSB8PiBTZXEuY29uY2F0IHw+IFNlcS50b0xpc3QgfQogICAgbGV0IHRvTnVtYmVycyB4ID0gYWRkIHggPj4gU2VxLm1hcCAoTGlzdC5yZWR1Y2UgKGZ1biB4IHkgLT4geCAqIDEwICsgeSkpCiAgICBsZXQgdG9EaWdpdHMgPSBTZXEudW5mb2xkIChmdW5jdGlvbiAwIC0+IE5vbmUgfCB4IC0+IFNvbWUoeCAlIDEwLCB4IC8gMTApKSA+PiBTZXEuc29ydCA+PiBTZXEudG9MaXN0CiAgICBsZXQgZGlnaXRzID0gc2V0IFsxIC4uIDldCiAgICBbZm9yIGQgaW4gMiAuLiA5IGRvCiAgICAgZm9yIG4gaW4gMSAuLiBkIC0gMSBkbwogICAgICAgIGlmIGdjZCAoZCwgbikgPSAxIHRoZW4geWllbGQhIFtmb3IgayBpbiAxIC4uIDcgLT4gKG4sIGQsIGspXV0KICAgIHw+IFNlcS5jb2xsZWN0IChmdW4gKG4sIGQsIGspIC0+CiAgICAgICAgZGlnaXRzIHw+IFNldC5yZW1vdmUgbiB8PiBTZXQucmVtb3ZlIGQgfD4gU2V0LnRvTGlzdCB8PiBwZXJtdXRhdGlvbiBrCiAgICAgICAgfD4gU2VxLmNvbGxlY3QgKGZ1biBwcyAtPgogICAgICAgICAgICBsZXQgZHMgPSBkOjpwcyB8PiBMaXN0LnNvcnQKICAgICAgICAgICAgcHMgfD4gdG9OdW1iZXJzIG4gfD4gU2VxLmNob29zZSAoZnVuIG5mIC0+IGlmIG5mICUgbiA9IDAgdGhlbiBTb21lKG5mLCBuZiAvIG4gKiBkKSBlbHNlIE5vbmUpCiAgICAgICAgICAgIHw+IFNlcS5maWx0ZXIgKGZ1biAobmYsIGRmKSAtPiBsZXQgZyA9IGdjZCAoZGYsIG5mKSBpbiBuZiAvIGcgPSBuICYmIGRmIC8gZyA9IGQgJiYgdG9EaWdpdHMgZGYgPSBkcykpKQo=