Custom shuffle algorithm
I know there is an efficient shuffling algorithm called Fisher Yates I believe but I try to build a custom one (out of stubbornness).
I am trying to generate a new random number in the right range, than use it to determine a new random place in a copied array. And then store this random number to NOT use it twice.
My method does not work. Would someone care to give me some enlightment?
public int shuffled(int numbers) {
int rand;
int copyNumbers = new int[numbers.length];
int usedRand = new int[numbers.length];
for (int i = 0; i < numbers.length; i++) {
rand = new Random().nextInt(numbers.length + 1);
if ((i != rand) && (usedRand[i]!=rand)) {
copyNumbers[rand] = numbers[i];
usedRand[i]=rand;
}
}
numbers = copyNumbers;
return numbers;
}
arrays shuffle
add a comment |
I know there is an efficient shuffling algorithm called Fisher Yates I believe but I try to build a custom one (out of stubbornness).
I am trying to generate a new random number in the right range, than use it to determine a new random place in a copied array. And then store this random number to NOT use it twice.
My method does not work. Would someone care to give me some enlightment?
public int shuffled(int numbers) {
int rand;
int copyNumbers = new int[numbers.length];
int usedRand = new int[numbers.length];
for (int i = 0; i < numbers.length; i++) {
rand = new Random().nextInt(numbers.length + 1);
if ((i != rand) && (usedRand[i]!=rand)) {
copyNumbers[rand] = numbers[i];
usedRand[i]=rand;
}
}
numbers = copyNumbers;
return numbers;
}
arrays shuffle
What does not work? evenRandom
should follow a certain structure. If you really want to use a random value, you should mix in some real random variables, like time, date etc.
– dnsiv
Nov 21 '18 at 10:08
I don't get a properly shuffled array. This is a school project so they do not look that close if our shuffling is "real" random. But of course I take any avice.
– Dovendyr
Nov 21 '18 at 10:29
1
Right now I see 2 possible errors. The first one isrand = new Random().nextInt(numbers.length+1);
You need a random number from 0 to numbers.length-1, since arrays start with indexing at 0, but right now you will get a random number from 1 to numbers.length. You should get anIndexOutOfBoundsException
this way.
– dnsiv
Nov 21 '18 at 10:50
The second possible error lies in this phrase(usedRand[i] != rand)
. You're just comparing the current entry (i
) in usedRand with the current random value, if that entry already used this random number. But this way, you wont be able to access one entry a second time. You need to create a second for loop, which iterates through all entries of usedRand and compares their values with the current random number
– dnsiv
Nov 21 '18 at 10:52
add a comment |
I know there is an efficient shuffling algorithm called Fisher Yates I believe but I try to build a custom one (out of stubbornness).
I am trying to generate a new random number in the right range, than use it to determine a new random place in a copied array. And then store this random number to NOT use it twice.
My method does not work. Would someone care to give me some enlightment?
public int shuffled(int numbers) {
int rand;
int copyNumbers = new int[numbers.length];
int usedRand = new int[numbers.length];
for (int i = 0; i < numbers.length; i++) {
rand = new Random().nextInt(numbers.length + 1);
if ((i != rand) && (usedRand[i]!=rand)) {
copyNumbers[rand] = numbers[i];
usedRand[i]=rand;
}
}
numbers = copyNumbers;
return numbers;
}
arrays shuffle
I know there is an efficient shuffling algorithm called Fisher Yates I believe but I try to build a custom one (out of stubbornness).
I am trying to generate a new random number in the right range, than use it to determine a new random place in a copied array. And then store this random number to NOT use it twice.
My method does not work. Would someone care to give me some enlightment?
public int shuffled(int numbers) {
int rand;
int copyNumbers = new int[numbers.length];
int usedRand = new int[numbers.length];
for (int i = 0; i < numbers.length; i++) {
rand = new Random().nextInt(numbers.length + 1);
if ((i != rand) && (usedRand[i]!=rand)) {
copyNumbers[rand] = numbers[i];
usedRand[i]=rand;
}
}
numbers = copyNumbers;
return numbers;
}
arrays shuffle
arrays shuffle
edited Dec 4 '18 at 5:37
Cœur
18.7k9110150
18.7k9110150
asked Nov 21 '18 at 10:03
DovendyrDovendyr
52
52
What does not work? evenRandom
should follow a certain structure. If you really want to use a random value, you should mix in some real random variables, like time, date etc.
– dnsiv
Nov 21 '18 at 10:08
I don't get a properly shuffled array. This is a school project so they do not look that close if our shuffling is "real" random. But of course I take any avice.
– Dovendyr
Nov 21 '18 at 10:29
1
Right now I see 2 possible errors. The first one isrand = new Random().nextInt(numbers.length+1);
You need a random number from 0 to numbers.length-1, since arrays start with indexing at 0, but right now you will get a random number from 1 to numbers.length. You should get anIndexOutOfBoundsException
this way.
– dnsiv
Nov 21 '18 at 10:50
The second possible error lies in this phrase(usedRand[i] != rand)
. You're just comparing the current entry (i
) in usedRand with the current random value, if that entry already used this random number. But this way, you wont be able to access one entry a second time. You need to create a second for loop, which iterates through all entries of usedRand and compares their values with the current random number
– dnsiv
Nov 21 '18 at 10:52
add a comment |
What does not work? evenRandom
should follow a certain structure. If you really want to use a random value, you should mix in some real random variables, like time, date etc.
– dnsiv
Nov 21 '18 at 10:08
I don't get a properly shuffled array. This is a school project so they do not look that close if our shuffling is "real" random. But of course I take any avice.
– Dovendyr
Nov 21 '18 at 10:29
1
Right now I see 2 possible errors. The first one isrand = new Random().nextInt(numbers.length+1);
You need a random number from 0 to numbers.length-1, since arrays start with indexing at 0, but right now you will get a random number from 1 to numbers.length. You should get anIndexOutOfBoundsException
this way.
– dnsiv
Nov 21 '18 at 10:50
The second possible error lies in this phrase(usedRand[i] != rand)
. You're just comparing the current entry (i
) in usedRand with the current random value, if that entry already used this random number. But this way, you wont be able to access one entry a second time. You need to create a second for loop, which iterates through all entries of usedRand and compares their values with the current random number
– dnsiv
Nov 21 '18 at 10:52
What does not work? even
Random
should follow a certain structure. If you really want to use a random value, you should mix in some real random variables, like time, date etc.– dnsiv
Nov 21 '18 at 10:08
What does not work? even
Random
should follow a certain structure. If you really want to use a random value, you should mix in some real random variables, like time, date etc.– dnsiv
Nov 21 '18 at 10:08
I don't get a properly shuffled array. This is a school project so they do not look that close if our shuffling is "real" random. But of course I take any avice.
– Dovendyr
Nov 21 '18 at 10:29
I don't get a properly shuffled array. This is a school project so they do not look that close if our shuffling is "real" random. But of course I take any avice.
– Dovendyr
Nov 21 '18 at 10:29
1
1
Right now I see 2 possible errors. The first one is
rand = new Random().nextInt(numbers.length+1);
You need a random number from 0 to numbers.length-1, since arrays start with indexing at 0, but right now you will get a random number from 1 to numbers.length. You should get an IndexOutOfBoundsException
this way.– dnsiv
Nov 21 '18 at 10:50
Right now I see 2 possible errors. The first one is
rand = new Random().nextInt(numbers.length+1);
You need a random number from 0 to numbers.length-1, since arrays start with indexing at 0, but right now you will get a random number from 1 to numbers.length. You should get an IndexOutOfBoundsException
this way.– dnsiv
Nov 21 '18 at 10:50
The second possible error lies in this phrase
(usedRand[i] != rand)
. You're just comparing the current entry (i
) in usedRand with the current random value, if that entry already used this random number. But this way, you wont be able to access one entry a second time. You need to create a second for loop, which iterates through all entries of usedRand and compares their values with the current random number– dnsiv
Nov 21 '18 at 10:52
The second possible error lies in this phrase
(usedRand[i] != rand)
. You're just comparing the current entry (i
) in usedRand with the current random value, if that entry already used this random number. But this way, you wont be able to access one entry a second time. You need to create a second for loop, which iterates through all entries of usedRand and compares their values with the current random number– dnsiv
Nov 21 '18 at 10:52
add a comment |
1 Answer
1
active
oldest
votes
As I already pointed the errors out in the comments. Here is possible implementation of shuffle(). I commented the code based on my modifications.
If you happen to have questions, please feel free to ask!
public static void main(String args) {
//sample values
int numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
//First call of recursive function
int x = shuffled(numbers, null, null, false, 0);
//Print out values
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + "|");
}
}
public static int shuffled(int numbers, int usedRand, int copyNumbers, boolean newRandomValue, int current) {
//Initialisation
int rand = -1;
int start = 0;
//If function hasn't been called before, initialise.
if (usedRand == null) {
usedRand = new int[numbers.length];
Arrays.fill(usedRand, -1);
}
if (copyNumbers == null) {
copyNumbers = new int[numbers.length];
}
//If function has been called recursively, reassign the start-Integer for for-loop
if (newRandomValue) {
start = current;
}
//Iterate over numbers-array with <start> as start-index
for (int i = start; i < numbers.length; i++) {
/*
new Random().nextInt(numbers.length+1 ) gets a random number between 0 and numbers.length + 1
In our example, numbers.length+1 is 20. So we will get a random number between 0 and 20.
But we want to get random values between -1 and 19, so
new Random().nextInt(numbers.length+1 ) --> values between 0 to 20
rand = new Random().nextInt(numbers.length+1 ) -1 --> values between -1 to 19
*/
rand = new Random().nextInt(numbers.length+1 ) -1;
//Iterate through usedRand array and compare if current rand value has already been used yet.
for (int j = 0; j < usedRand.length; j++) {
if (usedRand[j] == rand) {
/*
If current rand value has already been used, recursively call shuffle again with the current index i
as new start-index
*/
return shuffled(numbers, usedRand, copyNumbers, true, i);
}
}
copyNumbers[rand] = numbers[i];
usedRand[i] = rand;
}
numbers = copyNumbers;
return numbers;
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409543%2fcustom-shuffle-algorithm%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
As I already pointed the errors out in the comments. Here is possible implementation of shuffle(). I commented the code based on my modifications.
If you happen to have questions, please feel free to ask!
public static void main(String args) {
//sample values
int numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
//First call of recursive function
int x = shuffled(numbers, null, null, false, 0);
//Print out values
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + "|");
}
}
public static int shuffled(int numbers, int usedRand, int copyNumbers, boolean newRandomValue, int current) {
//Initialisation
int rand = -1;
int start = 0;
//If function hasn't been called before, initialise.
if (usedRand == null) {
usedRand = new int[numbers.length];
Arrays.fill(usedRand, -1);
}
if (copyNumbers == null) {
copyNumbers = new int[numbers.length];
}
//If function has been called recursively, reassign the start-Integer for for-loop
if (newRandomValue) {
start = current;
}
//Iterate over numbers-array with <start> as start-index
for (int i = start; i < numbers.length; i++) {
/*
new Random().nextInt(numbers.length+1 ) gets a random number between 0 and numbers.length + 1
In our example, numbers.length+1 is 20. So we will get a random number between 0 and 20.
But we want to get random values between -1 and 19, so
new Random().nextInt(numbers.length+1 ) --> values between 0 to 20
rand = new Random().nextInt(numbers.length+1 ) -1 --> values between -1 to 19
*/
rand = new Random().nextInt(numbers.length+1 ) -1;
//Iterate through usedRand array and compare if current rand value has already been used yet.
for (int j = 0; j < usedRand.length; j++) {
if (usedRand[j] == rand) {
/*
If current rand value has already been used, recursively call shuffle again with the current index i
as new start-index
*/
return shuffled(numbers, usedRand, copyNumbers, true, i);
}
}
copyNumbers[rand] = numbers[i];
usedRand[i] = rand;
}
numbers = copyNumbers;
return numbers;
}
add a comment |
As I already pointed the errors out in the comments. Here is possible implementation of shuffle(). I commented the code based on my modifications.
If you happen to have questions, please feel free to ask!
public static void main(String args) {
//sample values
int numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
//First call of recursive function
int x = shuffled(numbers, null, null, false, 0);
//Print out values
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + "|");
}
}
public static int shuffled(int numbers, int usedRand, int copyNumbers, boolean newRandomValue, int current) {
//Initialisation
int rand = -1;
int start = 0;
//If function hasn't been called before, initialise.
if (usedRand == null) {
usedRand = new int[numbers.length];
Arrays.fill(usedRand, -1);
}
if (copyNumbers == null) {
copyNumbers = new int[numbers.length];
}
//If function has been called recursively, reassign the start-Integer for for-loop
if (newRandomValue) {
start = current;
}
//Iterate over numbers-array with <start> as start-index
for (int i = start; i < numbers.length; i++) {
/*
new Random().nextInt(numbers.length+1 ) gets a random number between 0 and numbers.length + 1
In our example, numbers.length+1 is 20. So we will get a random number between 0 and 20.
But we want to get random values between -1 and 19, so
new Random().nextInt(numbers.length+1 ) --> values between 0 to 20
rand = new Random().nextInt(numbers.length+1 ) -1 --> values between -1 to 19
*/
rand = new Random().nextInt(numbers.length+1 ) -1;
//Iterate through usedRand array and compare if current rand value has already been used yet.
for (int j = 0; j < usedRand.length; j++) {
if (usedRand[j] == rand) {
/*
If current rand value has already been used, recursively call shuffle again with the current index i
as new start-index
*/
return shuffled(numbers, usedRand, copyNumbers, true, i);
}
}
copyNumbers[rand] = numbers[i];
usedRand[i] = rand;
}
numbers = copyNumbers;
return numbers;
}
add a comment |
As I already pointed the errors out in the comments. Here is possible implementation of shuffle(). I commented the code based on my modifications.
If you happen to have questions, please feel free to ask!
public static void main(String args) {
//sample values
int numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
//First call of recursive function
int x = shuffled(numbers, null, null, false, 0);
//Print out values
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + "|");
}
}
public static int shuffled(int numbers, int usedRand, int copyNumbers, boolean newRandomValue, int current) {
//Initialisation
int rand = -1;
int start = 0;
//If function hasn't been called before, initialise.
if (usedRand == null) {
usedRand = new int[numbers.length];
Arrays.fill(usedRand, -1);
}
if (copyNumbers == null) {
copyNumbers = new int[numbers.length];
}
//If function has been called recursively, reassign the start-Integer for for-loop
if (newRandomValue) {
start = current;
}
//Iterate over numbers-array with <start> as start-index
for (int i = start; i < numbers.length; i++) {
/*
new Random().nextInt(numbers.length+1 ) gets a random number between 0 and numbers.length + 1
In our example, numbers.length+1 is 20. So we will get a random number between 0 and 20.
But we want to get random values between -1 and 19, so
new Random().nextInt(numbers.length+1 ) --> values between 0 to 20
rand = new Random().nextInt(numbers.length+1 ) -1 --> values between -1 to 19
*/
rand = new Random().nextInt(numbers.length+1 ) -1;
//Iterate through usedRand array and compare if current rand value has already been used yet.
for (int j = 0; j < usedRand.length; j++) {
if (usedRand[j] == rand) {
/*
If current rand value has already been used, recursively call shuffle again with the current index i
as new start-index
*/
return shuffled(numbers, usedRand, copyNumbers, true, i);
}
}
copyNumbers[rand] = numbers[i];
usedRand[i] = rand;
}
numbers = copyNumbers;
return numbers;
}
As I already pointed the errors out in the comments. Here is possible implementation of shuffle(). I commented the code based on my modifications.
If you happen to have questions, please feel free to ask!
public static void main(String args) {
//sample values
int numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18};
//First call of recursive function
int x = shuffled(numbers, null, null, false, 0);
//Print out values
for (int i = 0; i < x.length; i++) {
System.out.print(x[i] + "|");
}
}
public static int shuffled(int numbers, int usedRand, int copyNumbers, boolean newRandomValue, int current) {
//Initialisation
int rand = -1;
int start = 0;
//If function hasn't been called before, initialise.
if (usedRand == null) {
usedRand = new int[numbers.length];
Arrays.fill(usedRand, -1);
}
if (copyNumbers == null) {
copyNumbers = new int[numbers.length];
}
//If function has been called recursively, reassign the start-Integer for for-loop
if (newRandomValue) {
start = current;
}
//Iterate over numbers-array with <start> as start-index
for (int i = start; i < numbers.length; i++) {
/*
new Random().nextInt(numbers.length+1 ) gets a random number between 0 and numbers.length + 1
In our example, numbers.length+1 is 20. So we will get a random number between 0 and 20.
But we want to get random values between -1 and 19, so
new Random().nextInt(numbers.length+1 ) --> values between 0 to 20
rand = new Random().nextInt(numbers.length+1 ) -1 --> values between -1 to 19
*/
rand = new Random().nextInt(numbers.length+1 ) -1;
//Iterate through usedRand array and compare if current rand value has already been used yet.
for (int j = 0; j < usedRand.length; j++) {
if (usedRand[j] == rand) {
/*
If current rand value has already been used, recursively call shuffle again with the current index i
as new start-index
*/
return shuffled(numbers, usedRand, copyNumbers, true, i);
}
}
copyNumbers[rand] = numbers[i];
usedRand[i] = rand;
}
numbers = copyNumbers;
return numbers;
}
answered Nov 21 '18 at 11:35
dnsivdnsiv
347117
347117
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409543%2fcustom-shuffle-algorithm%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What does not work? even
Random
should follow a certain structure. If you really want to use a random value, you should mix in some real random variables, like time, date etc.– dnsiv
Nov 21 '18 at 10:08
I don't get a properly shuffled array. This is a school project so they do not look that close if our shuffling is "real" random. But of course I take any avice.
– Dovendyr
Nov 21 '18 at 10:29
1
Right now I see 2 possible errors. The first one is
rand = new Random().nextInt(numbers.length+1);
You need a random number from 0 to numbers.length-1, since arrays start with indexing at 0, but right now you will get a random number from 1 to numbers.length. You should get anIndexOutOfBoundsException
this way.– dnsiv
Nov 21 '18 at 10:50
The second possible error lies in this phrase
(usedRand[i] != rand)
. You're just comparing the current entry (i
) in usedRand with the current random value, if that entry already used this random number. But this way, you wont be able to access one entry a second time. You need to create a second for loop, which iterates through all entries of usedRand and compares their values with the current random number– dnsiv
Nov 21 '18 at 10:52