Jump to content

  • Log In with Google      Sign In   
  • Create Account


Virtual Coin Flip


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
28 replies to this topic

#21 Álvaro   Crossbones+   -  Reputation: 12903

Like
2Likes
Like

Posted 11 October 2012 - 06:34 PM

Pretend you are the computer and follow the flow of the program. You compute a random number once. Then, if it is less than 0.5 you print "head" and do nothing else, because the rest of the code is inside the `else' block. If it is not less than 0.5, you print "tail" and make the comparison again, but without picking another random number. So you look at the number and, again, it is not less than 0.5. Etc.

You need to close the `else' block right after printing "tail". You also need to assign a fresh random number between throws.

Sponsor:

#22 ifthen   Members   -  Reputation: 820

Like
1Likes
Like

Posted 12 October 2012 - 08:34 AM

alvaro is right. Allow me to demonstrate it another way. I'll read your program as the computer reads it.

public static void main (String[] args){
  double start = 0;
  double end = 1;
  double random = new Random().nextDouble(); //hey Random, assign some number between <0-1) to variable random
  double result = start + (random * (end - start)); //now assign 0 + (random * (1-0)) = 0 + (random * 1) = random to variable result
  System.out.println(result); //I will tell the user the value of vairable result
  //is result is smaller than 0.5
  if (result < 0.5)
  { //block T
	//I will tell the user that it's a head
	System.out.println("head");
	//there aren't any statements, so I'll just skip over the block B, there's nothing relevant there
  } //end of block T
  else
  { //block F
	//I will tell the user it's a tail
	System.out.println("tail");
	//the programmer wants me to do something (compute another flip) more before I end...
	//wait... random, end and start probably didn't change, shouldn't the result be the same?
	//not my problem, i'll compute it
	result = start + (random * (end - start));
	//the value of result is the same as before... whatever
	//so let's compare again!
	if (result < 0.5)
	{
	  //I never get to this, the result is always smaller than 0.5
	  System.out.println("head");
	  //but if I did, I would see that there's nothing more and continue after the else branch
	}else{  //block F-F
	  //yeah... we print it
	  System.out.println("tail");
	  //ANOTHER TIME? This guy is crazy!
	  result = start + (random * (end - start));
	  //and we compare! yes!
	  if (result < 0.5){
		//also never happens
		System.out.println("head");
	  }else{ //block F-F-F
		/*and comparing and comparing...
		and comparing*/
	  } // end of block F-F-F
	} //end of block F-F <-- this is where I WOULD continue from if the heads come the second time
  } //end of block F <-- this is where I continue from if the heads come the first time
  //this is where I stop! No more work for me! YEAH!
}

Can you see what is wrong with the code?
1. If the heads come first time, the compiler prints "heads" and skips the whole else branch all down to end of the block F. Nothing else happens.
Solution: Remember, the parent block MUST be executed for the child block to be executed too. So just make all the ifs children of main() block! That way, they will be executed independently. You want to say to computer: "Flip the coin ten times and tell me the result after every flip." Instead, you are saying this: "Flip the coin and tell me the result. If it's tails, do the same thing once more. But flip the coin ten times at most." You must change the code to match its meaning.

2. The computer flips the coin only the first time. Remember, the act of flipping is
random = new Random().nextDouble();
This code
result = start + (random * (end - start));
just converts the result of flipping to another range (or the same range, in your case).

The computer just looks at the coin and says which side is up. But it doesn't flip the coin before checking it, so the result must be the same as before. (Variables, as is the case with coins, usually don't change the side lying up unless moved.Posted Image ).
SOLUTION: This one is easy, flip the coin (random = new Random().nextDouble();) before checking.

Also, it would be better to do it with procedures, but you seem you need to grasp the meaning of blocks ({}) and ifs. And those are probably the most important flow control in your code, so learn them and love them!Posted Image

EDIT: How do the code tags work? They don't accept line-breaks?
EDIT 2: Okay, got it. You can't start a code tag with a multi-line comment, or it will be displayed only on one line. Strange.

Edited by ifthen, 12 October 2012 - 11:30 AM.


#23 ByteTroll   Crossbones+   -  Reputation: 1307

Like
1Likes
Like

Posted 12 October 2012 - 12:10 PM

I am not sure if you are still having issues with this assignment, but I got bored today and figured I would lend a final hand. I recoded my example in Java. I generally don't do peoples homework for them, but you have at least given it a shot. For future reference, however, I would look closely at what I have done and learn. Hope this helps.

import java.util.Random;
public class flip
{
	public static void main(String[] args)
	{
		//Since these values never get changed, it is good practice to make them
		//final.
		final double start = 0;
		final double end = 1;
	  
		//Declare this as an instantiation of Random, not a double.
		Random random = new Random();
	  
		//Set the initial value of the result variable.  Notice how I use the
		//"random" object.  Intead of using a double that has an initial value,
		//I generate a new value ("random.nextDouble()")
		double result = start + (random.nextDouble() * (end - start));
	  
		System.out.println(result);
	  
		//First result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
		else
		{
			System.out.println("tail");
		}
	  
		//Generate a new value and shove it in the result variable.  Same thing
		//as the first call.  I use random to generate a new value.  If I didn't
		//and just used a double, the double variable would still have the same
		//value I set in the beginning.
		result = start + (random.nextDouble() * (end - start));
	  
		//Second result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
		else
		{
			System.out.println("tail");
		}
	  
		//Generate a new value and shove it in the result variable.
		result = start + (random.nextDouble() * (end - start));
	  
		//Third result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
	  
		//Generate a new value and shove it in the result variable.
		result = start + (random.nextDouble() * (end - start));
	  
		//Fourth result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
		else
		{
			System.out.println("tail");
		}
	  
		//Generate a new value and shove it in the result variable.
		result = start + (random.nextDouble() * (end - start));
	  
		//Fifth result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
		else
		{
			System.out.println("tail");
		}
	  
		//Generate a new value and shove it in the result variable.
		result = start + (random.nextDouble() * (end - start));
	  
		//Sixth result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
		else
		{
			System.out.println("tail");
		}
	  
		//Generate a new value and shove it in the result variable.
		result = start + (random.nextDouble() * (end - start));
	  
		//Seventh result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
		else
		{
			System.out.println("tail");
		}
	  
		//Generate a new value and shove it in the result variable.
		result = start + (random.nextDouble() * (end - start));
	  
		//Eighth result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
		else
		{
			System.out.println("tail");
		}
	  
		//Generate a new value and shove it in the result variable.
		result = start + (random.nextDouble() * (end - start));
	  
		//Ninth result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
		else
		{
			System.out.println("tail");
		}
	  
		//Generate a new value and shove it in the result variable.
		result = start + (random.nextDouble() * (end - start));
	  
		//Tenth result check.
		if(result <= 0.5)
		{
			System.out.println("head");
		}
		else
		{
			System.out.println("tail");
		}
	}
}

Edited by ByteTroll, 12 October 2012 - 12:14 PM.

▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬
I see the future in 1's and 0's
▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬

"This is called programming. The art of typing shit into an editor/IDE is not programming, it's basically data entry. The part that makes a programmer a programmer is their problem solving skills." - Serapth

#24 ifthen   Members   -  Reputation: 820

Like
0Likes
Like

Posted 12 October 2012 - 01:43 PM

Bytetroll got it almost right, although the else branch of the third result check is missing! That could lead to nasty bugs in your code (hey, why does it sometimes print 10 lines and sometimes just 9?), so fix it if you are going to use it. THAT is the reason why you shouldn't write programs copy-paste-style, if you have many same or almost same snippets in your program, you will at some point make a mistake when creating/editing it and the program will not work properly. So be wary of it and try to minimize it!

Also, it prints the result at start, so remove that line if you don't want to see that floating point number printed in your output.

If you cannot use the static keyword elsewhere than in main, you have to do either the ten ifs trick or use a class with recursive function (if anyone knows another approach, share your knowledge). That could look like this

import java.util.Random;
public class Coin {
  //Is the head upwards?
  protected boolean head;
  //Reference to random generator used.
  protected Random randomGenerator;
 
  //Init the coin to the init values
  Coin(boolean _head, Random _randomGenerator) {
    head = _head;
    randomGenerator = _randomGenerator;
  }
  //Flips the coin so it is heads 50% of time and tails 50% of time.
  void flip() {
    //notice that you can assign results of expressions to booleans
    head = randomGenerator.nextDouble() < 0.5;
  }
 
  //Prints the name of side that is upwards side
  void print() {
    if (head)
	  System.out.println("head");
    else
	  System.out.println("tail");
  }
 
  //Flips the coin repeat times and prints its upwards side after every flip
  void flipAndPrint(int repeat) {
    if ( repeat > 0) {
	  flip();
	  print();
	  flipAndPrint(repeat-1);
    }
  }
 
  //and some other functions if necessary (e.g. getter of the upwards side)
 
  //Flips a coin and prints the result ten times.
  public static void main (String[] args)
  {
    Random randomGenerator = new Random();
    //it doesn't matter if we choose heads or tails as the starting upwards side because it will be flipped anyway
    Coin coin = new Coin(true, randomGenerator);
    coin.flipAndPrint(10);
  }
}

Yeah, that's probably an overkill for now, but suppose that you would develop betting game software or something like that. Using ten ifs to flip ten coins would be rather unprofessional. (Of course you would be using for loops. But it is good practice in Java to split every non-simple task to a separate class - divide and conquer, so this applies a bit.)

#25 ByteTroll   Crossbones+   -  Reputation: 1307

Like
1Likes
Like

Posted 12 October 2012 - 03:07 PM

Bytetroll got it almost right, although the else branch of the third result check is missing! That could lead to nasty bugs in your code (hey, why does it sometimes print 10 lines and sometimes just 9?), so fix it if you are going to use it. THAT is the reason why you shouldn't write programs copy-paste-style, if you have many same or almost same snippets in your program, you will at some point make a mistake when creating/editing it and the program will not work properly. So be wary of it and try to minimize it!

Also, it prints the result at start, so remove that line if you don't want to see that floating point number printed in your output.

If you cannot use the static keyword elsewhere than in main, you have to do either the ten ifs trick or use a class with recursive function (if anyone knows another approach, share your knowledge). That could look like this

import java.util.Random;
public class Coin {
  //Is the head upwards?
  protected boolean head;
  //Reference to random generator used.
  protected Random randomGenerator;

  //Init the coin to the init values
  Coin(boolean _head, Random _randomGenerator) {
	head = _head;
	randomGenerator = _randomGenerator;
  }
  //Flips the coin so it is heads 50% of time and tails 50% of time.
  void flip() {
	//notice that you can assign results of expressions to booleans
	head = randomGenerator.nextDouble() < 0.5;
  }

  //Prints the name of side that is upwards side
  void print() {
	if (head)
	  System.out.println("head");
	else
	  System.out.println("tail");
  }

  //Flips the coin repeat times and prints its upwards side after every flip
  void flipAndPrint(int repeat) {
	if ( repeat > 0) {
	  flip();
	  print();
	  flipAndPrint(repeat-1);
	}
  }

  //and some other functions if necessary (e.g. getter of the upwards side)

  //Flips a coin and prints the result ten times.
  public static void main (String[] args)
  {
	Random randomGenerator = new Random();
	//it doesn't matter if we choose heads or tails as the starting upwards side because it will be flipped anyway
	Coin coin = new Coin(true, randomGenerator);
	coin.flipAndPrint(10);
  }
}

Yeah, that's probably an overkill for now, but suppose that you would develop betting game software or something like that. Using ten ifs to flip ten coins would be rather unprofessional. (Of course you would be using for loops. But it is good practice in Java to split every non-simple task to a separate class - divide and conquer, so this applies a bit.)


Oh dear! That was a copy and paste fail. As ifthen stated... that is why you do not write programs copy and paste style. I wrote one block and then copy and pasted; missing one. Sorry about that one. Thank you for catching that ifthen!

Edited by ByteTroll, 12 October 2012 - 03:09 PM.

▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬
I see the future in 1's and 0's
▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬

"This is called programming. The art of typing shit into an editor/IDE is not programming, it's basically data entry. The part that makes a programmer a programmer is their problem solving skills." - Serapth

#26 m3mb3rsh1p   Members   -  Reputation: 131

Like
1Likes
Like

Posted 12 October 2012 - 05:28 PM

Hi. I'm also a beginner so I thought I'd share my solution. I'm stuck at how to count the flips without loops because I don't quite yet have a firm grasp of the Java utils.

I enjoyed this. Thanks to all!
import java.util.Random;
import java.util.Arrays;
import java.util.Collections;

public class Coin
{
public enum Side { heads, tails, edge };

public Coin()
{
	_side = Side.edge;
}
public Coin(Side side)
{
	_side = side;
}
public Coin(Random generator)
{
	flip(generator);
}
public void flip(Random generator)
{
	double value = generator.nextDouble();

	if(value < 0.5 )
	{_side = Side.heads;}
	else if(value > 0.5)
	{_side = Side.tails;}
	else
	{_side = Side.edge;}
}
public boolean equals(Coin other)
{
	return _side == other._side;
}
public String toString()
{
	return _side.toString();
}
	private Side _side;

public static void main(String[] args)
{
	Coin heads = new Coin(Side.heads);
	Coin tails = new Coin(Side.tails);
	
	Random rand = new Random();
	
	Coin[] coins = new Coin[]
	{
		new Coin(rand),
		new Coin(rand),
		new Coin(rand),
		new Coin(rand),
		new Coin(rand),
		new Coin(rand),
		new Coin(rand),
		new Coin(rand),
		new Coin(rand),
		new Coin(rand)
	};

	System.out.println(Arrays.toString(coins));

	int numHeads = Collections.frequency(Arrays.asList(coins), heads);
	System.out.println("There are " + numHeads + " heads.");

	int numTails = Collections.frequency(Arrays.asList(coins), tails);
	System.out.println("There are " + numTails + " tails.");
}
}

I encountered some challenges while finding the "right way"
- no easy way to "apply"
- countif/equality not working here
- *()&(SFHKJHSF(&(*&:>( code tags!!

Edited by m3mb3rsh1p, 12 October 2012 - 06:33 PM.


#27 m3mb3rsh1p   Members   -  Reputation: 131

Like
0Likes
Like

Posted 12 October 2012 - 07:01 PM

Eureka! I solved the "equals() method not working properly!" conundrum!
public boolean equals(Object other)
{
final Coin c = (Coin)other;
return _side == c._side;
}

Edited by m3mb3rsh1p, 12 October 2012 - 07:02 PM.


#28 ifthen   Members   -  Reputation: 820

Like
0Likes
Like

Posted 13 October 2012 - 12:41 AM

Hmm... that really isn't a solution. Suppose you pass an object of type Car (or something else) to the function. It throws a ClassCastException and if you don't have the try-catch blocks surrounding it, it leads to premature program termination (as it does if other is null, but that is usually expected behaviour). You should compare that other is of type Coin or a child of Coin either by surrounding with try-catch blocks for ClassCastException or like this.
public boolean equals(Object other) {
  Class thisClass = this.getClass();
  Class otherClass = other.getClass();
  while (otherClass != thisClass) {
    otherClass = otherClass.getSuperclass();
    if (otherClass == null)
	  return false;
  }
  final Coin otherCoin = (Coin)other;
  return _side == otherCoin._side;
}


#29 Ryan Schurton   Members   -  Reputation: 172

Like
1Likes
Like

Posted 13 October 2012 - 09:28 AM

i've seem to of got it working thank a lot for all the help everyone. Hopefully someday i will be just like you guys in the For Beginners section helping out a fellow noob.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS