Untuk permutasi, rcppalgos bagus. Sayangnya, ada 479 juta kemungkinan dengan 12 bidang yang berarti terlalu banyak memori untuk kebanyakan orang:
library(RcppAlgos)
elements <- 12
permuteGeneral(elements, elements)
#> Error: cannot allocate vector of size 21.4 Gb
Ada beberapa alternatif.
Ambil sampel permutasi. Artinya, lakukan hanya 1 juta bukan 479 juta. Untuk melakukan ini, Anda dapat menggunakan permuteSample(12, 12, n = 1e6)
. Lihat @ JosephWood's jawaban untuk pendekatan yang agak mirip kecuali dia sampel 479 juta permutasi;)
Buat loop di rcpp untuk mengevaluasi permutasi pada kreasi. Ini menghemat memori karena pada akhirnya Anda akan membangun fungsi hanya untuk mengembalikan hasil yang benar.
Dekati masalah dengan algoritma yang berbeda. Saya akan fokus pada opsi ini.
Algoritma baru dengan kendala
Segmen harus 26
Kita tahu bahwa setiap segmen baris dalam bintang di atas perlu menambahkan hingga 26. Kita dapat menambahkan kendala itu untuk menghasilkan permutasi kami - beri kami hanya kombinasi yang menambahkan hingga 26:
# only certain combinations will add to 26
lucky_combo <- comboGeneral(12, 4, comparisonFun = '==', constraintFun = 'sum', limitConstraints = 26L)
Kelompok ABCD dan EFGH
Pada bintang di atas, saya telah mewarnai tiga grup secara berbeda: ABCD , EFGH , dan IJLK . Dua kelompok pertama juga tidak memiliki kesamaan poin dan juga memiliki segmen bunga yang sama. Oleh karena itu, kita dapat menambahkan batasan lain: untuk kombinasi yang menambahkan hingga 26, kita perlu memastikan ABCD dan EFGH tidak memiliki angka yang tumpang tindih. IJLK akan diberi 4 angka sisanya.
library(RcppAlgos)
lucky_combo <- comboGeneral(12, 4, comparisonFun = '==', constraintFun = 'sum', limitConstraints = 26L)
two_combo <- comboGeneral(nrow(lucky_combo), 2)
unique_combos <- !apply(cbind(lucky_combo[two_combo[, 1], ], lucky_combo[two_combo[, 2], ]), 1, anyDuplicated)
grp1 <- lucky_combo[two_combo[unique_combos, 1],]
grp2 <- lucky_combo[two_combo[unique_combos, 2],]
grp3 <- t(apply(cbind(grp1, grp2), 1, function(x) setdiff(1:12, x)))
Permutasi melalui grup
Kita perlu menemukan semua permutasi dari setiap grup. Artinya, kami hanya memiliki kombinasi yang menambahkan hingga 26. Misalnya, kami perlu mengambil 1, 2, 11, 12
dan membuat 1, 2, 12, 11; 1, 12, 2, 11; ...
.
#create group perms (i.e., we need all permutations of grp1, grp2, and grp3)
n <- 4
grp_perms <- permuteGeneral(n, n)
n_perm <- nrow(grp_perms)
# We create all of the permutations of grp1. Then we have to repeat grp1 permutations
# for all grp2 permutations and then we need to repeat one more time for grp3 permutations.
stars <- cbind(do.call(rbind, lapply(asplit(grp1, 1), function(x) matrix(x[grp_perms], ncol = n)))[rep(seq_len(sum(unique_combos) * n_perm), each = n_perm^2), ],
do.call(rbind, lapply(asplit(grp2, 1), function(x) matrix(x[grp_perms], ncol = n)[rep(1:n_perm, n_perm), ]))[rep(seq_len(sum(unique_combos) * n_perm^2), each = n_perm), ],
do.call(rbind, lapply(asplit(grp3, 1), function(x) matrix(x[grp_perms], ncol = n)[rep(1:n_perm, n_perm^2), ])))
colnames(stars) <- LETTERS[1:12]
Perhitungan Akhir
Langkah terakhir adalah melakukan perhitungan. Saya menggunakan lapply()
dan di Reduce()
sini untuk melakukan pemrograman yang lebih fungsional - jika tidak, banyak kode akan diketik enam kali. Lihat solusi asli untuk penjelasan yang lebih menyeluruh tentang kode matematika.
# creating a list will simplify our math as we can use Reduce()
col_ind <- list(c('A', 'B', 'C', 'D'), #these two will always be 26
c('E', 'F', 'G', 'H'), #these two will always be 26
c('I', 'C', 'J', 'H'),
c('D', 'J', 'G', 'K'),
c('K', 'F', 'L', 'A'),
c('E', 'L', 'B', 'I'))
# Determine which permutations result in a lucky star
L <- lapply(col_ind, function(cols) rowSums(stars[, cols]) == 26)
soln <- Reduce(`&`, L)
# A couple of ways to analyze the result
rbind(stars[which(soln),], stars[which(soln), c(1,8, 9, 10, 11, 6, 7, 2, 3, 4, 5, 12)])
table(Reduce('+', L)) * 2
2 3 4 6
2090304 493824 69120 960
Swapping ABCD dan EFGH
Pada akhir kode di atas, saya mengambil keuntungan bahwa kita dapat bertukar ABCD
dan EFGH
mendapatkan permutasi yang tersisa. Berikut adalah kode untuk mengonfirmasi bahwa ya, kami dapat menukar kedua grup dan menjadi benar:
# swap grp1 and grp2
stars2 <- stars[, c('E', 'F', 'G', 'H', 'A', 'B', 'C', 'D', 'I', 'J', 'K', 'L')]
# do the calculations again
L2 <- lapply(col_ind, function(cols) rowSums(stars2[, cols]) == 26)
soln2 <- Reduce(`&`, L2)
identical(soln, soln2)
#[1] TRUE
#show that col_ind[1:2] always equal 26:
sapply(L, all)
[1] TRUE TRUE FALSE FALSE FALSE FALSE
Performa
Pada akhirnya, kami mengevaluasi hanya 1,3 juta dari 479 permutasi dan hanya mengocok hingga 550 MB RAM. Dibutuhkan sekitar 0,7 untuk menjalankan
# A tibble: 1 x 13
expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
<bch:expr> <bch> <bch:> <dbl> <bch:byt> <dbl> <int> <dbl>
1 new_algo 688ms 688ms 1.45 550MB 7.27 1 5
x<- 1:elements
dan yang lebih pentingL1 <- y[,1] + y[,3] + y[,6] + y[,8]
. Ini tidak akan membantu masalah memori Anda sehingga Anda selalu dapat melihat ke rcpp