When to use set and add methods in list - java

cutDeck() does the last step of shuffling -- cutting the deck. This should move the first cutLocation number of cards ("first" meaning at the lowest index) from cards and add them to the back of the List. Make certain that you add cards in the same (relative) order that they were originally stored.
public List<PlayingCard> cutDeck(int cutLocation) {
for (int i = 0; i < cutLocation; i++) {
cards.add(cards.get(i));
}
for (int i = 0; i < cutLocation; i++) {
cards.remove(cards.get(i));
}
return cards;
}
This is the error message i am getting
cutDeck(133) did not correctly cut when cards had 208 cards. At index 0 expected 5H but was 3C expected:<[5H]> but was:<[3C]>
I can't see how I am doing something wrong, is it my logic should I be using the cards.set() instead of cards.add()?

Your removal is wrong. Imagine cards has five cards in it and we're splitting it after the first two cards.
1 2 3 4 5
After your first loop terminates, you get:
1 2 3 4 5 1 2
Now, your second loop starts and removes the first card at i = 0, which is 1
2 3 4 5 1 2
Now, your second loop removes the first card at i = 1, which is 3, and NOT 2!
This is where your mistake is. You could simplify the whole logic to a single for loop:
for(int i = 0; i < cutLocation; i++) {
cards.add(cards.remove(0));
}

When you removed the first card in your second for loop all your cards will have been shifted to the front by one position. But your loop variable i is still increasing and you use it in your cards.get(i) call. This means that when you are in the second iteration of your loop you will call cards.get(1), but this would be the original third card to remove. After that you try to remove the next card with cards.get(2), but it would delete the original fifth card and so on.
You might want to use cards.removeAt(0) to (always) remove the card at the beginning until you reached the limit cutLocation.

Related

Replicating the sleight of hand Trick Oil and Water

Note: I haven't found an answer to this particular question.
Backstory:
I recently learned the Oil and Water routine that magician's use in sleight of hand (this doesn't mean I can actually do it, but I have the mechanics done). For those that are unfamiliar with this routine, it takes three red cards and three black cards. These cards are initially put together red, black, red, black, red, black. By the end of the trick, all the reds are back together and all the blacks are back together.
I have successfully coded this in Java, but I am at a loss as to explain why it is doing it correctly. I think there is a problem with my logic I am sure, but I need some verification.
Here is the code I currently have:
int[] mixed = {1,2,1,2,1,2};
System.out.println("Before Sort: ");
for (int element : mixed){
System.out.println("Element: " + element);
}
for (int element : mixed){//this for loop moves all but the first and last element.
// for (int element=0;element < mixed.length-1;element++){// this for loop reverses order
int temp = mixed[element];
mixed[element]=mixed[element+1];
mixed[element+1]=temp;
}
if ((mixed[0]==1) && (mixed[5]==2)){//this swaps the first and last elements after using an enhanced for loop
int temp = mixed[0];
mixed[0] = mixed[5];
mixed[5] = temp;
}
System.out.println("After sort: ");
for (int element : mixed){
System.out.println("Element: " + element);
}
Make sure to read the comments I have in the code, as this is where my wtf moment is. My goal is to be able to have my high school students do this when it comes time to hit arrays. I would like to be able to introduce this as I introduce arrays. Any help would be greatly appreciated.
You are iterating over the array using elements of the array as an index for the switches that you make.
You are only ever doing two of the same switches.
When the current element is 1, it switches values at index 1 and index 2 of the array.
When the current element is 2, it switches values at index 2 and index 3 of the array.
This doesn't work; you have to do a manual switch at the end. And this manual switch will not work in other cases.
The right way to do this is to:
array 1 2 1 2 1 2
index 0 1 2 3 4 5
Switch:
0 with 1
1 with 3
2 with 5
The are only 3 switches so the loop should start at 0 and end at array length / 2.

Randomizing Playing Deck

I know there are multiple ways of writing code for this type of question, but I'm trying to understand my Professor's way. He wrote a method that takes the value of an integer in an array and assigns it the value of another random integer in the array, i.e "shuffling a deck":
static void shuffle(int[ ] deck) {
//Randomize the order of the elements of deck
//Pick a random card to go in position 0, then position 1, etc.
for(int cardNum=0; cardNum<DECK_SIZE-1; cardNum++){
//pick a random value randomCardNum from cardNum...DECK_SIZE-1
int randomCardNum = cardNum+(int)(Math.random()*(DECK_SIZE-cardNum));
//Swap card and randomCard
.....
What I can't understand is why he would have the for loop go until DECK_SIZE - 1. There are 52 cards, and I know that an array's last index is n-1, but the last cardNum is already not inclusive, so it's going from 0 to 50. I tried taking the -1 out, I get 52 random cards either way.
I'm not sure if it has to do with int randomCardNum, but this seems right as the equation for randomizing numbers in a specific range is :
Min + (int)(Math.random() + (Max-Min))
Your best bet is to ask your professor, but note that if cardNum could go all the way to 51 (the last index), then this line:
int randomCardNum = cardNum+(int)(Math.random()*(DECK_SIZE-cardNum));
...is guaranteed to result in a 51 in randomCardNum on the last iteration, because DECK_SIZE-cardNum will be 1, and so multiplying it by Math.random() will give you a value less than 1, and so casting that value to int will result in 0, and of course cardNum+0 is cardnum.
Since cardNum and randomCardNum would both be 51 on that last iteration, and there's no point in swapping a card with itself, he stopped one iteration early.
My question would have been: Why use DECK_SIZE rather than deck.length, since it introduces a possible maintenance error (changing the size of deck but not remembering to change the constant).
Your professor's code is correct. Look at the random call:
int randomCardNum = cardNum+(int)(Math.random()*(DECK_SIZE-cardNum));
When cardNum starts at 0, it chooses one of 52 cards, puts that random one at position 0. Next time through the loop it chooses one of the 51 remaining and puts it next. Then it chooses one of 50 remaining and puts it next, etc. The last time through the loop there are two cards remaining, it chooses one to be first, and then we're done. You add another iteration to the loop it just selects one of the remaining one card, and places it where it already is, to no effect whatsoever.

for loop decrementing by 2 to 0 and summing up the values that were generated before getting to 0

I am trying to find a way to count down from the int that is input by a user and then add each second value as i count down to 0
for example.
{user inputs 10
program counts down 8,6,4,2,0
then add 10 + 8 + 6 + 4 +2 +0= 30
}
how can I do this using a nested for loop
so far I have only been able to take user input, and count down by 2 each time. I get to 0 but have no way of adding every second value.
My code:
so far, it just counts to 0
public class Week5b {
static Scanner userVal = new Scanner (System.in);
public static void main(String[] args) {
//printTable();
reverseAddSkip();
public static void reverseAddSkip(){
System.out.println("Please enter an integer");
for (int i = userVal.nextInt(); i >=0; i-=2){
System.out.println(i) ;
}/* this creates a loop where the variable i is equal to user input;
the condition for the loop to continue is whether the input is larger or equal to 0; the update part of the loop takes 2 away each time, as if it were -- (which takes away one each time) */
}
}
How would I write that out mathematically?
Adding the sum of i-=2 to the original value of i.
You type 11 , it counts 9 7 5 3 1 , then adds 11 9 7 5 3 1. and give you the sum.
don't know how to sum every 2 numbers decrementing by 2, from a user value.
You input put 50, it counts down by 2 to 0
you put 51 it counts down by 2 to 0
but I haven't found away to sum all then numbers that were generated before getting to 0
:/
NoGlitching,
You need to look at the control flow of your program - which is to say, the path it takes upon execution.
You should also look at using more variables.
I'll give you the pseudocode I would use, because I think it's important for you to be able to write the code yourself:
Make a new integer called OriginalInput.
Make a new integer called RunningTotal.
Set RunningTotal to 0.
Store the user's input in OriginalInput.
Loop through OriginalInput.
Print the current OriginalInput.
Add the current OriginalInput to RunningTotal.
When the loop is finished:
Print RunningTotal.
I hope this helps.
EDIT:
// First you equalize j with i
input = userVal.nextInt();
j = i; // Put the user input in j first. for instance 11.
for (int i = input; i >=0; i-=2)
{
if (i >= 0) // If i is not below 0
{
j += i; // Add to j what i has now (everytime -2)
// put a system out print here to show what was added
// J starts as 11 and adds 9,7,5,3,1 then nothing. So it ends as 36.
}
}
// outside the For loop after it ends but INSIDE your method, you get the sum from the variable j!

cannot understand for statement result

Our teacher in my AP Computer Science course gave us this code
final int LIMIT = 5;
int i, count;
for (count=1; count<=LIMIT; count++)
{
for (i=0; i<count; i++)
{
System.out.print(count);
}
}
System.out.println();
When this code executes, the output is as follows
1
22
333
4444
55555
I do not have a good understanding of the for statement and I cannot understand why the code would print 1 once, 2 twice, 3 three times, ect. Can someone please try to explain this to me?
This is a great question and covers the basics of for loops.
Thinking About For Loops: The Basics
Think about the code you have written above in this way:
A for loop does ("executes") what is enclosed in its body once for each time you specify - or, to think about it another way, until a condition that you specify is false. As the coder, you need to tell the program: [1] at what point to begin; [2] how many times to do it (better thought about as "until when to do it"); [3] and by how many the code should "count" (what we call "increment").
To demonstrate with pseudo-code:
for ([1]; [2]; [3])
or
for (where to begin; how many times; how to count) {
// DO SOMETHING
}
Remember, as you "count", you are increasing - in the case of the first for loop - the count variable by the how to count piece (count + how to count). What you have in your above code is a nested for loop - a loop inside another loop (described, below). Referencing the pseudo-code I have written, above, your first for loop does the following:
for (start counting at 1; iterate once until count is greater than 5; increment count by 1)
Your Question
Now, comes the piece that is throwing you. You have two variables to pay attention to because you have two for loops: count, in the first for loop (used by the second); i in the second. Each time your first for loop iterates, the first for loop must execute the second for loop (look at your code). Again, pay attention to the two variables - but, more importantly, the relationship between the variables in both for loops' conditions. The second for loop depends upon the first. Think about it this way:
As count is incremented (here, increased by one), the second for loop must execute its own operation that many times:
for (i starting at 0; i not equal to count; increment by 1)
So, at the first iteration you would see something like this:
for (count = 1; count will always iterate once until condition false; increment){ }
for (i = 0; i < count (1); increment i){ }
Result will be:
1
Then the first loop is incremented (count becomes 2) and you get:
for (i = 0; i < (2); increment i)
Because the second loop will iterate until i is no longer less than 2 (not including 2), your result will be:
22
This relationship will continue until you get your final result:
55555
A Final Comment
Your teacher is looking to teach you a few different things with the code you provided, above, namely two: nested for loops; and how initializing your iterator (i and count) and the condition statement <, >, <=, >=, etc.) affects the behavior of a loop.
The first for loop indicates that it will loop the contents LIMIT times(which is 5), incrementing count by 1 at the end of each loop. The second inner for loop indicates that number of times to print the number count.
Might be easier to understand with indentation of your code:
final int LIMIT = 5;
int i, count;
for (count=1; count<=LIMIT; count++) {
for (i=0; i<count; i++) {
System.out.print(count);
}
System.out.println();
}
The first for loop starts at 1 and ends at limit 5. The inner loop starts at 0 and goes to the current count. So for the first iteration the inner loop will go from 0 to 1. This will print count 1 time which count is 1. The second time through the outer loop the counter will be 2 so the inner loop will loop from 0 to 2. It will print 2 twice. The 3rd time through count will be 3. The inner loop will loop from 0 to 3 and print 3 3 times. Etc... This is nested looping.
The first loop will write 5 lines as LIMIT = 5
The second loop will write n times the current index of the first loop, for each line.
n equals the current index of the first loop. So line #1, one time 1, line #2, two times 2, ....
You have two for loops, the outer loop starts count with a value of 1 and will iterate until count has a value greater than 5. The inner for loop will start with a value of 0 and will iterate until i has a value greater than or equal to count. So,
count <- 1
i <- 0
while (i < count) { print(count); i++; } // <-- 0 to 1 is a range of 1
newline();
Then
count <- 2
i <- 0
while (i < count) { print(count); i++; } // <-- 0 to 2 is a range of 2
newline();
And so on.
It is probably best to explain this by walking through the steps on by one...
final int LIMIT = 5;
int i, count;
for (count=1; count<=LIMIT; count++)
{
for (i=0; i<count; i++)
{
System.out.print(count);
}
System.out.println(); //from the results you are getting, this statement should be here
}
To put this in human readable terms:
A. we have a number LIMIT that is 5
B. we have a number i and count
C. set the number count to 1
D. if the number count is less than LIMIT, do the following:
1. set the number i to 0
2. if the number i is less than the number count, do the following:
a. print out the number count
b. add 1 to the number i
c. go back to step 2
3. print out an empty line
4. add 1 to the number count
5. go back to step D
So, if we go through the loops, here's what our variables become:
count is set to 1
count is less than 5
i is set to 0
i is less than count? yes, i is 0 and count is 1
print out the value of count (which is 1)
add 1 to i
i is 1
is i less than count? no, i is 1 and count is 1
print out a new line
add 1 to count
count is 2
count is less than 5
i is set to 0
i is less than count? yes, i is 0 and count is 2
print out the value of count (which is 2)
add 1 to i
is i less than count? yes, i is 1 and count is 2
print out the value of count (which is 2)
add 1 to i
is i less than count? no, i is 2 and count is 2
print out a new line
add 1 to count
count is 3
etc.
This continues until count is greater than 5, at which point it exists. As you can see from the pattern, the variable count determines which number gets printed, and the variable i determines how many times it is printed.

For loop stopping prematurely

I'm trying to solve problem #299 - Train Swapping in website UVa Online judge. The code I have works fine for independent test cases. However, when I use the sample input they provide, my program omits one of the test cases, the last one to be more specific:
Here is my code:
import java.util.Scanner;
public class Tester {
void problem(){
Scanner imput = new Scanner(System.in);
int numT =imput.nextInt();
int numL, aux, swaps=0;
int [] train = new int [50];
for (int i =0; i<numT; i++) {
numL = imput.nextInt();
for (int m =0; m< numL; m++) {
train[m]=imput.nextInt();
}
for (int j=0; j<numL; j++) {
if (train[j]>train[j+1]) {
for (int k =j; k<numL-1;k++) {
aux = train[k];
train[k]=train[k+1];
train[k+1]=aux;
swaps++;
}
}
}
System.out.println("Optimal train swapping takes "+swaps+" swaps.");
swaps = 0;
}
}
}
Example Input:
3
3
1 3 2
4
4 3 2 1
2
2 1
Example Output:
Optimal train swapping takes 1 swaps.
Optimal train swapping takes 6 swaps.
Optimal train swapping takes 1 swaps.
My code prints until the second solution, then for some reason stops. I've tried to debug it and check what's going on step by step but it has driven me to a migraine point. Any insight is highly appreciated.
...
To be more precise it stops at the second for loop the third time around without taking anything into the array...and I don't know why!
Another thing I found out is that to solve this problem the number of swaps for the case of the middle is 6, therefore the bubble sort wont be useful here, since it makes over 10 swaps thus yielding a wrong output, this is a separate issue to the original one I presented however. I still haven't figure out why it stops the third time around the loop where I assign values to the array for the third time.
The input consists of:
first line is number of cases.
this line enters the length of a train ex: 4
this line enters the number of the wagons ex: 2 4 3 1
the next following lines correspond to the following test cases whose structure is the same as the example.
They ask you to arrange the train and tell the number of swaps made to make the train in order.

Categories