I am trying to make a program where I can input the size of a 2D array, the highest number in a 2D array, and the most amount of a certain number in the 2D array, and then fill it with random numbers in between 1 and the highest number. In my code, I specify that the max amount of times a number should repeat is 4, yet my output doesn't match that. Any suggestions?
This is my code:
class Main {
public static void main(String[] args) {
System.out.println(fill(6, 9, 4));
}
public static String fill(int size, int max, int most) {
int[][] list = new int[size][size];
int count = 0;
for (int i = 0; i < list.length; i++) {
for (int j = 0; j < list[i].length; j++) {
int x = (int)((Math.random()* max) + 1);
int y = 0;
count = 0;
for (int k = 0; k < list.length; k++) {
for (int l = 0; l < list[k].length; l++) {
if(list[k][l] == x) count++;
}
}
if(count < most) {
list[i][j] = x;
} else {
while(true) {
y = (int)((Math.random()* max) + 1);
if(y != x) break;
}
list[i][j] = y;
}
System.out.print(list[i][j] + " ");
}
System.out.println();
}
return "";
}
}
And this is my output:
9 4 6 1 9 1
7 1 4 4 3 2
6 1 4 2 7 9
5 9 4 7 2 5
3 5 3 5 7 4
3 8 8 6 2 6
Problem: There are 6 "4"s and 2 "8"s
You generate a random number.
You then check if this random number is 'invalid', in the sense that it's been used too many times.
Then, you generate a new random number, check that this isn't the same as your previous number, and then just roll with that. You are failing to check if this number, too, is 'overloaded'. So, what could have happened here is that your algorithm picked '9', counts 9s, finds 4 of them, rolls up a new random number, 9 again, so it rolls yet another number, 4, and just puts 4 in, without checking again.
Rejigger your while loops.
Or, better yet, make a utility class to offload the job of generating a random number, but not a number that's already been returned N times, to a separate class, so that you can untangle this messy code.
Your method
while(true) {
y = (int)((Math.random()* max) + 1);
if(y != x) break;
}
does not check that count of y did not already reached most
Your Issue is here:
while(true) {
y = (int)((Math.random()* max) + 1);
if(y != x) break;
}
list[i][j] = y;
This basically just rules out that x will be repeated more than most, but not y.
On a side note, I recommend using hash maps to keep track of the occurrences instead of iterating over the whole array over and over.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
How do I get the kth combination inNCR. without iterating through all possible outcomes. e.g. say I have 3C2 for 3 positions and 2identical-items. I am aware it's [011],[101] and [110]. how do I get e.g. the 2nd term(k=1) which is [101] using a method?
constraints(R < N k >= 0 and k < P where P = NCR).
NB:[101] is the 2nd term(in ascending/lexicographical order) because 011 = 3,101 = 5 ,110 = 6
in decimal. so basically the goal is to get what number k in NCR is,
because every kth output from NCR can be represented as a number.
Yes, you are correct when you say:
because every kth output from NCR can be represented as a number.
There is a bijection from the set of integers 1 to # of combs/perms to the entire set of combs/perms. Finding the specific index of a particular comb/perm is sometimes referred to as getting the rank. According to the example that you have in your question, these are ordinary permutations. Moreover when you mention ascending order, you are referring to the lexicographical order.
It is a straightforward exercise in counting to obtain the nth ordinary permutation of a given set. We first need to obtain the total number of permutations using the well established formula:
P(n, r) = n! / (n - r)!
This next part is the key observation that allows us to quickly obtain each element of our target permutation.
If we look at all permutations of our set of n choose r, there will be n groups that are only different by a permutation of the n elements.
For example, if we look at the first two group of the permutations of [0 1 2 3] choose 3, we have:
[,0] [,1] [,2]
[0,] 0 1 2
[1,] 0 1 3
[2,] 0 2 1
[3,] 0 2 3
[4,] 0 3 1
[5,] 0 3 2
[6,] 1 0 2
[7,] 1 0 3
[8,] 1 2 0
[9,] 1 2 3
[10,] 1 3 0
[11,] 1 3 2
Note that the last permutations are simply the first 6 permutations of the set [1 0 2 3].. that is, 0 is mapped to 1, 1 is mapped to 0, and the final 2 elements are mapped to themselves.
This pattern continues as we move to the right only instead of n identical groups, we will get n - 1 similar groups for the second column, n -2 for the third, and so on.
So to determine the first element of our permutation, we need to determine the 1st group. We do that by simply dividing the number of permutations by n. For our example above of permutations of 4 choose 3, if we were looking for the 15th permutation, we have the following for the first element:
Possible indices : [0 1 2 3]
P(4, 3) = 24
24 / 4 = 6 (elements per group)
15 / 6 = 2 (integer division) 2 means the 3rd element here (base zero)
Now that we have used the 3rd element, we need to remove it from our array of possible indices. How do we get the next element?
Easy, we get our next subindex by subtracting the product of the group we just found and the elements per group from our original index.
Possible indices : [0 1 3]
Next index is 15 - 6 * 2 = 3
Now, we just repeat this until we have filled all entries:
Possible indices : [0 1 3]
Second element
6 / 3 = 2 (elements per group)
3 / 2 = 1
Next index is 3 - 3 * 1 = 0
Possible indices : [0 3]
Third element
2 / 2 = 1
0 / 1 = 0
So our 15th element is : [2 1 0]
Here is a C++ implementation that should be pretty easy to translate to Java:
double NumPermsNoRep(int n, int k) {
double result = 1;
double i, m = n - k;
for (i = n; i > m; --i)
result *= i;
return result;
}
std::vector<int> nthPermutation(int n, int r, double myIndex) {
int j = 0, n1 = n;
double temp, index1 = myIndex;
std::vector<int> res(r);
temp = NumPermsNoRep(n, r);
std::vector<int> indexVec(n);
std::iota(indexVec.begin(), indexVec.end(), 0);
for (int k = 0; k < r; ++k, --n1) {
temp /= n1;
j = (int) std::trunc(index1 / temp);
res[k] = indexVec[j];
index1 -= (temp * (double) j);
indexVec.erase(indexVec.begin() + j);
}
}
These concepts extends to other types of combinatorial problems, such as finding the nth combination, or permutation with repetition, etc.
The time complexity is O(kn), space is O(n)
public static void main(String[] args) {
//n = 4, r = 2, k = 3
int[] ret1 = getKthPermutation(4, 2, 3);
//ret1 is [1,0,0,1]
//n = 3, r = 2, k = 1
int[] ret2 = getKthPermutation(3, 2, 1);
//ret2 is [1,0,1]
}
static int[] getKthPermutation(int n, int r, int k) {
int[] array = new int[n];
setLastN(array, r, 1);
int lastIndex = n - 1;
for(int count = 0; count < k; count++) {
int indexOfLastOne = findIndexOfLast(array, lastIndex, 1);
int indexOfLastZero = findIndexOfLast(array, indexOfLastOne, 0);
array[indexOfLastOne] = 0;
array[indexOfLastZero] = 1;
//shortcut: swap the part after indexOfLastZero to keep them sorted
int h = indexOfLastZero + 1;
int e = lastIndex;
while(h < e) {
int temp = array[h];
array[h] = array[e];
array[e] = temp;
h++;
e--;
}
}
return array;
}
//starting from `from`, and traveling the array forward, find the first `value` and return its index.
static int findIndexOfLast(int[] array, int from, int value) {
for(int i = from; i > -1; i--)
if(array[i] == value) return i;
return -1;
}
//set the last n elements of an array to `value`
static void setLastN(int[] array, int n, int value){
for(int i = 0, l = array.length - 1; i < n; i++)
array[l - i] = value;
}
This is an adaption of the very typical "find the kth permation" algorithm.
I will try to explain the general idea (yours is a special case as there are only two types of elements: 0 and 1).
Lets say I have [2,1,6,4,7,5]. What is the next smallest permutation that is bigger than the current one? Why do I concern the next smallest permutation bigger than current one? Because if you start with the smallest permutation [1,2,4,5,6,7] and you repeat the action (find the smallest bigger than current) k times, you will find k+1 th smallest permutation.
Now, since the one I am looking for needs to be bigger than current one, I need to increment the current one. To keep the incrementation as small as possible, I am going to try to modify 5 (last one). Now, I cannot just change 5 to a random value, I can only swap it with some digit before it.
If I swap 5 with a bigger number before it, say 7, then I will get [2,1,6,4,5,7], which is smaller than current one. Now obviously I need to swap 5 with some smaller digit before it, but which one? If I swap 5 with 2, I get [5,1,6,4,7,2], this increment is too big. I need to swap 5 with a "lower digit" to keep the increment as small as possible. Thats leads us to find the first(lowest) digit (from right to left) that is smaller than 5. In this case I would need to swap 5 with 4 and get [2,1,6,5,7,4]. This way, I can make the impact of "swap" small. Now the prefix is decided [2,1,6,5. There is no smaller prefix. We need to deal with suffix 7,4]. Clearly, if we sort the suffix and make it 4,7], then we are done.
In our case, there are two differences:
1. we need to swap the last 1, because you cannot make the permutation bigger by swapping the a zero with any digit before it.
2. we can always sort the suffix using a shortcut as shown in the code. I will leave it to you:)
public static String lexicographicPermutation(String str, long n) {
final long[] factorials = { 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600 };
n--;
char[] arr = str.toCharArray();
for (int i = 0; i < arr.length - 1; i++) {
long fact = factorials[arr.length - i - 2];
long p = i + n / fact;
n %= fact;
for (int j = i + 1; j <= p; j++)
swap(arr, i, j);
}
return new String(arr);
}
private static void swap(char[] arr, int i, int j) {
char tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
You can replace STR with required string. In the given example, 1st permutation is "abcdefghijklm" (this is a string with 13 chars), 13!st permutation is reverse string "mlkjihgfedcba" and 100st permutation is "abcfklgmeihjd".
To realise this soulution just google Factorial number system. This is a key to solve this problem. This is a Project Euler: Problem 24.
Demo:
for(int i = 1; i <= 6; i++)
System.out.println(lexicographicPermutation("110", i));
1 - 110
2 - 101
3 - 110
4 - 101
5 - 011
6 - 011
for(int i = 1; i <= 6; i++)
System.out.println(lexicographicPermutation("abc", i));
1 - abc
2 - acb
3 - bac
4 - bca
5 - cab
6 - cba
I am having trouble getting the percentage of the frequency to print. Below is the question:
Write a program to simulate the rolling of two dice. The program should use an object of class Random once to roll the first die and again to roll the second die. The sum of the two values should then be calculated. Each die can show an integer value from 1 to 6, so the sum of the values will vary from 2 to 12, with 7 being the most frequent sum and 2 and 12 being the least frequent sums. Your application should roll the dice 36,000 times. Use a one dimensional array to keep track of the number of times each possible sum appears. Display the results in tabular format. Determine whether the totals are reasonable (e.g., here are six ways to roll a 7, so approximately one-sixth of the rolls should be 7). Sample output:
Sum Frequency Percentage
2 1027 2.85
3 2030 5.64
4 2931 8.14
5 3984 11.07
6 5035 13.99
7 5996 16.66
8 4992 13.87
9 4047 11.24
10 2961 8.23
11 1984 5.51
12 1013 2.81
This is my code so far:
import java.util.Random;
public class dice_roll {
public static void main(String [] args){
Random rand = new Random();
int dice1, dice2;
int [] frequency = new int [13];
int [] rolls = new int [13];
int sum;
double percentage;
for (int i = 0; i <= 36000; i++) {
dice1 = rand.nextInt(6)+1;
dice2 = rand.nextInt(6)+1;
frequency[dice1+dice2]++;
sum = dice1 + dice2;
}
System.out.printf("Sum\tFrequency\tPercentage\n");
for (int i = 2; i < frequency.length; i++) {
percentage = (frequency[i] * 100.0) / 36000;
System.out.printf("%d\t%d\t\n",i,frequency[i]);//this line here
}
}
}
First of all, your for loop is off by 1:
for (int i = 0; i <= 36000; i++) {
// ^
// remove this "=" or you will loop 36001 times
Your sum seems redundant, so remove that as well.
I think you just don't know how to format the output so that the floats correct to 2 d.p. right?
It's easy. Just add do %.2f!
Your printf will be like:
System.out.printf("%d\t%d\t%.2f\n",i,frequency[i], percentage);
Another problem with your code is that it might produce unaligned stuff. It also does not align the values to the right as the sample output shows. To fix this, you also just need to change the printf. Like this:
System.out.printf("%3d\t%9d\t%10.2f\n",i,frequency[i], percentage);
If you want to read more about how printf works, list here.
Stealing from this answer: we can use padRight which is defined as:
public static String padRight(String s, int n) {
return String.format("%1$-" + n + "s", s);
}
and do:
System.out.printf("Sum\tFrequency\tPercentage\n");
for (int i = 2; i < frequency.length; i++) {
String s = padRight(String.valueOf(i), 4);
String f = padRight(String.valueOf(frequency[i]), 12);
percentage = (frequency[i] * 100.0) / 36000;
String p = String.format("%.2f", percentage); // This formatting will keep two digits after the point
System.out.printf("%s%s%s\n", s ,f, p);
}
OUTPUT (example)
Sum Frequency Percentage
2 992 2.76
3 2031 5.64
4 3034 8.43
5 3947 10.96
6 4887 13.58
7 5948 16.52
8 4965 13.79
9 4051 11.25
10 3014 8.37
You can play with it and remove the \t from the first line and use spaces instead in order to create the amount of spacing you want between the columns and then pass the second parameter in the calls to padRight accordingly.
I would like to know that as I am learning Java from tutorials and there is a program for rolling the dice 1000 times and printing its frequency.
import java.util.Random;
public class RollDicewitharray {
public static void main(String[] args) {
Random r=new Random();
int arr[]= new int[7];
System.out.println("diceNo.\tFrequency");
for (int roll = 1; roll < 1000; roll++) {
++arr[1+r.nextInt(6)]; /* this line */
}
for (int i = 1; i < arr.length; i++) {
System.out.println(i+"\t"+arr[i]);
}
}
To summarise all, this program simulates rolling a six-sided dice 1000 times and records the occurrences of each number rolled.
public static void main(String[] args) {
Random r=new Random();
int arr[]= new int[7]; //Craete an array with 7 int elements
System.out.println("diceNo.\tFrequency");
for(int roll=1;roll<1000;roll++){ //Loop 1000 times
++arr[1+r.nextInt(6)]; //Randomly pick arr[1] to
} //arr[6] and plus one to it
for(int i=1;i<arr.length;i++){
System.out.println(i+"\t"+arr[i]); //Print occurrence of 1-6
}
}
Breaking the following code:
++arr[1+r.nextInt(6)]; //r.nextInt(6) will be evaluated first:
r.nextInt(6) returns random value of (0-5), so you have:
++arr[1+(random 0 to 5)]; //+1 will be evaluated next:
So you are generating a random value of 1-6. Next you add 1 to the array:
++arr[random 1 to 6]; //+1 to arr[1] or arr[2] or arr[3] or arr[4] or arr[5] or arr[6]
It can now be interpreted as:
arr[1] +=1; //or
arr[2] +=1; //or
arr[3] +=1; //or
arr[4] +=1; //or
arr[5] +=1; //or
arr[6] +=1;
So after running your program, if your array looks like:
[0] [1] [2] [3] [4] [5] [6] Array index
+---+---+---+---+---+---+---+
| 0 |175|170|165|170|165|175| <-- arr
+---+---+---+---+---+---+---+
It means 1 was rolled 175 times,
2 was rolled 170 times,
3 was rolled 165 times,
and so on..
r.nextInt(6) produces a random integer between 0 and 5. Adding 1 to it gives you a random dice roll between 1 and 6.
The arr array is used to count the number of times each dice roll occurred, so ++arr[1+r.nextInt(6)] increments the count for the current roll.
When the first loop is done, arr[1] holds the number of 1s, arr[2] the number of 2s, and so on.
1 + r.nextInt(6) draws a random number from 1 to 6 inclusive.
++arr[1 + r.nextInt(6)]; increments that element of the array arr.
So a frequency distribution of dice-rolls is built up. The zeroth element of the array is not used. Which is why it's set up with 7 elements. Wasteful perhaps? You tell me.
r.nextInt(6) - get the random number < 6;
arr[1+r.nextInt(6)] - get an item from the array arr with index 1 + random number from step 1;
++arr[1+r.nextInt(6)] increase the item from step 2 by 1
This line is equivalant to:
int number = r.nextInt(6); // Generates a random number between 0 and 6(exclusive)
int index = number + 1; // Since the faces of dice has value from 1 to 6
int value = arr[index];
and increases this number by 1;
Lets say I have a number 1-5, now if I have 2, I want 4 as an output, if I had 3 then have 3 as the output, if I have 1 then 4 as the output. Here is a chart of what I want:
1-10 Chart:
Give 1 return 9
Give 2 return 8
Give 3 return 7
Give 4 return 6
Give 5 return 5
What algorithm do I use for such a thing?
I don't see that you need an algorithm as much. What you have is:
InverseNumber = (myCollection.Length - MySelection);
Thats all you need for even numbers.
With a collection of 1 - 6 for example:
Give 2; 6 - 2 = 4. Also if given 4, 6 - 4 = 2.
You will need a slightly different problem for odds:
1 - 5; with 1 given 1 is at index 0, the opposite is 5, 2 given and the inverse ( 5 - 2) is 3. But if 3 is given, there is no inverse. So you might want to also add a catch for:
if (((myCollection.Length *.5).Round) == mySelection) { //Inverse does not exist!!!}
If you are using just integers, and not arrays of numbers then just replace the myCollection.Length with the upperbound integer.
I think the following code will work for what you need:
int a[] = new a[length_needed];
int counter = length_needed;
for(int c = 0; c < length_needed; c++) {
a[c] = counter;
counter--;
}
int number_inputed;
for(int c = 0; c < length needed; c++) {
if(c == number_inputed) System.out.println(a[c]);
}
Let's say you are giving max number as input. Then you are going to have 0-n numbers. For ex., if 9 is the max number you will have 0-9.
Then you can do something like this:
public static void main(String[] a) {
int max = a[0]; // read values from cmd line args
int forWhichNum = a[1]; //for which number we need its inverse
Sop(max- forWhichNum);
}
Integer value = 2;
Integer maxValue = 6;
Integer reverseCounter = 0;
for (int i = maxValue; i > 0; i--) {
reverseCounter++;
if (i == value) {
return reverseCounter;
}
}