创build20个独特的宾果卡

我试图创build20个独特的数字卡,但我挣扎了一点。所以基本上我需要创build20个独特的matrix3x3在第一列数字1-10,在第二列数字11-20和21-30在第三列..任何想法? 我宁愿在r中完成它,特别是因为我不知道Visual Basic。 在Excel中,我知道如何生成卡片,但不知道如何确保它们是唯一的。

这对我来说似乎是相当准确和直接的。 无论如何,我需要创build20个matrix,如下所示:

[,1] [,2] [,3] [1,] 5 17 23 [2,] 8 18 22 [3,] 3 16 24 

每个matrix应该是唯一的,每一列应该由三个唯一的数字组成(第一列 – 数字1-10,第二列11-20,第三列 – 21-30)。

生成随机数字很容易,但如何确保生成的卡片是唯一的?请看看我投票作为答案的文章 – 因为它给你彻底的解释如何实现它。

(注意:我误读“行”而不是“列”,所以下面的代码和解释将处理第一行1-10和第二行11-20的matrix,而不是列同样只是换位)

此代码应保证唯一性和良好的随机性:

 library(gtools) # helper function getKthPermWithRep <- function(k,n,r){ k <- k - 1 if(n^r< k){ stop('k is greater than possibile permutations') } v <- rep.int(0,r) index <- length(v) while ( k != 0 ) { remainder<- k %% nk <- k %/% n v[index] <- remainder index <- index - 1 } return(v+1) } # get all possible permutations of 10 elements taken 3 at a time # (singlerowperms = 720) allperms <- permutations(10,3) singlerowperms <- nrow(allperms) # get 20 random and unique bingo cards cards <- lapply(sample.int(singlerowperms^3,20),FUN=function(k){ perm2use <- getKthPermWithRep(k,singlerowperms,3) m <- allperms[perm2use,] m[2,] <- m[2,] + 10 m[3,] <- m[3,] + 20 return(m) # if you want transpose the result just do: # return(t(m)) }) 

说明

(disclaimer tl; dr)

为了保证随机性和唯一性,一个安全的方法是生成所有可能的宾果卡,然后在其中随机select而不用replace。

要生成所有可能的卡片,我们应该:

  1. 为每个3行元素生成所有的可能性
  2. 得到他们的笛卡尔产品

步骤(1)可以使用包gtools函数permutations容易地获得(参见代码中的对象allPerms )。 请注意,我们只需要第一行的排列(即从1到10取3个元素),因为其他行的排列可以通过分别相加10和20从第一排轻松获得。

步骤(2)也容易进入R,但是我们首先考虑将会产生多less可能性。 步骤(1)每行返回720个案例,所以最终我们将有720*720*720 = 720^3 = 373248000可能的宾果卡!
由于占用的内存是巨大的,所以生成它们都是不实际的,因此我们需要find一种方法来在这个大范围的可能性中获得20个随机元素,而不需要将它们存储在内存中。

解决scheme来自函数getKthPermWithRep ,给定一个索引k ,它返回第k个排列,重复从1:n取的r元素(注意在这种情况下,重复排列对应于笛卡尔乘积)。

例如

 # all permutations with repetition of 2 elements in 1:3 are permutations(n = 3, r = 2,repeats.allowed = TRUE) # [,1] [,2] # [1,] 1 1 # [2,] 1 2 # [3,] 1 3 # [4,] 2 1 # [5,] 2 2 # [6,] 2 3 # [7,] 3 1 # [8,] 3 2 # [9,] 3 3 # using the getKthPermWithRep you can get directly the k-th permutation you want : getKthPermWithRep(k=4,n=3,r=2) # [1] 2 1 getKthPermWithRep(k=8,n=3,r=2) # [1] 3 2 

因此,我们现在只select1:720^3范围内的20个随机索引(使用sample.int函数),然后使用函数getKthPermWithRep获得从1:720取出的3个数字的相应排列。
最后,这些数字的三元组可以通过将它们作为索引来转换为真正的卡片行,以获得最终的matrix(当然,在第二行和第三行之后加上+10+20 )。


奖金

getKthPermWithRep的解释

如果你看上面的例子(在1:3中重复2个元素的排列),并减去1的所有数量的结果,你会得到这个:

 > permutations(n = 3, r = 2,repeats.allowed = T) - 1 [,1] [,2] [1,] 0 0 [2,] 0 1 [3,] 0 2 [4,] 1 0 [5,] 1 1 [6,] 1 2 [7,] 2 0 [8,] 2 1 [9,] 2 2 

如果您将每行的每个数字视为一个数字,您可以注意到那些行(00,01,02 …)都是从0到8的数字,以3为基数表示(是,3表示为n)。 所以,当你用1:n重复r元素来问第k个排列的时候,你也需要把k-1翻译成n然后返回1

因此,给定algorithm将基数从10变为n:

 changeBase <- function(num,base){ v <- NULL while ( num != 0 ) { remainder = num %% base # assume K > 1 num = num %/% base # integer division v <- c(remainder,v) } if(is.null(v)){ return(0) } return(v) } 

您可以轻松获得getKthPermWithRep函数。

可以用下面的代码生成一个具有所需值范围的3x3matrix:

 mat <- matrix(c(sample(1:10,3), sample(11:20,3), sample(21:30, 3)), nrow=3) 

此外,您可以使用for循环来生成20个唯一matrix的列表,如下所示:

 for (i in 1:20) { mat[[i]] <- list(matrix(c(sample(1:10,3), sample(11:20,3), sample(21:30,3)), nrow=3)) print(mat[[i]]) } 

好吧,我可能会掉在这里,但我提出了一个校验和 (使用Excel)。

这是每个宾果卡的独特签名,如果在任何列中的数字顺序改变而不改变实际的数字,这将保持不变。 公式是

 =SUM(10^MOD(A2:A4,10)+2*10^MOD(B2:B4,10)+4*10^MOD(C2:C4,10)) 

第一张牌的宾果号码在A2:C4。

这个想法是为每列生成一个10位数的数字,然后乘以一个常数,并添加它们以获得签名。

所以在这里我用这里的标准公式生成了两张随机的宾果卡片,加上两个故意作为彼此排列的宾果卡片。

在这里输入图像说明

然后我检查是否有任何签名是使用公式重复的

 =MAX(COUNTIF(D5:D20,D5:D20)) 

不应该给出超过1的答案。

在不太可能发生重复的情况下,您只需按F9并生成一些新的卡片。

所有公式都是数组公式,并且必须使用Ctrl Shift Enterinput

这是一个不雅的方法来做到这一点。 生成所有可能的组合,然后抽样而不更换。 这些是排列,组合:顺序在宾果中很重要

 library(dplyr) library(tidyr) library(magrittr) generate_samples = function(n) { first = data_frame(first = (n-9):n) first %>% merge(first %>% rename(second = first)) %>% merge(first %>% rename(third = first)) %>% sample_n(20) } suffix = function(df, suffix) df %>% setNames(names(.) %>% paste0(suffix)) generate_samples(10) %>% suffix(10) %>% bind_cols(generate_samples(20) %>% suffix(20)) %>% bind_cols(generate_samples(30) %>% suffix(30)) %>% rowwise %>% do(matrix = t(.) %>% matrix(3)) %>% use_series(matrix)