Discussion:
permutation in Functional programming language
(too old to reply)
coolkid
2008-12-28 07:02:52 UTC
Permalink
I've begin to study Function programming language. I'm writing the
function, input is an array a, ouput is an array which each element is
a permutation of array a.
ex:
[1,2,3] -> [[1,2,3],[1,3,2],[2,1,3],....]
Someone have any idea about this function?
Vincent Zweije
2008-12-28 09:35:17 UTC
Permalink
In article
<0774f63c-c60e-49d4-b0ee-***@p2g2000prf.googlegroups.com>,
coolkid <***@gmail.com> wrote:

|| I've begin to study Function programming language. I'm writing the
|| function, input is an array a, ouput is an array which each element is
|| a permutation of array a.
|| ex:
|| [1,2,3] -> [[1,2,3],[1,3,2],[2,1,3],....]
|| Someone have any idea about this function?

Hint, consider this list:

[[[1,2,3],[1,3,2]],[[2,1,3],[2,3,1]],[[3,1,2],[3,2,1]]]

Ciao. Vincent.
--
Vincent Zweije <***@xs4all.nl> | "If you're flamed in a group you
<http://www.xs4all.nl/~zweije/> | don't read, does anybody get burnt?"
[Xhost should be taken out and shot] | -- Paul Tomblin on a.s.r.
coolkid
2008-12-28 10:41:32 UTC
Permalink
can you explain more?
Dirk Thierbach
2008-12-28 13:32:30 UTC
Permalink
Post by coolkid
can you explain more?
Homework? :-)

If you want all permutation of an n-element list, would it help
you if you already knew how to construct all permutations of an
(n-1)-element list?

- Dirk
coolkid
2008-12-28 14:25:42 UTC
Permalink
Post by Dirk Thierbach
Post by coolkid
can you explain more?
Homework? :-)
If you want all permutation of an n-element list, would it help
you if you already knew how to construct all permutations of an
(n-1)-element list?
- Dirk
Yeah, I knew the recursive algorithm in imperative language. But, i
have a problem when change it into functional programming
Dirk Thierbach
2008-12-28 20:11:52 UTC
Permalink
Post by coolkid
Yeah, I knew the recursive algorithm in imperative language.
Could you describe the algorithm again in your own words? (That really
helps to get started).
Post by coolkid
But, i have a problem when change it into functional programming
Where exactly is the problem? What have you tried, what worked,
what didn't work, where are you stuck?

- Dirk
coolkid
2008-12-29 03:03:14 UTC
Permalink
Post by Dirk Thierbach
Post by coolkid
Yeah, I knew the recursive algorithm in imperative language.
Could you describe the algorithm again in your own words? (That really
helps to get started).
Post by coolkid
But, i have a problem when change it into functional programming
Where exactly is the problem? What have you tried, what worked,
what didn't work, where are you stuck?
- Dirk
first, The recursive algorithm here is if we want to know the
permutations of array A, we will join each element of array A which
has n elements with the permutation of the array B which has other n-1
elements of array A. Is it right? :-/.
But In the functional programming concept, I don't know the way how to
take out each element of array A in the recursive way
Dirk Thierbach
2008-12-29 10:51:16 UTC
Permalink
Post by coolkid
first, The recursive algorithm here is if we want to know the
permutations of array A, we will join each element of array A which
has n elements with the permutation of the array B which has other n-1
elements of array A. Is it right? :-/.
Ok. That means given a list A (lists are more natural in FP),
you will need to split this list for each element into the element
itself and the rest B. Assume we have a function that does that,
say "splitUp". What's the type signature of this function?

While we're at it, let's call the main function "perms". What's
its type signature?

Given "splitUp", how exactly do you combine the results of
the recursive call in the definition of "perms"?

(I think you didn't say which language you want to use, but for
example in Haskell, one nice way to write this down would be to
use list comprehensions).

- Dirk
coolkid
2008-12-29 03:54:36 UTC
Permalink
Post by Dirk Thierbach
Post by coolkid
Yeah, I knew the recursive algorithm in imperative language.
Could you describe the algorithm again in your own words? (That really
helps to get started).
Post by coolkid
But, i have a problem when change it into functional programming
Where exactly is the problem? What have you tried, what worked,
what didn't work, where are you stuck?
- Dirk
first, The recursive algorithm here is if we want to know the
permutations of array A, we will join each element of array A which
has n elements with the permutation of the array B which has other n-1
elements of array A. Is it right? :-/.
But In the functional programming concept, I don't know the way how to
take out each element of array A in the recursive way
William James
2008-12-29 11:34:14 UTC
Permalink
Post by Dirk Thierbach
Post by coolkid
can you explain more?
Homework? :-)
If you want all permutation of an n-element list, would it help
you if you already knew how to construct all permutations of an
(n-1)-element list?
Ruby:

def permute array
return array if array.size < 2
result = []
array.each{|first|
permute(array - [first]).each{|rest|
result << [first, rest].flatten } }
result
end

p permute( [] )
p permute( [2] )
p permute( [2,3] )
p permute( [1,2,3] )
p permute( [2,3,4,5] )
Dirk Thierbach
2008-12-29 15:29:42 UTC
Permalink
Post by Dirk Thierbach
Homework? :-)
[Ruby solution]
Giving "coolkid" a complete solution won't help him to learn
functional programming. The point of the exercise is to push him
into a position where he can write down the program himself.

Yes, that takes some amount of effort on his part.

- Dirk
coolkid
2008-12-30 08:16:38 UTC
Permalink
Post by Dirk Thierbach
Post by Dirk Thierbach
Homework? :-)
[Ruby solution]
Giving "coolkid" a complete solution won't help him to learn
functional programming. The point of the exercise is to push him
into a position where he can write down the program himself.
Yes, that takes some amount of effort on his part.
- Dirk
Now I can solve the problem.
I don't study FP in any specific langugage. I just study the
"thinking" first
I've solve the problem as this

array permut(array a)
return length(a)==1? [first(a)] : con( concat(first(a), permut(rest
(a))) ,
concatnat(rest(a),change(first
(rest(a)), a))
)


array concatnat(array a, array b)
return length(a)==1? a : con( concat(first(a), permut(rest(b))) ,
concatnat(rest(a), change(first(rest
(a)), a))
)

con(array a, array b) is the function join 2 array
concat(int a, array b) is the function insert a into first index of
evey element of array b
i.e:
b = [[1,2] , [1,3]]
concat(4, b) = [[4,1,2] , [4,1,3]]
concatnat(array a, array b) is the function do concat function with
all element of array a to array b :)
i.e:
b = [[1,2] , [1,3]]
a = [4,5]
concatnat(a,b) = [[4,1,2] , [4,1,3] , [5,1,2] , [5,1,3]]

change(int a, array b) is the function move the int a in array b to
first index

Is the algorithm right?
Dirk Thierbach
2008-12-30 12:26:32 UTC
Permalink
Post by coolkid
Now I can solve the problem.
I don't study FP in any specific langugage. I just study the
"thinking" first
Ok, but using a concrete language helps to fix the notation :-)
Post by coolkid
con(array a, array b) is the function join 2 array
Again: in FP one usually thinks in "lists" -- the difference to arrays
is that there is no constant-time access to the n-th element (and
in a pure language, one cannot update an element, either).

Just so you see some notation in a concrete language, in e.g. Haskell
this function is an infix operator (++), as in

Prelude> [1,2,3] ++ [4,5,6]
[1,2,3,4,5,6]
Post by coolkid
concat(int a, array b) is the function insert a into first index of
evey element of array b
That function won't be a primitive in most languages. Again in Haskell,
one could implement it with a list comprehension:

concat x yss = [x:ys | ys <- yss]

where : puts a single element in front of a list. Read this similar
to a "set comprehension" in mathematics, i.e.

The list of all "x:ys" for all elements ys in the list yss

In Haskell, the type of a list is denoted by square brackets, so
"[Integer]" is a list of Integers. If the concrete type does not matter,
one can use type variables (which start in lower case). The type of
concat is

concat :: a -> [[a]] -> [[a]]

That means, the first argument can be any type (including an integer),
the second argument must be a list of lists of this type, and the
result is again a list of lists of this type. Note that this is both
more general than your type (it's not restricted to integers) and
more specific (the second argument is not just any array).
Post by coolkid
b = [[1,2] , [1,3]]
concat(4, b) = [[4,1,2] , [4,1,3]]
Test in ghci:

Prelude> let concat x yss = [x:ys | ys <- yss]
Prelude> :t concat
concat :: a -> [[a]] -> [[a]]
Prelude> concat 4 [[1,2], [1,3]]
[[4,1,2],[4,1,3]]
Post by coolkid
concatnat(array a, array b) is the function do concat function with
all element of array a to array b :)
Again, that's not primitive, but can be implemented in a similar
way (exercise :-).

Also, I assume the code you gave for "concatnat" is a copy-and-paste
error, because it doesn't match this description.
Post by coolkid
change(int a, array b) is the function move the int a in array b to
first index
That assumes that you can identify the integer in the array (by
equality), and will fail if your array consists of elements that
cannot be compare (functions, for example).

Moreover, if you want to use that function, that means that now
you have an algorithm different to the one we discussed before.
Post by coolkid
array permut(array a)
return length(a)==1? [first(a)] : con( concat(first(a), permut(rest
(a))) ,
concatnat(rest(a),change(first
(rest(a)), a))
)
Is the algorithm right?
There's a type error in your case for length one: The result must be
a list of lists, so you don't return the first (and only) element of
"a", but the whole list instead.

Also, in FP it's more convenient to do the case distinction for an
empty list (what should the result be in this case)?

Finally, I can guess what you want to do, but I don't think it will
work quite in this way, given that I understood your "concatnat"
correctly.

So there are two things unfinished:

1) Implement the above algorithm correctly; and
2) Implement the (different) algorithm from the other posting.

I also recommend using a concrete FP language (no matter which one),
in this way, you can test out that it really works. With ad-hoc
notation and handwaving, it's easy to make mistakes.

- Dirk
Torben Ægidius Mogensen
2009-01-06 11:15:21 UTC
Permalink
Post by Dirk Thierbach
Post by coolkid
concat(int a, array b) is the function insert a into first index of
evey element of array b
That function won't be a primitive in most languages. Again in Haskell,
concat x yss = [x:ys | ys <- yss]
where : puts a single element in front of a list. Read this similar
to a "set comprehension" in mathematics, i.e.
The list of all "x:ys" for all elements ys in the list yss
Or you could use map:

concat x yss = map (x:) yss

map takes a function and applies it to every element of a list. (x:)
is the function that adds x to the front of its argument.

But the name "concat" is a bit misleading, as this sounds like list or
string concatenation, which th eabove isn't.


There are basically two recursive algorithms for permutations:

A:

For all elements in the list do:

Remove the selected element from the list.

Generate all permutations of the reduced list and add the
selected element to the front of all these.

Combine the above lists of permutations into a single list.


B:

Take the first element from the list.

Find all permutations of the rest.

In each of these, insert the first element at all possible
positions in the permuted list.

Combine the above lists of permutations into a single list.


In algorithm A, the hardest part is the function that removes the
selected element from the list. The rest is fairly trivial:

permsA [] = [[]]
permsA xs = foldr (++) [] [map (y:) (permsA (remove y xs)) | y<-xs]

In algorithm B, the hardest part is inserting an element in all
possible positions in a list. Again, the rest is fairly trivial:

permsB [] = [[]]
permsB (x:xs) = foldr (++) [] (map (insertAtAll x) (permsB xs))

So, the exercise for you is to define one of these two functions:

remove :: EQ a => a -> [a] -> [a]

insertAtAll :: a -> [a] -> [[a]]

The "EQ a =>" in the type signature for remove means that equality
must be defined on a. This makes solution A less general than B
(which doesn't require equality on elements), but it is possible to
make a variant of algorithm A that doesn't have this limitation.

Torben

Continue reading on narkive:
Loading...