locker puzzle using a boolean array - java

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

Related

Mailman mailbox problem using 2d arrays and for loops

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].

Nested Loop not working properly in Mastermind game

I recently started coding in Java and my coach gave me an exercise where I have to re-create the Mastermind game. To give an overview of this game: the computer creates an array with X random integers, and the user gets to input X integers as well. Location matters. The users scores "Gold" if he guesses an integer that is in the same spot as the computer generated array. If the integer is present in the array, but in the wrong spot, the users gets a "Silver" score. If the integer is not present in the array at all, the user gets a "NotFound" score. The final array should give the user a score for each place in the array, e.g. (Gold, Silver, NotFound)
I have tried to make a nested loop that scores the users guesses. It captures the score in a different array (yourScore[]). User guesses are captured in array "guessednums[]" and the computer generated array is called "nums[]". The size of all arrays has been set with a variable prior to the mentioned code.
What I want the code to do is to first check whether a user's guess matches with the computer choice on the same spot, and if that is the case set the matching space in the yourScore array to "Gold". Then, if the guess does not directly match, I want a loop to check whether the user guess is present in ANY place of the computer generated nums[] array, and to score it as "Silver" if that is the case. Finally, if this is not the case, I want the yourScore[] place to be set as "NotFound".
Matching guesses are properly scored as "Gold". The problem I am encountering is that sometimes the loop will not properly score a guess as "Silver", but instead mark it as "NotFound". I suspect that this has to do with the loop not properly initialising. I have read multiple questions on Stack Overflow and other articles as well, and played around with my code, but I keep running into similar issues.
I would love to get a second opinion on the code and see what I have done wrong.
package Mastermind;
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class Mastermind {
static Scanner userInput = new Scanner(System.in);
public static void main(String[] args){
int size = 3; // Allows you to set the size of the arrays in the game
int[] nums = generateNumbers(size); //Stores the computer choice 3-tuple
int[] guessednums; //Stores the guessed 3-tuple
int iteration = 0; //Keeps track of the # of guesses so far
boolean correctAnswer; //true if the guessed tuple matches the computer choice tuple
//Set array size
//The game starts here
while (true){
iteration++;
System.out.println("Iteration #" + iteration);
guessednums = guessTheNumbers(size);
correctAnswer = yourScore(nums, guessednums, size);
if(correctAnswer) break;
}
//Printing the result
printResults(iteration, nums);
}
private static void printResults(int iteration, int[] nums) {
System.out.println("************************************************************"); // Print final result if users has a completely matching guess
System.out.println("************************************************************");
System.out.println("The correct answer was " + Arrays.toString(nums));
System.out.println("It took you " + iteration + " iterations to find the answer!");
}
private static int[] guessTheNumbers(int size) {
System.out.println("Please your ordered guess (press enter after each):");
int[] guessednums = new int[size]; // Initialise array for user choices
for (int i = 0; i < size; i++){ // Loop that creates the array of user input
guessednums[i] = userInput.nextInt();
}
System.out.println(Arrays.toString(guessednums));
return guessednums; // Return array for user guessed numbers array to main method
}
public static int[] generateNumbers(int size){
int[] nums = new int[size]; // Initialise array for computer choices
Random rn = new Random(); // Create new variable for randomised computer choices
for (int i = 0; i < size; i++){ // Loop that creates the array of computer choices
nums[i] = rn.nextInt(9) + 1;
}
System.out.println(Arrays.toString(nums)); // Temporary to print array
return nums; // Return array for computer generated numbers array to main method
}
public static boolean yourScore(int[] nums, int[] guessednums, int size){
String[] yourScore = new String[size]; // Initialise array for user choices
for(int i = 0; i < size; i++){ // Nested loop that scores the user entries as Gold/Silver/NotFound
if (guessednums[i] == nums[i]){
yourScore[i] = "Gold";
} else {
yourScore[i] = "NotFound";// in case is not found it stays that way
for(int j = 0; j < size; j++){
if (guessednums[i] == nums[j]){
yourScore[i] = "Silver"; // found one! break the loop and keep checking numbers
break;
}
}
}
}
if (yourScore[0] == "Gold" && yourScore[1] == "Gold" && yourScore[2] == "Gold"){ // Marks the input as true or false depending on if it matches with the computer choices
boolean correctanswer = true;
return correctanswer;
} else {
System.out.println("Your score is " + Arrays.toString(yourScore) + "!");
System.out.println("************************************************************");
boolean correctanswer = false;
return correctanswer;
}
}
}
The problem comes with the logic. I find useful to put the logic into words:
For each number in the array:
1. Check if the numbers are equal in that position (Gold)
2 else, for each number in the array, check if that number is equal to another in the array
3. If that number is in it, break the loop (Silver)
4. else, mark it as not found (NotFound).
the code would be like this:
for(int i = 0; i < size; i++){ // Nested loop that scores the user entries as Gold/Silver/NotFound
if (guessednums[i] == nums[i]){
yourScore[i] = "Gold";
} else {
yourScore[i] = "NotFound";// in case is not found it stays that way
for(int j=0;j<size<j++){
if (guessednums[i] == nums[j]){
yourScore[i] = "Silver"; // found one! break the loop and keep checking numbers
break;
}
}
}
}
I think you mixed up the outer and inner index meaning. Try this:
for(int i = 0; i < size; i++){ // Nested loop that scores the user entries as Gold/Silver/NotFound
for(int j = 0; j < size; j++){
if(i == j) {
if (guessednums[i] == nums[j]){
yourScore[i] = "Gold";
}
} else {
if (guessednums[i] == nums[j]){
yourScore[i] = "Silver";
} else if (guessednums[i] != nums[j]){
yourScore[i] = "NotFound";
}
}
}
}
Gold is only possible if i == j ...
HTH and always better for readers, if indentation is plausible and thus easy for the eyes ...
Not elegant but simple:
for(int i = 0; i < 5; i++){
yourScore[i] = "NotFound";//most likely
}
for(int i = 0; i < 5; i++){
for(int j = 0; j < 5; j++){
if(guessednums[i]==nums[j]) {
yourScore[i] = "Silver"; //quite likely
}
}
}
for(int i = 0; i < 5; i++){
if(guessednums[i]==nums[i]) {
yourScore[i] = "Gold"; //very unlikely
}
}

Automatically fill and array with a loop without a prompt..

I was wondering if it's possible to use a loop to fill and array without prompting the user for input?
I have to design a program to fill an array of size 6 with multiples of 7. The specification doesn't say anything about prompting the user, and it says 'Use a loop to fill the array' so I can't hard code the numbers in.
Of the multiples of 7 , I need to print out which ones can be divided by 3 exactly.
Is it possible to fill the array without an input from the user?
My code is below...
import java.util.Scanner;
/**
* Created by IntelliJ IDEA.
* Date: 26/02/2015
* Time: 15:25
* UPDATE COMMENT ABOUT PROGRAM HERE
*/
public class Array7Mult
{
public static void main(String[] args)
{
int multipleSeven [] = new int[6];
final int HOWMANY=6,DIVIDE=3;
Scanner keyboard = new Scanner(System.in);
for(int count=0;count<HOWMANY;count++)
{
System.out.println("Please enter a multiple of 7 below..");
multipleSeven[count]=keyboard.nextInt();
}//for
System.out.println("The multiples of seven that can be divided by 3 are..");
for(int count=0;count<HOWMANY;count++)
{
if (multipleSeven[count] % DIVIDE == 0)
{
System.out.println(multipleSeven[count]);
}//if
}//for
}//main
}//class
Yes ofcourse. Say you want to populate an array by a variable which is incremented by one per index. Say variable i (so we use the same variable that's instantiated in the loop).
for(int i = 0; i < arr.length; i++)
arr[i] = i;
Simple as that. You may ofcourse create a global variable and add it into the array within the boundaries of the loop and manipulate its value within the loop too.
int a = 0;
for(int i = 0; i < arr.length; i++) {
arr[i] = a;
a += 10;
}
If you want to increment the value as a multiple of seven, you can simple use the first example and instead of doing arr[i] = i do arr[i] = i*7
Use
for(int count=0;count<HOWMANY;count++)
multipleSeven[i]=(i+1)*7;
Instead of
for(int count=0;count<HOWMANY;count++)
{
System.out.println("Please enter a multiple of 7 below..");
multipleSeven[count]=keyboard.nextInt();
}
To fill the array multipleSeven with values 7,14,21,28,35,42.

finding the number of pairs of numbers in an array that add up to a number

I am trying to come up with a program that will search inside of an array that is given a length by the user that picks out whether there is a pair of numbers that sum to 7. The idea is that if there is k amount of dice being thrown, how many pairs of numbers out of those dice thrown add up to 7. So far this is all that I could come up with but I am very stuck.
This is the driver class for the program. I have to write a class that will make this driver function properly.
import java.util.Scanner;
public class SevenDriver{
public static void main(String[] args){
System.out.println("Enter number of dice to toss");
Scanner s = new Scanner(System.in);
int diceCount = s.nextInt();
SevenTally t = new SevenTally(diceCount);
int experiments = 1000000;
int wins = 0;
for(int j = 0; j < experiments; j++)
if(t.experiment()) wins++;
System.out.println((double)wins/experiments);
}
}
This is what I have so far. It does not currently work or compile. I am just looking for some ideas to get me going. Thanks!
public class SevenTally{
private int diceCount;
public SevenTally(int die){
diceCount = die;
}
public int genDice(){
return 1 + (int)(Math.random()*6);
}
public boolean experiment(){
boolean[] nums = new boolean[diceCount];
int ranNum;
int sum = 7;
for(int i = 0; i < nums.length; i++){
ranNum = genDice();
if (nums[ranNum] == sum){
return true;
}
}
int left = 0;
int right = nums.length - 1;
while(left<right){
int tempSum = nums[left] + nums[right];
if(tempSum == 7){
return true;
}
else if(tempSum>7){
right--;
}
return false;
}
}
First populate your array of length k with random int in [1;6]
The number of possible pairs in an array of length k is the number of 2-combinations in the array, which is (k-1)*k/2 (http://en.wikipedia.org/wiki/Combination)
You can test all the possible pairs (i,j) in your array like so:
int win = 0;
int tally = 7;
for(int i=0; i<k-1; i++){
for(int j=i+1; j<k; j++){
if(array[i]+array[j] == tally){
win++;
}
}
}
What this does is that it sets the first element of the pair to be the first element of the array, and sums it with the other elements one after the other.
It pairs array[0] with array[1] to array[k-1] at the first pass of the i for loop, that's k pairs.
Then k-1 pairs at second pass, and so on.
You end up with (k)+(k-1)+(k-2)+...+1 pairs, and that's exactly (k-1)*k/2 pairs.
done =]
edit: sorry, haven't read the whole thing. the method experiment() is supposed to return a boolean. you can return win>0?true:false; for example...
This Wiki page has some algorithms to do that. Its not a trivial problem...
You're generating a random number in ranNum, and then using it as an index into the array nums. Meanwhile, nums never gets filled, so no matter which box you index into, it never contains a 7.
What you want to do, if I understand your problem correctly, is fill each space in the array with the result of a die roll, then compare every two positions (rolls) to see if they sum to seven. You can do that using a nested for loop.
Essentially, you want to do this: (written in pseudocode as I'm not a java programmer)
int[] results[numrolls]
for (count = 0 to numrolls-1) { results[numrolls]=dieRoller() }
for (outer = 0 to numrolls-2)
for (inner = outer+1 to numrolls-1)
if (results[outer] + results[inner] == 7) return true
return false;
However, in this case there's an even easier way. You know that the only ways to get a sum of 7 on 2d6 are (1,6),(2,5),(3,4),(4,3),(5,2),(6,1). Set up a 6-length boolean array, roll your dice, and after each roll set res[result] to true. Then return (1-based array used for simplicity) ( (res[1] && res[6]) || (res[2] && res[5]) || (res[3] && res[4]) ).
ArrayIndexOutOfBoundsException means you are trying to access an element of the array that hasn't been allocated.
In your code, you create a new array d of length diceCount, but then you genDice() on always 6 elements.

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