Visit the LQ Articles and Editorials section
 Home Forums HCL Reviews Tutorials Articles Register Search Today's Posts Mark Forums Read
 LinuxQuestions.org using rand in matlab
 Programming This forum is for all programming questions. The question does not have to be directly related to Linux and any language is fair game.

Notices

 12-10-2005, 02:19 AM #1 lmvent LQ Newbie   Registered: Sep 2005 Posts: 24 Rep: using rand in matlab I need to create a row vector that includes the numbers 1-52 randomly with no repeats. I know how to do it with repeats, but I can't figure out how to get it without repeats Code: ```function[deck] = shuffle %SHUFFLE shuffle shuffles the deck of cards deck = randint(1,52,51) + 1; return```
 12-10-2005, 09:36 AM #2 graemef Senior Member   Registered: Nov 2005 Location: Hanoi Distribution: Fedora 13, Ubuntu 10.04 Posts: 2,379 Rep: I don't use Matlab but you need to think about your algorithm. The probelm is that rand is not guaranteed not to repeat. (A nasty double negative there) There are numerous ways to address this some which may be more appropriate to you chosen language. However here is one. Create a sorted array with the numbers 1-52 and an empty result array Repeat until the result array has 52 entries.create a random number from 1 - 52 Find the number in the unsorted array If it is zero ignore and go to step 2 Else add an element with this number to the result array And make the element in the sorted array zero go to step 2
 12-10-2005, 02:01 PM #3 lmvent LQ Newbie   Registered: Sep 2005 Posts: 24 Original Poster Rep: Okay I tried what you said and this is what I come up with, but it gets stuck in a loop somwhere. Code: ```function[deck] = shuffle %SHUFFLE shuffle shuffles the deck of cards a = (1:52); deck = []; d = randint(1,1,51) + 1; for i = 1:52 while a(1,d) ~= d d = randint(1,1,51) + 1; end if a(1,d) == d a(1,d) = 0; deck(1,i) = d; end end return```
 12-10-2005, 06:25 PM #4 graemef Senior Member   Registered: Nov 2005 Location: Hanoi Distribution: Fedora 13, Ubuntu 10.04 Posts: 2,379 Rep: You loop is certain not correct. Essentially it wants to be loop until your desk is 52 in size. By the look of it you have two loops. Only one is necessary. Remember it is an array that is growing by one each time you generate a unique number. Finally it is not a very efficient algorithm but that can be improved upon once you have teh basic approach sorted out. graeme.
 12-13-2005, 12:39 AM #5 kike_coello Member   Registered: Jul 2005 Location: maryland Distribution: Ubuntu 9.04 Posts: 88 Rep: i don't know if graemef's solution helped since you haven't replied but the idea is good. just gotta cum up with a good algorithm i think you should do something like he said 1. make an array with 1 to 52 sorted 2. make an empty array of 52 elements 3. now loop for the first element in the array 4. if the number that random gives (between 1 and 52) is in the list then copy it to the first element and make the location of the random number 0 5. now loop for next, if the random number happens to be one that has been deleted from the original array (0) then loop again to get a new random number 6. do this until the original array is full of 0's, then the second array will be full of non repeating numbers i took matlab like 3 years ago and i haven't practiced at all after the end of that class. sorry i can't give you any code but its a very simple problem and you should be able to code it
 12-13-2005, 10:43 AM #6 lmvent LQ Newbie   Registered: Sep 2005 Posts: 24 Original Poster Rep: Code: ```function[deck] = q5 %Q5 q5 shuffles the deck of cards a = (1:52); %Create a row vector with all numbers from 1 to 52 deck = []; %create an empty vector to be filled with random numbers d = randint(1,1,52) + 1; %Create a random number between 1 and 52 for i = 1:52 while a(1,d) ~= d %Find the random number in a and set it to zero %If the random number is no longer in a, find %a new random number d = randint(1,1,52) + 1; end a(1,d) = 0; deck(1,i) = d; %Insert the random value into the out row vector end return``` This is the code I came up with from your suggestion and it works fine. The problem in the last one I posted was that I was using rand incorrectly, because I had d = randint(1,1,51) + 1 so I was only finding random numbers between 1 and 51 and that is why it got stuck in the loop. Thanks for all your help
 02-21-2009, 12:39 AM #7 tjudd LQ Newbie   Registered: Feb 2009 Posts: 2 Rep: randperm randperm(52) should do the trick
 02-21-2009, 07:40 AM #8 wje_lq Member   Registered: Sep 2007 Location: Mariposa Distribution: Debian lenny, Slackware 12 Posts: 809 Rep: What tjudd said. He has, with one stroke, solved lmvent's problem. But it can't hurt to go into topic of permutations a little more deeply. I'm going to do it in C, because I've never used matlab. This will be of benefit for those who actually wish to use lmvent's solution in other languages. lmvent's solution works, but it can be slow if you ever wish to shuffle huge arrays. What you want is an algorithm that scales well. If you're going to shuffle twice as many elements, you want the shuffling to take only twice as long. But lmvent's algorithm is proportional to the square of the number of elements. Why? Because as you go through the for loop, you'll find that the while loop takes longer and longer. That's because more and more elements in the array a have been zeroed out. With a little more computation in your major loop, you can eliminate the minor loop (and, incidentally, the extra array) entirely. For small decks, this might increase your compute time a little, but you don't care. For large decks, the payoff will be huge. I don't know matlab, but here's a proof of concept in C. I wrote the permutation code in a macro, so you can drop it into anything regardless of the type of your data. You can convert it into a function if you want. Code: ```#define RANDPERM(xxx_type,xxx_array,xxx_size) \ do \ { \ int jndex; \ int pick_one; \ \ xxx_type temp; \ \ for(jndex=xxx_size; \ jndex>1; /* we need do this only xxx_size-1 times */ \ jndex-- \ ) \ { \ pick_one =rand()%(jndex); \ temp =xxx_array[pick_one]; \ xxx_array[pick_one]=xxx_array[jndex-1]; \ xxx_array[jndex-1] =temp; \ } \ \ } while(0) #include /* for the srand() statement, if you use it */ #include #include #include /* for strcpy() and strcat(), if you use them */ #include /* for the srand() statement, if you use it */ #include /* for the srand() statement, if you use it */ int main(void) { int jndex; int int_deck[52]; long long long_long_deck[62]; char *named_deck[52]; /* The following line is not mandatory, but would be a good idea. */ srand(time(NULL)+getpid()); printf("=== part 1: integers from 1 to 52\n"); for(jndex=0; jndex<52; jndex++ ) { int_deck[jndex]=jndex+1; } RANDPERM(int,int_deck,52); for(jndex=0; jndex<52; jndex++ ) { printf("%2d\n",int_deck[jndex]); } printf("=== part 2: first 62 powers of 2\n"); for(jndex=0; jndex<62; jndex++ ) { long_long_deck[jndex]=1LL<
 02-22-2009, 05:20 PM #9 sLeeQ LQ Newbie   Registered: Feb 2009 Posts: 1 Rep: more on random perms Just for variety, here is a solution in Mathematica: RandomSample[{1, 1, 2, 3, 5, 8, 13}, 4] will return a randomly chosen subset of the first argument (namely the first 7 Fibonacci numbers) of size given by the second argument (namely 4). None of the elements will repeat, but notice that the two 1's are indistinguishable. ----------------------------------------------------------- And just for extra variety, here is an O-O solution in Java: Code: ```public class RandomIndeces { private int[] indeces; private int n; private java.util.Random randy; public RandomIndeces(int size) { n=size; indeces= new int[n]; for (int i=0; i
02-22-2009, 06:17 PM   #10
wje_lq
Member

Registered: Sep 2007
Location: Mariposa
Distribution: Debian lenny, Slackware 12
Posts: 809

Rep:
Quote:
 I suspect tjudd might be distressed to know she was referred to as "he".
Not if she's the gentleman I think she is.

02-23-2009, 05:35 PM   #11
tjudd
LQ Newbie

Registered: Feb 2009
Posts: 2

Rep:
Quote:
 Originally Posted by wje_lq Not if she's the gentleman I think she is.
ha ha:) ok just to settle it, I am female.