Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have

s = {2, 3, 5, 7, 1, 4, 6}  (* always with diffente elements in {1,2....7}*)
l = Length[s]
n = 3

and n tells us that we want to select 3 positions in the list s, and permute them within the full list.

For example,

a = RandomSample[Range[l], n]

Suppose we obtain a = {2, 6, 4} and we apply a random permutation to these positions obtaining {4, 6, 2}. Then

Position 2 goes to position 4
Position 6 goes to position 6
Position 4 goes to position 2

obtaining

s = {2, 7, 5, 3, 1, 4, 6}

What´s a simple (and comprehensible) way without using an auxiliary list.

Edit

After reading MrWizard an Yi-Wang answers: (I like the s[[a]] =s[[b]] of MWizard, and the use of permutations and rule of Yi-Wang, but I think that a simpler an more comprehensible way is

s = {2, 3, 5, 7, 1, 4, 6}
n = 3
Print["BEFORE -> ", s]
choice = RandomSample[Range[Length[s]], n]
choicepermuted = RandomSample[choice, n]
s[[choice]] = s[[choicepermuted]]
Print["AFTER ->  ", s]
share|improve this question
    
Why without without use an auxiliary list? Is modification of the original list acceptable? –  Mr.Wizard Jun 6 at 11:01
1  
Pardon me, but you seem to have added my method to your question, stated you like it best, but given the Accept (green tickmark) to Yi Wang. This confounds me. Why? –  Mr.Wizard Jun 6 at 11:41
    
@Mr.Wizard, Yes, I like your code s[[a]] = s[[b]] for the interchange but "a" is not a random selection os positions, and "b" is not a Permutation of previous selection. And the solution of Yi-wang does exactly what I wanted. This is the issue because I invite you to edit your answer to give a randomly and b an randomly permutation of a. But.... YES Youre righth the f2 function you propose is perfect. I change now the green tickmark :-) It´s a pity that is no possible give TWO ACCEPTS :-) because many of you are very very good, and it´s a trouble having to choose :-)) –  Mika Ike Jun 6 at 12:39

2 Answers 2

up vote 2 down vote accepted

This is the simplest and probably also fasted method. If it is not acceptable please explain why.

s = {2, 3, 5, 7, 1, 4, 6};

a = {2, 6, 4};  (* random sample *)
b = {4, 6, 2};  (* permuted *)

s[[a]] = s[[b]];

s
{2, 7, 5, 3, 1, 4, 6}

You can always make a copy of the list if you don't want to modify the original, e.g. s2 = s, then operate on s2.


Full code for clarity. A function for in-place modification:

SetAttributes[f1, HoldFirst]

f1[s_Symbol?VectorQ, n_Integer] :=
  (s[[#]] = s[[ RandomSample @ # ]];) & @ RandomSample[Range @ Length @ s, n]

(You must evaluate s to see the result.)

And one for modification of a copy:

f2[ss_List, n_Integer] :=
  Module[{a, s = ss},
    a = RandomSample[Range @ Length @ s, n];
    s[[a]] = s[[ RandomSample @ a ]];
    s
  ]
share|improve this answer
    
@mr-wizard is perfect, the only aspect is use Random for a, and after, use random for make b= permutation of b, if you want to edit to other people. –  Mika Ike Jun 6 at 11:13
    
@MikaIke Thanks for the Accept. Do I understand that you are suggesting I include the actual RandomSample usage in this answer, for clarity? –  Mr.Wizard Jun 6 at 11:15
    
@mr-wizars, your me is enough! :-) but... in that example you set the positions will be permuted a = {2, 6, 4}; but if you want randomly select 3 positions, it´s suitable use the Random for the position and for the permutation (b) –  Mika Ike Jun 6 at 11:18
1  
@MikaIke See update. –  Mr.Wizard Jun 6 at 11:30
    
@mr-wizard Thank you very much. I like it, and learn with your answers, but in this case I think that it´s very complicated for what I want. I edited the original quesiton with a little of you, and a little of Yi-Wang answers :-) –  Mika Ike Jun 6 at 11:39

I think Mr. Wizard's way is cleaner. Nevertheless, here is another approach: One can select the numbers to permute first, and then permute them and replace them.

s = {2, 3, 5, 7, 1, 4, 6};
n = 3;

choice = RandomSample[s, n];
choicePermuted = Permute[choice, RandomPermutation[3]];
rule = Dispatch @ MapThread[Rule, {choice, choicePermuted}];

s /. rule
share|improve this answer
    
Thank you. Perfect! I don´t know use the rules. I must learn. –  Mika Ike Jun 6 at 11:06
    
On short lists this should be adequate. Be aware that on long lists it will become quite inefficient, though adding Dispatch may help. –  Mr.Wizard Jun 6 at 11:08
    
@yi-wang Excuse me, Your answer is a good solution for me (especially if i want to store the permutation applied), but the MrQizard option is less simple, and is valid for me. –  Mika Ike Jun 6 at 11:11
    
BTW, I made a modification: choice = RandomSample[Range@l, n] is changed to choice = RandomSample[s, n]. Although for the particular s it doesn't make a difference, I think the new version is what the OP really wants. –  Yi Wang Jun 6 at 11:13
1  
@yi-wang I like very much your answer, because show the permutation if you want. but in may case, I only obtain a permutation, and I´m not intererest in know what permutation was applied. I like –  Mika Ike Jun 6 at 11:15

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.