Ici, j'ai des entiers 1:7
pour quatre partitions différentes, à savoir {1}, {2,3,4}, {5,6} et {7} et ces partitions sont écrites dans une liste, c'est-à-dire list(1,c(2,3,4),c(5,6),7)
. Je traite les partitions comme des ensembles, de sorte que différentes permutations d'éléments au sein d'une partition doivent être reconnues comme identiques. Par exemple, list(1,c(2,3,4),c(5,6),7)
et list(7,1,c(2,3,4),c(6,5))
sont équivalents.
Notez qu'il n'y a pas de répétition pour les éléments de la liste, par exemple, non list(c(1,2),c(2,1),c(1,2))
, car ce problème traite des partitions exclusives sur l'ensemble.
J'ai énuméré certaines des différentes permutations dans la liste lst
ci-dessous
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)))
et ce que je veux faire est de vérifier que toutes les permutations sont équivalentes. Si oui, alors nous obtenons un résultat TRUE
.
Ce que j'ai fait jusqu'à présent, c'est trier les éléments dans chaque partition, et les utiliser setdiff()
avec interset()
et union()
pour les juger (voir mon code ci-dessous)
s <- Map(function(v) Map(sort,v),lst)
equivalent <- length(setdiff(Reduce(union,s),Reduce(intersect,s),))==0
Cependant, je suppose que cette méthode serait lente chaque fois que la taille de la partition augmente. Existe-t-il une approche plus rapide pour y parvenir? Apprécié à l'avance!
- certains cas de test (données de petite taille)
# 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)))
la source
Map
appels multipleslst_equal = list(list(1:2, 3:4), list(3:4, 1:2))
et aussi un où le résultat devrait êtreFALSE
, peutlst_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
. De cette façon, lorsqu'une réponse fonctionne sur certains cas de test, mais pas sur tous, il est facile de diagnostiquer pourquoi. Lorsqu'il n'y a qu'un seul exemple, vous perdez des nuances dans les résultats du test. Il est également agréable d'ajouter de nouveaux exemples plutôt que de modifier des exemples existants sous des personnes qui ont déjà travaillé dessus.lst
est potentiellement longue, vous pourriez gagner en efficacité avec d'autres approches. Par exemple, un premier chèque quilength(unique(lengths(lst))) == 1
reviendrait très rapidementFALSE
si l'une des listes internes avait le mauvais nombre d'éléments ....lst
, en le comparantlst[[i]]
àlst[[1]]
, et de cette façon, vous pouvez vous arrêter dès que vous constatez un décalage, plutôt que de faire toutes les comparaisons. Silst
est long etFALSE
s sont communs, cela pourrait être un gros gain d'efficacité, mais probablement pas la peine autrement.Réponses:
Un article sur
R
et toute variante de fast n'est pas complet sans une solution avec rcpp .Pour maximiser l'efficacité, choisir la bonne structure de données sera de la plus haute importance. Notre structure de données doit stocker des valeurs uniques et également avoir un accès / insertion rapide. C'est exactement ce que std :: unordered_set incarne. Il nous suffit de déterminer comment identifier de manière unique chacun
vector
des éléments non ordonnésintegers
.Entrez dans le théorème fondamental de l'arithmétique
L'ALE stipule que chaque nombre peut être représenté de manière unique (jusqu'à l' ordre des facteurs) par le produit des nombres premiers.
Voici un exemple démontrant comment nous pouvons utiliser le FTA pour déchiffrer rapidement si deux vecteurs sont équivalents jusqu'à l'ordre (NB
P
ci-dessous est une liste de nombres premiers ...(2, 3, 5, 7, 11, etc.)
:De cela, nous voyons cela
vec1
etvec3
mappons correctement vers le même nombre, alors qu'ilvec2
est mappé sur une valeur différente.Étant donné que nos vecteurs réels peuvent contenir jusqu'à une centaine d'entiers de moins de 1000, l'application de l'ALE produira des nombres extrêmement élevés. Nous pouvons contourner cela en profitant de la règle de produit du logarithme:
Avec cela à notre disposition, nous serons en mesure de traiter des exemples beaucoup plus importants (cela commence à se détériorer sur des exemples extrêmement grands).
Premièrement, nous avons besoin d'un simple générateur de nombres premiers (NB Nous générons en fait le logarithme de chaque nombre premier).
Et voici l'implémentation principale:
Voici les résultats appliqués
lst1, lst2, lst3, & lst (the large one)
par @GKi.Et voici quelques repères avec le
units
paramètre défini surrelative
.Environ 3 fois plus rapide que la solution la plus rapide à ce jour sur le plus grand exemple.
Pour moi, ce résultat en dit long sur la beauté et l'efficacité de
base R
celles affichées par @GKi, @ chinsoon12, @Gregor, @ThomasIsCoding, et plus encore. Nous avons écrit une centaine de lignes très spécifiquesC++
pour obtenir une accélération modérée. Pour être honnête, lesbase R
solutions finissent par appeler principalement du code compilé et finissent par utiliser des tables de hachage comme nous l'avons fait ci-dessus.la source
Après le tri, vous pouvez utiliser
duplicated
etall
.Alternative: trier dans une boucle
Alternative: trier pendant la boucle et permettre une sortie anticipée
ou en utilisant
setequal
ou en améliorant légèrement l'idée de @ chinsoon12 pour échanger la liste avec un vecteur!
ou évitez le second
order
ou échanger
order
avecmatch
(oufmatch
)Ou sans sortie anticipée.
ou écrit en C ++
Merci à @Gregor pour des conseils pour améliorer la réponse!
la source
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)))
sera jugé commeFALSE
min
!Performance:
Bibliothèques:
Les fonctions:
Les données:
la source
length(setdiff(Reduce(union,s),Reduce(intersect,s)))==0
, désolé pour mon erreur ....Espérons que la 2e fois chanceuse
cas de test:
contrôles:
code temporel:
horaires:
la source