Loop, random number generator, then checker - java

trying to further my comprehension of loops and I found some questions online that I'm trying to complete but I got stuck on the second last one.
The original question was :
loop4(int val). This method uses a loop (for or while?) to do the following. Generate a random number between 1 and 10 (including 1 and 10) 10 times and count how many times val is generated, then print that number out.
What I've managed to do so far:
public int Loop4(int val){
for(int i = Math.random()*10; i<= 10; val!=0){
if (i == val) {
System.out.println(//I cannot for the life of me think of how I could constantly increment a +1 to this value because I only want to end up with 1 number in the end)
}
}
}

Simply create an count value and increment it.
public int Loop4(int val){
int count = 0;
for(int i = 0; i< 10; i++){
if ((int)(Math.random()*10) == val) {
count++;
}
}
System.out.println(count);
return count;
}

This code will do the trick:)
public int Loop4(int val){
int totalCount = 0;
for(int i = 0; i<= 10; i++){
int generatedNumber = (int)(Math.random()*10);
if (generatedNumber == val){
totalCount++;
}
}
System.out.print(totalCount );
}

You may want to try something like this. From your question you only want to loop 10 times and count how many times val is generated. You should create a total variable and increment each time the new random number == val.
Ex:
public int Loop4(int val){
int total = 0;
for(int i = 0; i <= 10; i++){
if ((int)(Math.random()*10) == val) {
total++;
}
}
return total;
}

There are a couple things in your code that you need to consider.
First, Math.random() returns a double, not an int so you have to cast it: (int) Math.random() (However casting this will cause some issue with rounding so do some research on that).
Second, the third argument in a for loop needs to be an iteration, not a comparison.
Ex: i++, ++i, --i
Third, create another variable int count = 0 that will count the number of times a number appears and place: count++ inside of your inner if statement and then have the System.out print it after your iteration.

Related

What is this method doing? (Arrays and random numbers)

My textbook gave me this code to help count the amount of times a certain number shows up in an array of integers. I tried to apply the code my textbook gave me to my assignment but it doesn't seem to be working. Basically, I have to generate 30 random integers in an array, with the upper bound being 15 and lower bond being -5.
I want to find out how many times a number in the array is equal to 0, 1, 2... all the way until 10. The first code is the one my textbook gave me. They also used a random number generator but instead of finding how many elements is equal to 0, 1, etc, they want to find how many times each number appears. (The scores array is simply the random number generator, and their upper bound is 100). The second code is mine.
int[] counts = new int [100];
for (int i = 0; i < scores.length; i++) {
int index = scores[i];
counts[index]++;
}
//This is my code
public static void main(String[] args) {
int []a = arrayHist ();
printArray (a);
}
public static int randomInt (int low, int high) {
int range = (high - low) +1;
return (int) (Math.random() * range) + low;
}
public static int[] randomIntArray (int x) {
int[] random = new int[x];
for (int i = 0; i< x; i++) {
random [i] = randomInt (-5, 15);
}
return random;
}
public static int[] arrayHist () {
int[] counts = new int [30];
int[] hist = randomIntArray (30);
for (int i = 0; i < 10 && i >= 0; i++) {
int index = hist[i];
counts[index]++;
}
return hist;
}
public static void printArray (int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.println (a[i]);
}
}
I'm supposed to be getting only 11 elements, but instead I get 30 random numbers again. Why is that?
I'll put some comments in your code, and see if you can spot where it goes wrong:
//take a histogram of the array. We're only going to count values between 0 and 10
//so 25th to 75 centiles, ignoring values that are lower than 0 or higher than 10
public static int[] arrayHist () {
//need to make an array of 11 numbers for the counts
int[] counts = new int [30];
//get an array of 30 random numbers
int[] hist = randomIntArray (30);
//loop over the whole array of 30 numbers
for (int i = 0; i < 10 && i >= 0; i++) {
//retrieve the random number into a variable temporarily
int index = hist[i];
//if the value is too low or too high, skip it
//else, store it in the counts array - the value from the random array
//serves as the index position in the counts array
counts[index]++;
}
//return the counts array
return hist;
}
What I've done with my comments is equivalent to designing the algorithm using the language you think in (English) and then you can translate it into the language you're learning (java). Very few developers think in the programming language they write. As a student I recommend you should ALWAYS write comments to explain your algorithm to yourself before you write code underneath the comments. You get points for writing comments (usually) so if you write them first then a) it helps you write the code and b) you don't have the tedious job of writing comments after you get the code working
Please please, for your own good/learning, try working out what is wrong from the above before looking at the spoilers(answers) below. Roll the mouse over the box to display the spoilers
//loop over the whole array of 30 numbers - YOU ONLY LOOP 10
for (int i = 0; i < 10 && i >= 0; i++) {
//if the value is too low or too high, skip it - YOU DIDN'T DO THIS CHECK
...
}
//return the counts array - YOU RETURNED THE WRONG ARRAY
return hist;
Edits in response to comments:
Checking a range
You'll have to check two limits, and hence it will need to be of one of the following forms:
if(x < 0 || x > 10) then don't do the count
if(!(x >= 0 && x <= 10)) then don't do the count
if(x >= 0 && x <= 10) then do the count
if(!(x < 0 || x > 10)) then do the count
Tests that use NOT - the exclamation mark ! - are typically a bit harder to read and understand, so try to avoid them is possible. Tests that are "positive minded" - i.e. they return a positive result rather than a negative that needs to be negated - are easier to read and understand.
A helpful tip for loops and methods, in terms of error checking, is to test for bad values that meet certain conditions, and if a bad value is encountered, then skip processing the rest of the loop (using the continue) keyword, or skip the rest of the method (by returning from it)
Doing this means that your if body (the bit between { and } ) doesnt get massive. Compare:
for(...){
if(test for bad values)
continue;
//50 lines long loop body
}
Is neater than doing:
for(...){
if(test for goodvalues){
//50 lines long loop body
}
}
If you use the bottom pattern, you can end up after several IFs in a real indented mess, with { and } all over the place and your code is way over to the right hand side of the screen:
for(...){
//code
if(...){
//code
if(...){
//code
if(...){
//code
if(...){
//code
if(...){
//code
if(...){
//code
}
//code
}
//code
}
//code
}
//code
}
//code
}
//code
}
Keeping indent levels to a minimum helps make your code more readable
Hence, I recommend in your case, that rather than test for the value being inside the range 0 to 10 and doing something with it, you adopt the form "if value is OUTSIDE" the range 0 to 10, skip doing the rest of the loop
Your arrayHist() method just returns the array with the random numbers. It should be more like this:
public static int[] arrayHist() {
// generate array with random numbers
int[] hist = randomIntArray(30);
// initialize the array for counting
int[] counts = new int[11];
// step through the random numbers array and increase corresponding counter if the number's values is between 0 and 10
for (int j = 0; j < hist.length; j++) {
int number = hist[j];
if (number > -1 && number < 11) {
counts[number]++;
}
}
return counts;
}

Calculating the factorial of every element in an integer array

I need to create a Method that has 2 parameters in Java, upperborder and lowerborder. This method must create an array from the number 2 to the number 10.
Then I must implement another method, that calculates the factorial for a given number.
Then I must implement a third method that calculates the factorial for every element in the created array and test all these methods in a TestClass.
I know how to do this, but apparently I'm making some kind of a mistake in my code and it gives me the StackOverflow exception. I read the code a couple of times, but I can't seem to quite understand where I'm wrong.
package fakultaetinarray;
public final class FakultaetinArray{
private int i;
private int[] a;
private int j;
public FakultaetinArray(){
System.out.println("Given array : ");
createArray(1, 9);
System.out.println("Factorial for every element : ");
FakinArray();
}
public int fakRe(int n){
if(n == 1){
return n;
}
return n * fakRe(n - 1);
}
public void createArray(int untergrenze, int obergrenze){
this.a = new int[obergrenze];
for(this.j = 1; j <= a.length; j++){
a[i] = j + 1;
System.out.println(a[i]);
}
}
public void FakinArray(){
a[0] = 2;
for(i = 1; i < a.length; i++){
int fak = fakRe(a[i]);
a[i] = fak;
System.out.println(fak);
}
}
}
The reason you're getting StackOverflowErrors is due to your recursive method not having a case when n == 0.
The reason that your values are coming in as 0 is due to how you're constructing your loop.
for(this.j = 1; j <= a.length; j++){
a[i] = j + 1;
System.out.println(a[i]);
}
It's unclear why you're using j here at all, and i is initialized to its default value of 0, so in all reality, you're only ever filling one element of your array with a positive value and all of the others are at zero.
You need to reconsider how your loops are constructed. I would strongly encourage you not to make them fields, but declare them as part of the loop construct instead.
if(n == 1){ is not a strong enough condition to block the recursion: n can go below 1. In your particular case, you have a situation where n is 0.
Consider unwinding the recursion to a simple loop in any case. As a rule of thumb, recursion is not good for O(N) stuff.

How to find the next available slot in an array?

I was practicing on CodingBat when I came across this problem I couldn't quite get right. Given an array of positive integers, I must create an array of length "count" containing the first even numbers from the original array. The original array will contain at least "count" even numbers. My code is below, though I know that everything below the first if statement does not work and the "counter" variable is basically useless.
public int[] copyEvens(int[] nums, int count) {
int counter = 0;
int[] countArr = new int [count];
for (int i = 0; i < nums.length; i++) {
if (nums[i] % 2 == 0) {
//what to put here?
}
}
return countArr;
}
any help would be much appreciated.
The following is incorrect:
if (i == count) {
This checks the position in the input array, rather than the position in the output array, against count.
public int[] copyEvens(int[] nums, int count) {
int counter = 0;
int[] countArr = new int [count];
for (int i = 0; i < nums.length && counter < count; i++)
if ((nums[i] % 2) == 0)
countArr[counter++] = nums[i];
return countArr;
}
School stuff... right?
I think you should be comparing the
counter... which starts at 0 .. so you need to add 1 as I am pretty sure count does not include 0 as an index.
Thus,
if((counter+1) ==count)
should replace the original.

How do I write a method to calculate the mode of an array?

I'm trying to write a method to calculate the mode of an array. I'm trying to write it with only two arrays. For some reason, the output I get is the size of the array --> 100. So far this is what I have:
public static int mode(int[ ] grades) {
int mode[ ] = new int [101];
int value = 0;
for (int i = 0; i < value; i++)
mode[grades[ i ] ]++; //this part really confuses me and I don't know how to interpret this.
//can someone please explain this to me too. I know this is the only...
int max = 0; //...way to get it with 2 arrays.
for(int i = 0; i < 101; i++) {
max = mode[ i ];
value = i;
}
return value;
}
grades can be in the range [0,100], which is 101 numbers (hence the size of 101).
for (int i = 0; i < value; i++)
mode[grades[i]]++;
grades[i] gets the number at slot i. Let's say that's 85. This give us:
mode[85]++, which increments the number of times we've seen the grade 85.
After this is complete, we iterate through mode and see which slot has the highest value, this value cooresponds to the mode, since mode simply keeps track of the number of times we encounter each score.
However, the second part is incorrect, you only want to update max, value if the current element is > max, ie:
int max = 0;
for(int i = 0; i< 101; i++)
{
if (mode[i] > max)
{
max = mode[i];
value = i;
}
}

Why aren't my variables being altered in my loops?

I've got a method that is meant to work out the group of elements of a 3D array with the highest combined value. I've got 3 nested loops that I'm using to go through my array, and as certain conditions are met I want to alter the variables. However none of the variables are being used. I ant to alter int y and int m to whatever iteration of the for loop it's on if sum exceeds total.
Thanks. Here is my code:
public void wettestMonth(){
double sum = 0;
double total = 0;
int y = 0;
int m = 0;
//cycle through each year and month
for(int i = 0; i < 34; i++){
for(int j = 0; j < 12; j++){
//reset the current month to 0 after each month has been cycled through
sum = 0;
for(int k = 0; k < 31; k++){
//only add the record if the current entry is not null (-99.99)
if(sortedData[i][j][k] != -99.99){
sum += sortedData[i][j][k];
}
//if the current month is wetter than the wettest one, make the current month the new wettest one
if(sum > total){
total = sum;
y = i;
m = j;
}
}
}
}
JOptionPane.showMessageDialog(null, "The wettest month on record was " +m +y, "Wettest Month.", JOptionPane.PLAIN_MESSAGE);
}
Edit, I just reconstructed it with while loops instead and I'm getting an out-of-bounds error on what appears to be the problem line, if(sortedData[i][j][k] != -99.99)
Edit 2, here is where I declare and initialise sortedData[][][]
public class GetData {
//initialises an array that holds 34 years, each with 12 months, each of which has 31 entries for reach day
public double[][][] sortedData = new double[34][12][31];
//initialises a new scanner named rainFile
private Scanner rainFile;
//method for opening the file
public void openFile() {
try{
//as the input for the scanner we use the rainfall file
rainFile = new Scanner(new File("C:\\\\Users\\\\admin\\\\Documents\\\\NetBeansProjects\\\\110_term3\\\\WeatherDataFiles\\\\rainfall.txt"));
}
catch(Exception e){
//if no file has been found a JOptionPane will display an error message telling the user to double-check the file path
JOptionPane.showMessageDialog(null, "Check the file path is correct.", "No file found!", JOptionPane.ERROR_MESSAGE);
}
}
//method for reading the file
public void readFile(){
//ignore the first 3 lines in the data file
String dump1 = rainFile.nextLine();
String dump2 = rainFile.nextLine();
String dump3 = rainFile.nextLine();
//these nested for loops will dictate the current index of sortedData
for(int i = 0; i < 34; i++){
for(int j = 0; j < 12; j++){
//ignores the year and month at the start of each line
String dump4 = rainFile.next();
String dump5 = rainFile.next();
//this final nested for loop dictates the final index of sortedData
for(int k = 0; k < 31; k++){
//asigns the current value of scanner rainFile to String a
String a = rainFile.next();
//converts the String a to a double type and then assigns it to the current index of sortedData
double dbl = Double.parseDouble(a);
sortedData[i][j][k] = dbl;
}
}
}
}
Have you tried printing out the sum for each month?
The most obvious possibility is that your sums are always less than 0 because of a buggy equality check.
For this line,
sortedData[i][j][k] != -99.99
It will be true unless the value is exactly what -99.99 rounds to. This may be unintended. For example, if you are constructing the value through floating point math somehow, you most likely won't get exactly the same value due to rounding errors. Furthermore, use of a weird sentinel value like this is error prone and less readable. You're better off using an obvious sentinel value like NaN if you can.
To see the problem, consider what would happen if your values are slightly different. Say, -99.99000001. Then after the first day, you already have a negative value. After a month, the sum will be approximately -3099.69000031, much less than 0. Since the sum is always negative, it is never better than the original total 0, so the best never gets updated.
You probably also want to move the update check outside of the day loop. This part looks like it's supposed to use the sum for the whole month, but you are running it with the partial sum of every day of the month. It won't actually cause incorrect results as long as the values being added are nonnegative (but they probably aren't due to the aforementioned bug), but you should still fix it.
if(sum > total){
total = sum;
y = i;
m = j;
}
I don't see anything wrong on your code.
Maybe the following condition never evals to true?
if(sortedData[i][j][k] != -99.99)
Carefully, reviewed the first code snippet that has been provided, it appears to me that you have been doing if check for the size inside the for loop, moved the for loop vars to the finals, added some further comments.
You could try and run your swing app through the Eclipse debug and see what results you get at each line in your application ?
Would expect it to work given correct input 3D array))
/**
* This method calculates the wettest month during the certain period of time.
*/
public void wettestMonth(){
double sum = 0;
double total = 0;
int y = 0;
int m = 0;
final int numberOfYearsToCycleThrough = 34;
final int numberOfMonthsToCycleThrough = 12;
//cycle through each year and month
for (int i = 0; i < numberOfYearsToCycleThrough; i++) {
for (int j = 0; j < numberOfMonthsToCycleThrough; j++) {
sum = 0;
for (int k = 0; k < 31; k++){
//only add the record if the current entry is not null (-99.99)
if (sortedData[i][j][k] != null && sortedData[i][j][k] != -99.99) {
sum += sortedData[i][j][k];
}
}
//if the current month is wetter than the wettest one, make the current month the new wettest one
if (sum > total) {
total = sum;
y = i;
m = j;
}
}
}
JOptionPane.showMessageDialog(null, "The wettest month on record was " +m +y, "Wettest Month.", JOptionPane.PLAIN_MESSAGE);
}

Categories

Resources