Create matrix with entries unique to row and column R - r

I need to find all possible 5x5 matrix of integers 1-5 unique to each row and column (imagine a Sudoku) in R.
Is there any efficient way of doing this without creating all 120C5 matrices and then finding the fitting ones?
Thank you!

As I said in my comment above, matrices of this type are called Latin squares.
For a start, we already know that there are 56 so-called reduced Latin squares and 161280 all Latin squares of size 5. The reduced Latin squares are such that both the first column and the first row are just 1, 2, 3, 4, 5 (in this order). Given those reduced Latin squares, one may easily (as long as the size is not greater than 5) generate all Latin squares: permute all the rows except the first one and permute all the columns. Hence, as expected, 161280=5!*4!*56.
By restricting the first row and column one could generate 4!*3!*2!=288 matrices and check which 56 are Latin squares. However, I'm going to skip that and take their list from here.
First we read and rearrange the data
reduced <- read.table("http://users.cecs.anu.edu.au/~bdm/data/reduced5.txt", head = FALSE, colClasses = "character")
reduced <- lapply(1:nrow(reduced), function(r) matrix(as.numeric(unlist(strsplit(unlist(reduced[r, ]), ""))) + 1, 5))
length(reduced)
# [1] 56
Now let's generate all 5! and 4! permutations of 1, 2, 3, 4, 5 and 1, 2, 3, 4, respectively.
library(combinat)
perms5 <- permn(1:5)
perms4 <- permn(1:4)
Lastly, we go over all the reduced Latin squares and permute them in all possible ways
allLS <- sapply(reduced, function(m) {
LS <- vector("list", gamma(6) * gamma(5))
for(i in 1:gamma(5))
for(j in 1:gamma(6))
LS[[(i - 1) * gamma(6) + j]] <- m[perms4[[i]] + 1, perms5[[j]]]
LS
})
Takes just a couple of seconds and we have the result
length(allLS)
# [1] 161280
It is easy to verify that they all are different
table(table(sapply(allLS, paste0, collapse = "")))
# 1
# 161280
and you could also check if they all are Latin squares.

Related

understanding the output of a function

Trying to understand how the value of "traded" is 34
available <- c(10,4,7,10,12)
desired <- c(12,5,2,6,14)
traded <- sum(mapply(function(x,y) min(x,y), available, desired))
Correct value for traded is 34. Just not sure why this is the case. I thought the value would be 6 as the minimum values from each vector (4 and 2) summed together =6
This is answered in the comments, but I wanted to add this breakdown since it helps me to visualize each step.
mapply(function(x,y) min(x,y)): Maps min(x,y) to each item in vectors x and y , so the function is doing this:
min(10,12)
min(4,5)
min(7,2)
min(10,6)
min(12,14)
and outputs = (10, 4, 2, 6, 12)
sum(mapply(...)): Which "sees" the output above and computes 10+4+2+6+12 = 34

R: expand.grid with the same vector repeated multiple times

So I'm trying to get all the possible combinations of rolling two dice n number of times.
Currently I have:
# Get all possible rolls with two dice
d <- list(1, 2, 3, 4, 5, 6)
rolls <- lapply(apply(expand.grid(d, d), 1, identity), unlist)
# Get all possible ways to roll two dice twice
trials <-lapply(apply(expand.grid(rolls, rolls), 1, identity), unlist)
d stores all possible values you can get on a single dice. rolls stores all possible outcomes of rolling two dice at the same time. And trials stores all possible outcomes of rolling two dice at the same time, twice in a row.
I can modify the last line as
trials <-lapply(apply(expand.grid(rolls, rolls, rolls), 1, identity), unlist)
to get all possible outcomes of rolling two dice at the same time, three times in a row, but I cannot figure out how to make the number of times variable, so that I could pass some arbitrary number n and get all possible outcomes of rolling two dice at the same time, an n number of times in a row
I know I only made this post about 20 minutes ago but I actually already managed to figure it out. The solution is:
trials <-lapply(apply(expand.grid(rep(list(rolls), times = n)), 1, identity), unlist)
Assuming you want permutations (both 1,2 and 2, 1) and not combinations (just 1,2), this is simpler:
n <- 2
perms <- expand.grid(as.data.frame(matrix(1:6, 6, n)))
dim(perms)
# [1] 36 2
n <- 4
perms <- expand.grid(as.data.frame(matrix(1:6, 6, n)))
dim(perms)
#[1] 1296 4
n <- 6
perms <- expand.grid(as.data.frame(matrix(1:6, 6, n)))
dim(perms)
# [1] 46656 6

Multiply certain elements of a vector in R

I have a vector [1:360] with integers and need to find the products of the first, second ... twelfth set of 30 elements. Ultimately, I need a function that gives me a vector [1:12] with the products of all twelve 30-element intervals.
I'm fairly new to R and have been stuck on this for too long.
A simple way to do this would be to turn your vector into a 30-row matrix and get the product of each column.
In the absence of a reproducible example, let's make one with a vector of 360 numbers drawn from a normal distribution:
set.seed(69)
vec <- rnorm(360)
We can turn vec into a 30 * 12 matrix by just doing matrix(vec, nrow = 30), which will fill the matrix by column. We then get the product of each column by using apply to apply the function prob to each column.
apply(matrix(vec, nrow = 30), 2, prod)
#> [1] -6.253460e-09 -4.413086e-09 -1.332389e-10 1.041448e-08 -1.779489e-08 1.255979e-10
#> [7] 3.463687e-13 -6.265196e-12 8.300651e-04 -1.041469e-10 4.256378e-09 1.439522e-09

R: Accessing elements of 2D matrix with vectors of indices

Suppose I have a 3 X 15 matrix "phi", and I want to create a vector of entries from phi corresponding to an i,j combination, where i is a length 900 vector of numbers 1:3, and j is a length 900 vector of numbers 1:15. In other words, I want a length 900 vector of phi values, where the first element is phi[i[1], j[1]], the second element would be phi[i[2], j[2]], etc.
My initial thought was phi_list <- phi[i, j], but that appears to give back every combination of i,j values. So, how would I go about constructing such a vector?
Thanks for any help!
In this case, we can use the index as a matrix with the i for row index and 'j' for column index
phi[cbind(i, j)]
#[1] 6 18 35
If we use the i and jvectors in the 'i', and 'j' it would return a matrix by including the rows and columns included in the index instead of picking the elements that matches the location
data
set.seed(24)
phi <- matrix(1:50, 5, 10)
i <- c(1, 3, 5)
j <- c(2, 4, 7)

Generate random numbers with 3 to 7 digits in R

How can I generate random numbers of varying length, say between 3 to 7 digits with equal probability.
At the end I would like the code to come up with a 3 to 7 digit number (with equal probability) consisting of random numbers between 0 and 9.
I came up with this solution but feel that it is overly complicated because of the obligatory generation of a data frame.
options(scipen=999)
t <- as.data.frame(c(1000,10000,100000,1000000,10000000))
round(runif(1, 0,1) * sample_n(t,1, replace = TRUE),0)
Is there a more elegant solution?
Based on the information you provided, I came up with another solution that might be closer to what you want. In the end, it consists of these steps:
randomly pick a number len from [3, 7] determining the length of the output
randomly pick len numbers from [0, 9]
concatenate those numbers
Code to do that:
(len <- runif(1, 3, 7) %/% 1)
(s <- runif(len, 0, 9) %/% 1)
cat(s, sep = "")
I previously provided this answer; it does not meet the requirements though, as became clear after OP provided further details.
Doesn't that boil down to generating a random number between 100 and 9999999?
If so, does this do what you want?
runif(5, 100, 9999999) %/% 1
You could probably also use round, but you'd always have to round down.
Output:
[1] 4531543 9411580 2195906 3510185 1129009
You could use a vectorized approach, and sample from the allowed range of exponents directly in the exponent:
pick.nums <- function(n){floor(10^(sample(3:7,n,replace = TRUE))*runif(n))}
For example,
> set.seed(123)
> pick.nums(5)
[1] 455 528105 89241 5514350 4566147

Resources