let rec take_while f xs =
match xs with
| [] -> []
| x :: rest -> if f x
then x :: take_while f rest
else []
let rec drop_while f xs =
match xs with
| [] -> []
| x :: rest -> if f x
then drop_while f rest
else xs
let span f xs = (take_while f xs, drop_while f xs)
let string_to_char_list s =
let rec string_to_char_list_impl i l =
if i < 0
then l
else string_to_char_list_impl (i - 1) (s.[i] :: l) in
string_to_char_list_impl
(String.length s
- 1) []
let char_list_to_string cs =
let next_permutation word =
let rec next_permutation_impl char_list =
match char_list with
| x0 :: rest0 ->
(match next_permutation_impl rest0 with
| (true, rest1) -> (true, x0 :: rest1)
| (false, rest1) ->
(match rest1 with
| [] -> (false, x0 :: rest1)
| x1 :: _ ->
if x0 < x1
then
let (left, right) = span (fun x -> x > x0) rest1 in
let chunk =
(match (List.rev left
) with | [] -> List.concat
[[x0
]; right
] | l
:: revLeft
-> List.concat
[[l
]; List.rev revLeft
; [x0
]; right
]) in (match chunk with
| (x2
:: rest2
) -> (true, x2
:: List.rev rest2
) else (false, x0 :: rest1)))
| [] -> (false, [])
in
let char_list = string_to_char_list word in
match next_permutation_impl char_list with
| (true, result) -> Some (char_list_to_string result)
| _ -> None
bGV0IHJlYyB0YWtlX3doaWxlIGYgeHMgPSAKICBtYXRjaCB4cyB3aXRoCiAgfCBbXSAtPiBbXQogIHwgeCA6OiByZXN0IC0+IGlmIGYgeAogICAgICAgICAgICAgICAgIHRoZW4geCA6OiB0YWtlX3doaWxlIGYgcmVzdAogICAgICAgICAgICAgICAgIGVsc2UgW10KCmxldCByZWMgZHJvcF93aGlsZSBmIHhzID0gCiAgbWF0Y2ggeHMgd2l0aAogIHwgW10gLT4gW10KICB8IHggOjogcmVzdCAtPiBpZiBmIHgKICAgICAgICAgICAgICAgICB0aGVuIGRyb3Bfd2hpbGUgZiByZXN0CiAgICAgICAgICAgICAgICAgZWxzZSB4cwoKbGV0IHNwYW4gZiB4cyA9ICh0YWtlX3doaWxlIGYgeHMsIGRyb3Bfd2hpbGUgZiB4cykKCmxldCBzdHJpbmdfdG9fY2hhcl9saXN0IHMgPQogIGxldCByZWMgc3RyaW5nX3RvX2NoYXJfbGlzdF9pbXBsIGkgbCA9CiAgICBpZiBpIDwgMCAKICAgIHRoZW4gbCAKICAgIGVsc2Ugc3RyaW5nX3RvX2NoYXJfbGlzdF9pbXBsIChpIC0gMSkgKHMuW2ldIDo6IGwpIGluCiAgc3RyaW5nX3RvX2NoYXJfbGlzdF9pbXBsIChTdHJpbmcubGVuZ3RoIHMgLSAxKSBbXQoKbGV0IGNoYXJfbGlzdF90b19zdHJpbmcgY3MgPSAKICBTdHJpbmcuY29uY2F0ICIiIChMaXN0Lm1hcCAoZnVuIHggLT4gU3RyaW5nLm1ha2UgMSB4KSBjcykKCmxldCBuZXh0X3Blcm11dGF0aW9uIHdvcmQgPSAKICBsZXQgcmVjIG5leHRfcGVybXV0YXRpb25faW1wbCBjaGFyX2xpc3QgPQogICAgbWF0Y2ggY2hhcl9saXN0IHdpdGgKICAgIHwgeDAgOjogcmVzdDAgLT4gCiAgICAgICAobWF0Y2ggbmV4dF9wZXJtdXRhdGlvbl9pbXBsIHJlc3QwIHdpdGgKICAgICAgICB8ICh0cnVlLCByZXN0MSkgLT4gKHRydWUsIHgwIDo6IHJlc3QxKQogICAgICAgIHwgKGZhbHNlLCByZXN0MSkgLT4gCiAgICAgICAgICAgKG1hdGNoIHJlc3QxIHdpdGgKICAgICAgICAgICAgfCBbXSAtPiAoZmFsc2UsIHgwIDo6IHJlc3QxKQogICAgICAgICAgICB8IHgxIDo6IF8gLT4KICAgICAgICAgICAgICAgaWYgeDAgPCB4MQogICAgICAgICAgICAgICB0aGVuIAogICAgICAgICAgICAgICAgIGxldCAobGVmdCwgcmlnaHQpID0gc3BhbiAoZnVuIHggLT4geCA+IHgwKSByZXN0MSBpbgogICAgICAgICAgICAgICAgIGxldCBjaHVuayA9IAogICAgICAgICAgICAgICAgICAgKG1hdGNoIChMaXN0LnJldiBsZWZ0KSB3aXRoCiAgICAgICAgICAgICAgICAgICAgfCBbXSAtPiBMaXN0LmNvbmNhdCBbW3gwXTsgcmlnaHRdCiAgICAgICAgICAgICAgICAgICAgfCBsIDo6IHJldkxlZnQgLT4gTGlzdC5jb25jYXQgW1tsXTsgTGlzdC5yZXYgcmV2TGVmdDsgW3gwXTsgcmlnaHRdKQogICAgICAgICAgICAgICAgIGluIChtYXRjaCBjaHVuayB3aXRoCiAgICAgICAgICAgICAgICAgICAgIHwgKHgyIDo6IHJlc3QyKSAtPiAodHJ1ZSwgeDIgOjogTGlzdC5yZXYgcmVzdDIpCiAgICAgICAgICAgICAgICAgICAgIHwgW10gLT4gcmFpc2UgKEZhaWx1cmUgIkZ1Y2siKSkKICAgICAgICAgICAgICAgZWxzZSAoZmFsc2UsIHgwIDo6IHJlc3QxKSkpCiAgICB8IFtdIC0+IChmYWxzZSwgW10pCiAgaW4KICBsZXQgY2hhcl9saXN0ID0gc3RyaW5nX3RvX2NoYXJfbGlzdCB3b3JkIGluCiAgbWF0Y2ggbmV4dF9wZXJtdXRhdGlvbl9pbXBsIGNoYXJfbGlzdCB3aXRoCiAgfCAodHJ1ZSwgcmVzdWx0KSAtPiBTb21lIChjaGFyX2xpc3RfdG9fc3RyaW5nIHJlc3VsdCkKICB8IF8gLT4gTm9uZQo=