(defun permutations (bag) "Return a list of all the permutations of the input." ;; If the input is nil, there is only one permutation: ;; nil itself (if (null bag) '(()) ;; Otherwise, take an element, e, out of the bag. ;; Generate all permutations of the remaining elements, ;; And add e to the front of each of these. ;; Do this for all possible e to generate all permutations. (mapcan #'(lambda (e) (mapcar #'(lambda (p) (cons e p)) (permutations (remove e bag :count 1)))) bag))) #### sub is_empty_list { return @{$_[0]} == 0; } # remove ($what, $list, $howmany) # # Removes $what from the list $list up to $howmany times. # If $howmany is not provided, removes all occurrences of $what. # sub remove { my $what = $_[0]; my $list = $_[1]; my $howmany = defined $_[2] ? $_[2] : -1; my @ret = (); foreach my $elem (@{$list}) { push @ret, $elem unless ($elem == $what and $howmany-- > 0); } return \@ret; } #### sub permutations { my $bag = $_[0]; if (is_empty_list($bag)) { return [[]]; } my $perms = []; foreach my $elem (@$bag) { foreach my $perm (@{permutations(remove($elem, $bag, 1))}) { unshift(@{$perm}, $elem); push(@{$perms}, $perm); } } return $perms; }