skiminok: (xkcd)
skiminok ([personal profile] skiminok) wrote2010-10-10 03:26 pm
Entry tags:

Еще один красивый пример

Боянистый, правда, до ужаса, но тем не менее красивый.

Взять список чисел на входе. Вернуть на выходе список списков: все перестановки заданных чисел.
Иллюстрирует:
  • List comprehensions
  • Правую свертку
  • Композицию функций
Если бы авторы F# изгнали мочу из головы и поставили, как все нормальные люди, аргумент-список в foldBack на последнее место, то иллюстрировал бы еще и частичное применение / карринг. (Правда, для этого потребуется изгнать мочу и из компилятора, а то получим радостный Value restriction, будь он неладен.)
Будучи дословно переведенным на Haskell, иллюстрирует ленивую генерацию списка. На F# для этого потребуется seq, который некрасиво пишется :-)

 let permute xs =
     let rec insert x = function 
         | [] -> [[x]]
         | y::ys -> (x::y::ys)::[for res in insert x ys -> y::res]
     List.foldBack (insert >> List.collect) xs [[]]

Работа:

> permute [1..4];;
val it : int list list =
  [[1; 2; 3; 4]; [2; 1; 3; 4]; [2; 3; 1; 4]; [2; 3; 4; 1]; [1; 3; 2; 4];
   [3; 1; 2; 4]; [3; 2; 1; 4]; [3; 2; 4; 1]; [1; 3; 4; 2]; [3; 1; 4; 2];
   [3; 4; 1; 2]; [3; 4; 2; 1]; [1; 2; 4; 3]; [2; 1; 4; 3]; [2; 4; 1; 3];
   [2; 4; 3; 1]; [1; 4; 2; 3]; [4; 1; 2; 3]; [4; 2; 1; 3]; [4; 2; 3; 1];
   [1; 4; 3; 2]; [4; 1; 3; 2]; [4; 3; 1; 2]; [4; 3; 2; 1]]

Хорошее упражнение: посчитать сложность работы permute ;)

[identity profile] xonixx.livejournal.com 2010-10-11 05:23 pm (UTC)(link)
вариант на mercury используя backtracking

:- module perm.

:- interface.

:- import_module io.

:- pred main(io, io).
:- mode main(di, uo) is det.

:- implementation.

:- import_module list, solutions.

appendl([]) = [].
appendl([H]) = H.
appendl([H1,H2|T]) = appendl([append(H1, H2)|T]).

:- mode permut(in, out) is multi.
permut([], []).
permut([H | T], appendl([A, [H], B])) :-
permut(T, Pt),
append(A, B, Pt).

main -->
{ solutions(permut(1..5), Perms) },
print(Perms).

результат

>perm
[[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3,
2], [2, 1, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4
, 3, 1], [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1], [3, 4, 1, 2], [
3, 4, 2, 1], [4, 1, 2, 3], [4, 1, 3, 2], [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2
], [4, 3, 2, 1]]