Di sini saya memiliki bilangan bulat 1:7
untuk empat partisi yang berbeda, yaitu {1}, {2,3,4}, {5,6}, dan {7} dan partisi tersebut ditulis dalam daftar, yaitu list(1,c(2,3,4),c(5,6),7)
,. Saya memperlakukan partisi sebagai set, sehingga permutasi elemen yang berbeda dalam satu partisi harus diakui sebagai yang sama. Misalnya, list(1,c(2,3,4),c(5,6),7)
dan list(7,1,c(2,3,4),c(6,5))
setara.
Perhatikan bahwa, tidak ada pengulangan untuk elemen dalam daftar, misalnya, tidak list(c(1,2),c(2,1),c(1,2))
, karena masalah ini membahas partisi eksklusif di seluruh set.
Saya mendaftarkan beberapa permutasi yang berbeda ke dalam daftar lst
seperti di bawah ini
lst <- list(list(1,c(2,3,4),c(5,6),7),
list(c(2,3,4),1,7,c(5,6)),
list(1,c(2,3,4),7,c(6,5)),
list(7,1,c(3,2,4),c(5,6)))
dan yang ingin saya lakukan adalah memverifikasi semua permutasi setara. Jika ya, maka kami mendapatkan hasil TRUE
.
Apa yang saya lakukan sejauh ini adalah menyortir elemen-elemen di dalam setiap partisi, dan menggunakannya setdiff()
dengan interset()
dan union()
menilainya (lihat kode saya di bawah)
s <- Map(function(v) Map(sort,v),lst)
equivalent <- length(setdiff(Reduce(union,s),Reduce(intersect,s),))==0
Namun, saya kira metode ini akan lambat setiap kali ukuran partisi naik. Apakah ada pendekatan yang lebih cepat untuk membuatnya? Dihargai di muka!
- beberapa test case (data ukuran kecil)
# should return `TRUE`
lst1 <- list(list(1,c(2,3,4),c(5,6)),
list(c(2,3,4),1,c(5,6)),
list(1,c(2,3,4),c(6,5)))
# should return `TRUE`
lst2 <- list(list(1:2, 3:4), list(3:4, 1:2))
# should return `FALSE`
lst3 <- list(list(1,c(2,3,4),c(5,6)), list(c(2,3,4),1,c(5,6)), list(1,c(2,3,5),c(6,4)))
sumber
Map
panggilanlst_equal = list(list(1:2, 3:4), list(3:4, 1:2))
dan juga di mana hasilnya seharusnyaFALSE
, mungkinlst_false <- list(list(1,c(2,3,4),c(5,6)), list(c(2,3,4),1,c(5,6)), list(1,c(2,3,5),c(6,4)))
FALSE
. Dengan begitu, ketika jawaban berhasil pada beberapa, tetapi tidak semua, menguji kasus, mudah untuk mendiagnosis sebabnya. Ketika hanya ada satu contoh, Anda kehilangan nuansa dalam hasil tes. Lebih baik menambahkan contoh baru daripada mengubah contoh yang ada di bawah orang yang telah mengerjakannya.lst
berpotensi panjang, Anda mungkin mendapatkan efisiensi dengan pendekatan lain. Misalnya, cek pertama yanglength(unique(lengths(lst))) == 1
akan kembali dengan sangat cepatFALSE
jika ada daftar bagian dalam yang memiliki jumlah elemen yang salah ....lst
, membandingkanlst[[i]]
untuklst[[1]]
, dan dengan cara itu Anda dapat berhenti segera setelah Anda menemukan ketidakcocokan, daripada melakukan semua perbandingan. Jikalst
panjang danFALSE
umum, ini bisa menjadi keuntungan efisiensi yang besar, tetapi mungkin tidak sepadan dengan itu.Jawaban:
Kiriman tentang
R
dan varian cepat tidak lengkap tanpa solusi yang menampilkan rcpp .Untuk memaksimalkan efisiensi, memilih struktur data yang benar akan sangat penting. Struktur data kami perlu menyimpan nilai unik dan juga memiliki insert / akses cepat. Inilah yang std :: unordered_set mewujudkan. Kita hanya perlu menentukan bagaimana kita dapat mengidentifikasi secara unik setiap
vector
unorderedintegers
.Masukkan Teorema Dasar Aritmatika
FTA menyatakan bahwa setiap angka dapat diwakili secara unik (hingga urutan faktor) oleh produk dari bilangan prima.
Berikut adalah contoh yang menunjukkan bagaimana kita dapat menggunakan FTA untuk dengan cepat menguraikan jika dua vektor setara dengan urutan (NB di
P
bawah ini adalah daftar bilangan prima ...(2, 3, 5, 7, 11, etc.)
:Dari ini, kita melihat itu
vec1
danvec3
memetakan dengan benar ke nomor yang sama, sedangkanvec2
dipetakan ke nilai yang berbeda.Karena vektor kami yang sebenarnya mungkin berisi hingga seratus bilangan bulat kurang dari 1000, menerapkan FTA akan menghasilkan angka yang sangat besar. Kita dapat menyiasati hal ini dengan mengambil keuntungan dari aturan produk logaritma:
Dengan ini, kami akan dapat menangani contoh angka yang jauh lebih besar (Ini mulai memburuk pada contoh yang sangat besar).
Pertama, kita membutuhkan generator bilangan prima sederhana (NB Kita sebenarnya menghasilkan log dari setiap bilangan prima).
Dan inilah implementasi utamanya:
Ini adalah hasil ketika diterapkan pada yang
lst1, lst2, lst3, & lst (the large one)
diberikan oleh @GKi.Dan berikut adalah beberapa tolok ukur dengan
units
parameter diatur kerelative
.Tentang 3x lebih cepat daripada solusi tercepat namun pada contoh yang lebih besar.
Bagi saya, hasil ini berbicara banyak tentang keindahan dan efisiensi
base R
seperti yang ditampilkan oleh @GKi, @ chinsoon12, @Gregor, @ThomasIsCoding, dan banyak lagi. Kami menulis sekitar 100 baris yang sangat spesifikC++
untuk mendapatkan kecepatan sedang. Agar adil,base R
solusi akhirnya memanggil sebagian besar kode yang dikompilasi dan akhirnya menggunakan tabel hash seperti yang kita lakukan di atas.sumber
Setelah menyortir, Anda dapat menggunakan
duplicated
danall
.Alternatif: Sortir dalam satu loop
Alternatif: Sortir selama loop dan izinkan keluar awal
atau menggunakan
setequal
atau sedikit meningkatkan ide dari @ chinsoon12 untuk bertukar daftar dengan vektor!
atau hindari yang kedua
order
atau bertukar
order
denganmatch
(ataufmatch
)Atau tanpa keluar lebih awal.
atau ditulis dalam C ++
Terima kasih kepada @Gregor untuk mendapatkan petunjuk untuk meningkatkan jawabannya!
sumber
lst <- list(list(1,c(2,3,4),c(5,6),7), list(c(2,3,4),1,7,c(5,6)), list(1,c(2,3,4),7,c(6,5)), list(7,1,c(3,2,4),c(5,6)))
akan dinilai sebagaiFALSE
min
!Kinerja:
Perpustakaan:
Fungsi:
Data:
sumber
length(setdiff(Reduce(union,s),Reduce(intersect,s)))==0
, maaf atas kesalahan saya ....Semoga beruntung 2 kali
kasus uji:
memeriksa:
kode waktu:
pengaturan waktu:
sumber