2017-10-13 4 views
1

J'ai une chaîne contenant plusieurs éléments, certains identiques et d'autres uniques. Je veux que mon code vérifie chaque 2 éléments suivants dans ma chaîne et s'ils sont égaux, il devrait appeler une fonction ShuffleString, où la variable d'entrée (randomize) est la chaîne elle-même, qui remodèlera la chaîne dans une nouvelle position . Ensuite, le script doit vérifier à nouveau tous les 2 éléments suivants dans la chaîne jusqu'à ce que deux éléments identiques apparaissent côte à côte.Comment mélanger de telle sorte que deux mêmes éléments ne sont pas ensemble?


Je l'ai fait ce qui suit:
Mon fichier de fonction ShuffleString fonctionne très bien. La variable d'entrée randomize, comme indiqué précédemment, contient les mêmes éléments que MyString mais dans un ordre différent, car cela était nécessaire sur une question non liée plus tôt dans le script.

function [MyString] = ShuffleString(randomize) 
MyString = []; 
while length(randomize) > 0 
    S = randi(length(randomize), 1); 
    MyString = [MyString, randomize(S)]; 
    randomize(S) = []; 
end 

Le script ne fonctionne pas comme prévu. En ce moment, il ressemble à ceci:

MyString = ["Cat" "Dog" "Mouse" "Mouse" "Dog" "Hamster" "Zebra" "Obama"... 
    "Dog" "Fish" "Salmon" "Turkey"]; 

randomize = MyString; 
while(1) 
    for Z = 1:length(MyString) 
     if Z < length(MyString) 
      Q = Z+1; 
     end 
     if isequal(MyString{Z},MyString{Q}) 
      [MyString]=ShuffleString(randomize) 
      continue; 
     end 
    end 
end 

Il semble juste de remanier la chaîne une quantité infinie de fois. Quel est le problème avec ceci et comment puis-je le faire fonctionner?

+0

parce que vous utilisez une boucle infinie? 'alors que (1)'. –

Répondre

3

Vous utilisez une boucle infinie while qui n'a aucun moyen de se rompre et donc d'itérer.

Voici une manière plus simple:
Utilisez le troisième argument de sortie de la fonction unique pour obtenir les éléments sous forme numérique pour faciliter le traitement. Appliquez diff dessus pour vérifier si les éléments consécutifs sont identiques. S'il y a une occurrence de mêmes éléments consécutifs, la sortie de diff donnera au moins un zéro qui, appliqué avec negatedall retournera true pour continuer la boucle et vice versa. A la fin, utilisez les indices/représentation numérique des chaînes obtenues après la boucle pour indexer le premier argument de sortie unique (qui a été calculé plus tôt). Ainsi, le script sera:

MyString = ["Cat" "Dog" "Mouse" "Mouse" "Dog" "Hamster" "Zebra" "Obama"... 
    "Dog" "Fish" "Salmon" "Turkey"]; %Given string array 
[a,~,c] = unique(MyString);%finding unique elements and their indices 
while ~all(diff(c))  %looping until there are no same strings together 
    c = ShuffleString(c); %shuffling the unique indices 
end 
MyString = a(c);   %using the shuffled indices to get the required string array 

Pour la fonction ShuffleString, une meilleure façon serait d'utiliser randperm. Votre version de la fonction fonctionne mais elle ne cesse de changer la taille des tableaux MyString et randomize et donc adversely affects the performance and memory usage. Voici une façon plus simple:

function MyString = ShuffleString(MyString) 
MyString = MyString(randperm(numel(MyString))); 
end 
+0

Wow, c'est incroyable! Fonctionne parfaitement et juste ce que je voulais, merci beaucoup! – Birks