Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate permutations without duplicated elements in both rows and colums

I have 4 teams (A-D) and 4 games (1-4).

GOAL: I want to generate a dataframe (4,4) :

  • that has 4 rows for 4 rounds
  • that has 4 columns for 4 games
  • I want to attribute a different team to each column/game over these 4 rows/rounds
  • and I DON'T want duplicates in either rows or columns

I get how to do permutations, and I know how to avoid duplicates in each row, but I'm stuck when trying to avoid duplicates in both rows and columns.

In the end, I want to get a dataframe like this (no duplicates horizontally or vertically):

A B C D

B D A C

D C B A

C A D B

And obviously, in reality I have way more games and teams !

Can someone help me with that please ?

Thank you!


edit:

Thanks to all of you ! Super useful.

I also would like to be able to fix some positions in the output that I get (the final one being with 12 games and 12 teams).

For example, I'd like to be able to specify several fixed positions such as : B must be in position (1,2) AND D must be in position (4,3), AND etc.

Any idea how to get latin squares that also meet these conditions ?

like image 531
Hal Avatar asked Oct 26 '25 09:10

Hal


2 Answers

I think your problem is equivalent to cycling through the vector. I.e. start with ABCD, shift one over for BCDA, etc. We can do that e.g. like so:

x <- LETTERS[1:4]
sapply(seq_along(x), \(i) x[c(i:length(x), seq_len(i - 1))])
     [,1] [,2] [,3] [,4]
[1,] "A"  "B"  "C"  "D" 
[2,] "B"  "C"  "D"  "A" 
[3,] "C"  "D"  "A"  "B" 
[4,] "D"  "A"  "B"  "C"
like image 77
Axeman Avatar answered Oct 28 '25 23:10

Axeman


No duplicates in either row or column sounds like a Latin square to me.

The magic package could be of help with this

magic::rlatin(n = 3)
#>      [,1] [,2] [,3]
#> [1,]    2    1    3
#> [2,]    1    3    2
#> [3,]    3    2    1

And for your example, we can use an already existing x with letters or team names and convert to a data frame afterwards.

x <- LETTERS[1:4]
as.data.frame(matrix(x[magic::rlatin(length(x))], nrow = length(x)))
#>   V1 V2 V3 V4
#> 1  D  B  A  C
#> 2  A  D  C  B
#> 3  B  C  D  A
#> 4  C  A  B  D

Depends on the use-case if you want to require a whole other package, especially when a good answer on how to do this in base R has already been submitted.

like image 30
JoshCowley Avatar answered Oct 28 '25 22:10

JoshCowley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!