Mailman mailbox problem using 2d arrays and for loops - java

This program is supposed to create a boolean array with 150 "mailboxes". The first for loop is supposed to set them all to "closed" defined by false. The second for loop should start at the second mailbox, index[1] and open every even. The third and fourth for loops are supposed to start at the third mailbox index[2] and open every third then after reaching the 150th return to the fourth for loop and open every third. The final for loop is supposed to print out which for loops are closed. I haven't been able to get it to run past line 17.
public class CS2LAB1 {
public static void main(String[] args)
{
boolean[] mailboxes = new boolean[149];
/*this function sets all mailbox doors to closed*/
for(int i = 0; i <= mailboxes.length; i++)
{
mailboxes[i] = false;
}
/*This function uses a for loop to begin at mailbox 2 and open every even mailbox
*/
for(int count = 1; count <= mailboxes.length; count = count + 2)
{
mailboxes[count] = true;
}
/*This function starts at 3 and opens every 3rd mailbox, next it goes to 4 and opens every 3rd mailbox followed by the 4th then 5th then 6th */
for(int count2 = 2; count2<=mailboxes.length; count2++)
{
for(int count3 = count2; count3 <= mailboxes.length; count3 = count3 + count2)
{
if(mailboxes[count2] = true)
{ mailboxes[count2] = false;}
else{ mailboxes[count2] = true;}
}
}
/*This function outputs all the closed doors*/
for(int print =0; mailboxes.length>=print; print++)
if(mailboxes[print] = false)
{
System.out.println("Mailbox" + print++ + "is closed" );
}
}
}
Update: I went through and changed the boolean values so that closed is now equivalent to true and open is for false off the basis that any boolean array is already set to false. I did not get the correct output instead the program outputs all even mailboxes as opened
moreover I believe I've narrowed the problem down to the nested for loop. The if statements within are never used and I do not understand why. Any ideas?
for(int count2 = 2; count2<= 149; count2++)
{
for(int count3 = 2; count3 <= 149; count3 = count3 + 3)
{
if(mailboxes[count3] = false)
{ mailboxes[count3] = true;}
else{ mailboxes[count3] = false;}
}
}

Your first for loop is probably throwing an IndexOutOfBoundException. Array's in Java are 0-indexed meaning that they start at 0 and go all the way up until Array.length - 1. Therefore in order to traverse an entire array one would iterate from for(int i = 0; i < arr.length; i++).
Your for loop is traversing from for(int i = 0; i <= mailboxes.length; i++). Meaning the last value for index i is 149 when the arrays indexes go from [0, ..., 148].

Related

locker puzzle using a boolean array

I don't want the answer I want to know what I a doing wrong. below is the question
A school has 100 lockers and 100 students. All lockers are closed on the first day of school. As the students enter, the first student, denoted S1, opens every locker. Then the second student, S2, begins with the second locker, denoted L2, and closes every other locker. Student S3 begins with the third locker and changes every third locker (closes it if it was open, and opens it if it was closed). Student S4 begins with locker L4 and changes every fourth locker. Student S5 starts with L5 and changes every fifth locker, and so on until student S100 changes L100.
After all the students have passed through the building and changed the lockers, which lockers are open? Write a program to find your answer. The program should display the answer
and my code is
public class LockerPuzzle {
public static void main(String[] args) {
boolean[] lockers = new boolean[100];
// first all the lockers are closed. false represents closed
for (int i= 0; i<lockers.length;i++){
lockers[i]= false;
System.out.println(lockers[i]);
}
// then the first student comme and opens all the lockers
for (int i = 0; i< lockers.length; i++){
lockers[i] = true;
}
int locker = 0;
for(int j = 1; j<= lockers.length; j++){
for(int k =j; k< lockers.length; k =k+j){
if(lockers[k] == false){
lockers[k]=true;
}else{
lockers[k]= true;
}
}
}
// this prints all the open lockers.
for(int S=0; S<lockers.length; S++)
{
if (lockers[S] == true) {
System.out.println("Locker " + S + " Open");
}
}
}
}
and the output for me is saying all lockers are open.
I noticed this block:
if(lockers[k] == false){
lockers[k]=true;
}else{
lockers[k]= true;
}
which will set lockers[k] to true either way. You can avoid this sort of typo by just replacing it with lockers[k] = !lockers[k].
While I agree with this comment, I still think you would benefit from some general tips and directions that will reduce your code size.
As #onkarruikar noted, you don't have to manually initialise your lockers table. new boolean[100] creates an array with all elements set to false.
As #MathiasRaba has mentioned, you don't need an if/else block to open/close a locker. Simply set the locker to its opposite value.
Now lets consider the actual simulation of locking and unlocking. i-th student begins with the i-th locker and then proceeds on to a locker that is i + 1 elements away. Something like this:
boolean[] lockers = new boolean[100];
for (int i = 0; i < 100; i++) {
for (int j = i; j < 100; j += i + 1) {
lockers[j] = !lockers[j];
}
}
Note that the numbering of students/lockers is zero based in order to play better with array indices.
No need to start with 1. Zero indexing is good to go.
public class MainClass {
public static void main(String[] args) {
boolean LockerList [] = new boolean [100];
for (int s=0; s<100; s++) // student loop [0..99]
for (int l=s; l<100; l=l+(s+1)) // locker loop [0..99]
LockerList[l] = !LockerList[l]; // toggle value
// display open-lockers
for (int x=0; x<100; x++)
if (LockerList[x] == true)
System.out.printf("Locker %d is open\n", x+1);
}
}
// hints: s=5 is the 6th student so he will hop six boxes i.e. s+1
// And do not display last locker as 99, it should be 100 i.e. x+1
Just a suggestion, you do not have to write following code.
// first all the lockers are closed. false represents closed
for (int i= 0; i<lockers.length;i++){
lockers[i]= false;
System.out.println(lockers[i]);
}
Array elements are automatically initialized to defaults. In case of boolean the default value is false

Using return vs While(condition) methods To Break Loops

I'm doing a little google interview question. Find the pair of numbers in a loop that add up to the number given. I found the numbers 2 and 6 that make up 8 so I say match = true so that the while loop stops, however it still proceeds until it finds the second which is 6 and 2 however, those numbers I have already found just the other way around and I had expected my loop to break as my if statement states if there is any 2 numbers that give the sum, match = true therefore terminating the loop, I guess I am wrong though.
However, if I get rid of the while statement and just return; once a match is found it breaks without looking for the second match (which I want it to).
Why is this happening, the logic of both seems the exact same to me.
Using the while(condition) Method
public class Main {
public static void main(String[]args){
int[] list = new int[]{1,2,1,1,1,6};
boolean match = false;
int sumNeeded = 8;
while(!match){
for(int i = 0; i < list.length; i ++){
for(int j = (list.length -1); j >= 0; j --){
if(list[i] != list[j]){
if(list[i] + list[j] == sumNeeded){
System.out.println("The numbers are = " + list[i] + " & " + list[j]);
match = true;
}
}
}
}
}
}
}
Using return
public class Main {
public static void main(String[]args){
int[] list = new int[]{1,2,1,1,1,6};
int sumNeeded = 8;
for(int i = 0; i < list.length; i ++){
for(int j = (list.length -1); j >= 0; j --){
if(list[i] != list[j]){
if(list[i] + list[j] == sumNeeded){
System.out.println("The numbers are = " + list[i] + " & " + list[j]);
return;
}
}
}
}
}
}
In your while-loop implementation, if the array doesn't have the desired pair at all it would result in an infinite loop. There is no need for the while statement in your solution.
After you enter into the while loop, you look for all the possible pairs in the array and then check for their sum. If it equals the desired sum, you make the boolean variable match as true.
But, until the nested for loop is completely executed (i.e., all the possible pairs are checked) we do not check for the while condition. The entire nested for loop is executed in one iteration of the while loop. Then, the while loop condition is checked again.
As by the end of the first iteration of the while loop all the possible pairs are accounted for, there is no need for a while loop.
Moreover, there are other logical errors in your implementation. The correct brute-force implementation is as follows:
public class Main {
public static void main(String[]args){
int[] list = new int[]{1,2,1,1,1,6};
boolean match = false;
int sumNeeded = 8;
for(int i = 0; i < list.length; i ++){
for(int j = (list.length -1); j > i; j --){
if(list[i] + list[j] == sumNeeded){
System.out.println("The numbers are = " + list[i] + " & " + list[j]);
return;
}
}
}
}
}
The inner-for loop is modified to reduce the double-counting of the unordered pairs. Whenever a match is found and printed, we exit the function.
You may also add a break statement inside the while loop in your initial implementation.
if(match == true) {
break;
}
The while condition continues to execute the first and second for-loop until it's finished where as with return it stops execution entirely from the first and second loop.
To fix the while loop you could use a label and then break from that.
firstLoop:
for(int i = 0; i < list.length; i ++) {
match = true;
break firstLoop;

Why is the for loop running even though the condition is false

I have been trying to write a code trace for this program. after many attempts on paper I thought I understood it but now I have stumbled again.
In the for loop i=counter ,because i=0 and the counter=0 so since it has to be less than counter how is this code even running?
I have included my incomplete code trace below.
The aim of the program is to print 50 unique random numbers between 1 and 999, in 10 rows of 5. The program works perfectly.I just want to figure out how its working with the help of a code trace. I know this might be a simple problem to you, but I am struggling with it. Could you please help me, thank you.
import java.util.Random;
public class Random50 {
public static void main(String[] args) {
int numbersNeeded = 50;
int[] randomNumbers = new int[numbersNeeded];
int counter = 0;
Random randomGenerator = new Random();
int max = 999;
int min = 1;
while (counter < numbersNeeded) {
int generated = min + randomGenerator.nextInt(max);
boolean found = false;
for (int i = 0; i < counter && !found; i++) {
if (randomNumbers[i] == generated) {
found = true;
}
}
if (!found) {
randomNumbers[counter++] = generated;
}
}
for (int i = 0; i < counter; i++) {
System.out.printf("%03d ",randomNumbers[i] );
if (i > 0 && (i+1) % 5 == 0) {
System.out.println("");
}
}
}
}
This line is the reason why:
randomNumbers[counter++] = generated;
By using counter++, you're using the ++ postfix increment operator, which evaluates to the value of counter, but then increments it by 1 after the evaluation. The equivalent code without use of this operator would look something like this:
randomNumbers[counter] = generated;
counter = counter + 1;
So on the first iteration where this line is executed, randomNumbers[0] is updated, but then counter gets set to 1 (because 0 + 1 = 1). On the second iteration, randomNumbers[1] is updated, then counter gets updated to 2 (because 1 + 1 = 2)...and so forth.
You can find more information about arithmetic operators here: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op1.html

Find largest sequence within an arraylist

Some Background
Last week I did a problem in my textbook where It told me to generate 20 random numbers and then put brackets around successive numbers that are equal
Consider the following which my program outputs
697342(33)(666)(44)69(66)1(88)
What I need to do
The next problem was to basically get the longest sequence of these words and put brackets around them. If you have
1122345(6666)
Basically you need to put brackets around four 6's , since they occur most often.
I've finished all other problems in the chapter I am studying ( Arrays and ArrayLists), however I can't seem to figure this one out.
Here is the solution that I have made for putting brackets around successive numbers:
class Seq
{
private ArrayList<Integer> nums;
private Random randNum;
public Seq()
{
nums = new ArrayList<Integer>();
randNum = new Random();
}
public void fillArrList()
{
for (int i = 0 ; i < 20 ; i++)
{
int thisRandNum = randNum.nextInt(9)+1;
nums.add(thisRandNum);
}
}
public String toString() {
StringBuilder result = new StringBuilder();
boolean inRun = false;
for (int i = 0; i < nums.size(); i++) {
if (i < nums.size() - 1 && nums.get(i).equals(nums.get(i + 1))) {
if (!inRun) {
result.append("(");
}
result.append(nums.get(i));
inRun = true;
} else {
result.append(nums.get(i));
if (inRun) {
result.append(")");
}
inRun = false;
}
}
return result.toString();
}
}
My Thoughts
Iterate through the whole list. Make a count variable, that keeps track of how many numbers are successive of each other. I.e 22 would have a count of 2. 444 a count of 3
Next make an oldCount, which compares the current count to the oldCount. We only want to keep going if our new count is greater than oldCount
After that we need a way to get the starting index of the largest count variable, as well as the end.
Is my way of thinking correct? Because I'm having trouble updating the oldCount and count variable while comparing them, since there values constantly change. I'm not looking for the code, but rather some valuable hints.
My count is resetting like this
int startIndex, endIndex = 0;
int count = 0;
int oldCount = 0;
for(int i = 0 ; i < nums.size(); i++)
{
if(nums.get(i) == nums.get(i+1) && count >= oldCount)
{
count++;
}
oldCount = count;
}
Only after walking all elements you will know the longest subsequence.
11222333333444555
11222(333333)444555
Hence only after the loop you can insert both brackets.
So you have to maintain a local optimum: start index plus length or last index of optimum.
And then for every sequence the start index of the current sequence.
As asked:
The optimal state (sequence) and the current state are two things. One cannot in advance say that any current state is the final optimal state.
public String toString() {
// Begin with as "best" solution the empty sequence.
int startBest = 0; // Starting index
int lengthBest = 0; // Length of sequence
// Determine sequences:
int startCurrent = 0; // Starting index of most current/last sequence
for (int i = 0; i < nums.size(); i++) {
// Can we add the current num to the current sequence?
if (i == startCurrent || nums.get(i).equals(nums.get(i - 1)))) {
// We can extend the current sequence with this i:
int lengthCurrent = i - startCurrent + 1;
if (lengthCurrent > lengthBest) { // Current length better?
// New optimum:
startBest = startCurrent;
lengthBest = lengthCurrent;
}
} else {
// A different num, start here.
// As we had already a real sequence (i != 0), no need for
// checking for a new optimum with length 1.
startCurrent = i;
}
}
// Now we found the best solution.
// Create the result:
StringBuilder result = new StringBuilder();
for (int i = 0; i < nums.size(); i++) {
result.append(nums.get(i));
}
// Insert the right ')' first as its index changes by 1 after inserting '('.
result.insert(startBest + lengthBest, ")");
result.insert(startBest, "(");
return result.toString();
}
The first problem is how to find the end of a sequence, and set the correct start of the sequence.
The problem with the original algorithm is that there is handled just one sequence (one subsequence start).
The way you have suggested could work. And then, if newcount is greater than oldcount, you'll want to store an additional number in another variable - the index of the where the longest sequence begins.
Then later, you can go and insert the ( at the position of that index.
i.e. if you have 11223456666.
The biggest sequence starts with the first number 6. That is at index 7, so store that 7 in a variable.
I think you need to iterate the entire list even though the current count is lower than the oldCount, what about e.g. 111224444?
Keep 4 variables while iterating the list: highestStartIndex, highestEndIndex, highestCount and currentCount. Iterate the entire list and use currentCount to count equal neighbouring numbers. Update the highest* variables when a completed currentCount is higher than highestCount. Lastly write the numbers out with paranthesis using the *Index variables.

Method for avoiding duplicates when generating a random list of pairs of numbers is not working as it should

I have this code for setting random values to true in a boolean[][], without making any duplicates:
int a = 0;
int b = 0;
int counter = 0;
for (int i=0; i<=50; i++) {
do {
a = randomizer.nextInt(hoogte);
b = randomizer.nextInt(breedte);
/**debug variable*/
counter++;
} while (bommaker[a][b]);
bommaker[a][b] = true;
}
After testing for a while, I noticed something was wrong, so I added a counter to check it. Every time I run the program, there comes a different number out of "counter". One time it was 57 while the other time even 63. But I have set the loop to exactly 51. This means the code isn't working as it should. Can somebody explain why it generates more than 51 numbers, and give a possible solution?
You have to remember that you have a loop within a loop. The OUTTER loop is limited to 51 executions, but the inner loop will cause a random number of iterations (an extra iteration for each time it sees that the array has already been set to true).
Other than the counter value being greater than you expected, what about the code is not working?
move out the counter++ line from do while loop
int a = 0;
int b = 0;
int counter = 0;
for (int i=0; i<=50; i++) {
do {
a = randomizer.nextInt(hoogte);
b = randomizer.nextInt(breedte);
/**debug variable*/
} while (bommaker[a][b]);
counter++;
bommaker[a][b] = true;
}

Categories