Permutations
Return to Topics page
Permutations are different ways to arrange some group of things.
The key concept is that the order of the things
in these arrangements is important.
If we start with three things, A, B, and C then we can arrange them
in any of the following ways: ABC, ACB, BAC, BCA, CAB, or CBA.
These are all permutations of the letters A, B, and C.
There are 6 permutations of the three things.
Another example would be to start with four things, say,
cat, dog, eel, and fox, and ask for the permutations of these
four things taken two at a time.
That is, find all the different arrangements of two things
where the two things are taken from the list of the
four things: cat, dog, eel, and fox. This will be
cat dog,
cat eel,
cat fox,
dog cat,
dog eel,
dog fox,
eel cat,
eel dog,
eel fox,
fox cat,
fox dog, and
fox eel.
There are 12 permutations of four things taken two at a time.
Clearly there are two related but different tasks
here. One is to be able to construct the different permutations and the other is
to predict the number of permutations that we will find.
R can help us with both of these.
Unfortunately, that help will take a little bit of extra effort.
This next section presents the "permutations" function. Although it is nice to see it,
this class does not require you to use it. For this class we will
get a smaller, easier to use function, in fact we will get two of them,
to mimic the function available on the TI-83/84 calculators. Those functions are presented
later on this page.
|
Bill Venables, and later Gregory R. Warnes, developed and refined
a special function that constructs permutations. That function
is not part of the base R installation. Instead, that function is
provided in a package that is called "gtools". In order for us to use that
function we must do two things. First we need to actually get the package
and second we need to load it into our R session.
Fortunately the commands to do both of these are quite short.
They are
install.packages("gtools")
library(gtools)
Once we have performed those two statements within our session we will be able to use the
permutations() function. Figure 1 shows the console screen
that reflects doing those two commands.
Figure 1
Following the installation shown in Figure 1 we can give the command
permutations(3, 3, letters[1:3])
which is a call to the
permutations() function, telling it that it should use
the 3 values in the third argument and to use them 3 at a time
to form all of the possible permutations that it can. The third argument,
letters[1:3] provides the letters "a", "b", and "c" for permutations()
to use as the values.
Figure 2 shows the result of that command.
Figure 2
It is always nice to get a confirmation like that. We can try
to confirm the "cat dog eel fox" challenge from earlier.
The command permutations(4, 2, c("cat","dog","eel","fox"))
should do it.
Figure 3
We can make that challenge a bit more difficult if we ask for
all the permutations of the 4 things taken 3 at a time
by using the command permutations(4, 3, c("cat","dog","eel","fox"))
as shown in Figure 4.
Figure 4
As a by-product of having R construct the various permutations
we also discover the number of permutations. After all, it really
does not matter what values we are using the number of permutations of
3 things taken 3 at a time is 6 (as seen in Figure 2),
the number of permutations of 4 things taken 2 at a time is 12
(as seen in Figure 3), and the number of permutations of
4 things taken 3 at a time is 24 (as seen in Figure 4).
Remember that we get the output that we saw in those figures
because we just use the function permutations() as a statement.
We did not assign the results of the function call to any variable.
We will change that behavior with the command
t<-permutations(3,3,c("M","A","T","H","1","6","0"))
shown in Figure 5.
Figure 5
In Figure 5 the result of the permutations() function
is stored in the variable t; the result is not displayed in
the console.
Because the work shown above was done in RStudio, we
can find the variable t in the Environment pane.
There we see the "dimensions" of t as well as the first few values
stored in that variable. This is shown in Figure 6.
Figure 6
The dimensions [1:6, 1:3] specify that t
is structured as 6 rows (numbered 1 through 6) and 3 columns (numbered 1 through 3).
This is exactly what we expect since there are 6 permutations each holding
3 values.
We could issue the command t to have R display the contents of
t. That is done in Figure 7.
Figure 7
The display in Figure 7 shows our 6 rows and 3 columns.
Each row contains a different permutation.
What might be surprising is the values from the
third argument, "M","A","T","H","1","6","0", that
permutations() seems to have chosen. It almost looks like
the function took the last three values instead of the first three that
most people would have expected!
In fact, permutations() selected the lexicographically lowest three values.
We can see this if we rerun the command but change the choice of values as is
shown in Figure 8.
Figure 8
The values shown in Figure 8 are the three lexicographically ordered values
in the third argument of permutations(3,3,c("M","A","T","H","1","6","W"))
.
Lexicographic ordering is an extension of what we would
call alphabetic ordering. The extension means that we are using the coded values of the
characters to sort them. In this case it is enough to point
out that the character "1" has a lower "lexicographic" value than does the
character "6" which in turn has a lower "lexicographic" value than does the
character "A".
One issue with permutations is that it does not take
much to create a situation where the number of permutations
gets to be quite large. For example,
if we use all seven of the characters in MATH160 and ask for the permutations
of 7 things taken 3 at a time, we will get 210 permutations.
We can see this by running the command t<-permutations(7,3,c("M","A","T","H","1","6","0"))
as shown in Figure 9.
Figure 9
Because the functional value was assigned to a variable, t,
there is no associated output.
However, the information about t displayed in the Environment
pane now reflects the new contents of t.
Figure 10 shows this diagnostic information.
Figure 10
Indeed, the dimensions of t shown in Figure 10 indicate that there
are 210 permutations of 7 things taken 3 at a time.
Thus, using the diagnostic information in the Environment pane
we have found a way to determine the number of permutations that we
have for whatever number of things we have taken some number of things at a time.
However, we would like to have a more direct way to find that number.
You might notice that when we ask for the number of arrangements of 7 things taken 3 at a time
we are really saying that we have three positions to fill using the 7 values,
We can form a picture to helps us.
Figure 11 shows our three positions and gives them the names first, second,
and third.
Figure 11
Then our process is to fill the three positions with the 7 values. We start by
filling the first position. We have any of seven choices that we
could put into that first position.
Once we have made that choice, however, there are only six remaining values
that we could put into the second position. That means that there are 7*6 or
42 different ways to just fill the first and second positions.
But for each of those 42 arrangements there are still five possible
choices for the third position. Therefore, we have 7*6*5 ways to fill
all three positions using our 7 possible values. But, 7*6*5=210, the number of
permutations of 7 things taken 3 at a time.
This suggests an algorithm for finding the number of
permutations of n things taken r at a time.
We just form the product of r factors,
starting with n and decreasing by one for each new factor.
This algorithm says that the number of permutations of 9 things taken 4 at a time
is equal to the value of the four factor expression 9*8*7*6, or 3024.
Before we go any further we will use our sneaky trick to see if we get the same answer.
Figure 12 shows the command to create, but not display, the permutations.
Figure 12
And, Figure 13 shows the dimensions of the new variable t, confirming
our answer of 3024.
Figure 13
Here is where we develop our own functions
for finding the number of
permutations of n things taken r at a time.
|
The algorithm of creating the product of r factors,
starting with n and decreasing by one for each new factor,
can be written in R to define a new function as:
num_perm <- function( n, r ) # compute the number of permutations
{ # of n things taken r at aa time
if( r == 0 ) # special case if r=0
{return(1)}
p <- 1 # initialize the product
for (i in 1:r) # go throgh the r factors
{ p <- p*n
n <- n-1
}
return(p) # send back the result
}
When this text is given to R it just accepts the definition
as shown in Figure 14.
Figure 14
The first confirmation of the acceptability of our new
function is that R did not complain about any errors.
The second confirmation is that the new function,
num_perm() is now shown in the Environment
pane shown in Figure 15.
Figure 15
Once our new function is defined we can run it by
using its name and sending it two values.
For example we can have it find the number of
permutations of 9 things taken 4 at a time
by giving the command num_perm(9,4)
.
R responds with our much anticipated 3024.
Or we could have our function find the number of
permutations of 12 things taken 7 at a time
by giving the command num_perm(12,7)
.
In that case R responds with 3991680.
All of this is shown in Figure 16.
Figure 16
In all of the discussion above we have written out the
challenge in the form "find the number of
permutations of n things taken r at a time."
It would be nice if we has some way to say this in just a few
symbols. Unfortunately, there has not been any
agreement on the most acceptable form for such symbolism.
One form nPr has a small advantage
in that it is the form used by the TI-83/84 calculators.
On such a calculator one would enter 12nPr7
to find the number of permutations of 12 things taken 7 at a time.
However, in a textbook or paper, the symbol
for that specific computation would be 12P7.
Table 1 gives some the general and specific forms.
Here we will try to consistently use the nPr form.
Now that we have a symbol for permutations, it would be nice to have a
direct way to express the formula without having to
print out our function. The first step in doing this is to note that
6P6 = 6*5*4*3*2*1.
In fact, nPn = n*(n-1)*(n-2)*...*3*2*1.
We have a mathematical symbol for 6*5*4*3*2*1 and that is 6!
which
is read as "6 factorial."
That means that 8! = 8*7*6*5*4*3*2*1 and
n! = n*(n-1)*(n-2)*...*3*2*1.
It would be nice if we were able to use the factorial symbol to help write the
equation for permutations. However,
8P3 = 8*7*6; it only has three factors.
We need to find a way to say that we should stop appending factors at some point.
The general form nPr will have r factors.
It could be written as
nPr = n*(n-1)*(n-2)*...*(n-r+2)*(n-r+1).
That is, the general form says that we start the factors at n but stop when we get to the
factor equal to (n-r+1). We can verify that for n=8 and r=3
which makes (n-r+1) be 6 and, indeed, our factors start at 8 and end at 6
to get 8*7*6.
Unfortunately, there is no symbolic way to say "Start doing 8 factorial but stop after
3 factors are in place." However, we can observe that
This pattern gives us a way to write, in a short space, the value of
the product of three numbers starting at 8 and decreasing by 1 each time.
We know that
12P5 = 12*11*10*9*8 but we could write that as
12P5 = (12!) / 7!.
In general terms we state this pattern as
This formula, nPr = n! / (n-r)!,
is the one generally quoted as the way to find the
number of permutations of n things taken r at a time.
The formula works and if we have some way to find factorials
then this becomes a convenient formula.
Back in Figure 14 we saw a function that we wrote, num_perm().
That function did not use factorials at all. It turns out that R
has a built-in function, factorial() that computes factorials.
Therefore, we could, if we wanted to, create a new function that does the same thing that the old one did but
this time uses factorial(). One possibility for this would be
nPr <- function( n,r )
{ return (factorial(n)/factorial(n-r))}
Figure 17 shows this function definition in RStudio session.
Figure 17
We can see, in the Environment pane shown in Figure 18, that R
has accepted the function definition.
Figure 18
Now that the function is defined we can use it by entering
commands such as nPr(9,4)
or nPr(12,7)
as demonstrated in Figure 19.
Figure 19
Of course we got the same results as we did from num_perm()
back in Figure 16.
Now we have two functions, num_perm() and nPr(), that do the same
thing. Which should we use? It really does not make a difference; we get the same
answer with either function. Use whichever appeals to you.
Before we leave this topic there is one sticky point that we need to cover.
The factorial() function makes sense for things like factorial(9)
or factorial(3). It even makes some sense that factorial(1)
gives the answer of 1. However, look at Figure 20.
Figure 20
According to Figure 20, 0! is 1. On the surface this may seem strange but it a
a part of the definition of factorial. In fact, we need 0! to be defined
to be 1 so that our formula for the number of permutations works out
in the extreme cases. We already know that the number of
permutations of 6 things taken 6 at a time is the same as 6!.
But our formula says that
6P6 = 6! / (6-6)!.
Simplifying that denominator means that
6P6 = 6! / 0!,
so we need to define 0! to be 1.
Return to Topics page
©Roger M. Palay
Saline, MI 48176 December, 2015