I am in a beginning Java programming class and one of our assignment is to write a program that simulates tossing a coin a user-specified number of times. The functional class, CoinToss.java, looks like this:
public class CoinToss {
private char[] results;
private int numHeads;
private int numTails;
private double headsFrac;
private double tailsFrac;
private int currentRun;
private char currentOutcome;
public CoinToss(int numTosses) {
results = new char[numTosses];
for(int i = 0; i < results.length; i++) {
double number = Math.random();
if(number < 0.5) {
results[i] = 't';
}
else {
results[i] = 'h';
}
}
}
public void count() {
for(int i = 0; i < results.length; i++) {
if(results[i] == 't') numTails++;
else numHeads++;
}
headsFrac = (double)numHeads/results.length;
tailsFrac = (double)numTails/results.length;
}
public double getFracHeads() {
return headsFrac;
}
public double getFracTails() {
return tailsFrac;
}
public char[] getTosses() {
return results;
}
public void getLongestRun() {
currentOutcome = 'h';
for(int i = 0; i < results.length; i++) {
if(currentOutcome == results[i]) {
currentRun++;
}
else {
currentOutcome = results[i];
currentRun = 1;
}
}
if(currentOutcome == 'h') {
System.out.println("Longest run was " + currentRun + " heads.");
}
else {
System.out.println("Longest run was " + currentRun + " tails.");
}
}
}
My main area of concern is the getLongestRun() method. The instructions say: Create a method that examines the array of coin tosses to locate the longest
possible run of heads or tails that were tossed. You will need two attributes,
these attributes have the current number of consecutive outcomes (a run) and
the outcome associated with the run (head or tail). In a loop, compare each toss
in the array to the outcome
of the current run. If they match, the current run is
now recognized as one longer. If they don’t match, then the current run has
ended. Compare the number of consecutive outcomes in this run that has just
ended with the largest number of consecutive outcomes that has been
previously seen
(the longest run so far). Whether or not this is a new longest
run, reset the current outcome to the one just examined and reset the length of
the current run to 1. Think about if any special processing needs to happen
when the loop terminates.
My main concern is how to get that method working correctly. It is not counting the longest consecutive number of heads or tails correctly.
You don't store the results of each run; you simply overwrite the previous value when a new run begins. That means that your getLongestRun() method will only ever print the length of the last run, rather than the longest.
To fix this, you will need to record the results of each run in an array (or, preferably, an object structure like ArrayList) then traverse it to find the maximum value. Alternatively, you could simply have a variable which always holds the maximum streak and simply discard the latest one if it's lower than the current maximum.
I won't provide full code for you since this is coursework, but here's a pseudocode (Pythonic) idea of what I mean:
current_streak = 0
longest_streak = 0
current_coin = coin_toss_list[0]
for coin in coin_toss_list:
if current_coin == coin:
current_streak = current_streak + 1
else:
if current_streak > longest_streak:
longest_streak = current_streak
current_streak = 1
current_coin = coin
print "Longest streak was " + longest_streak
Related
In a class I am taking, we are supposed to solve equations that look like this ([] = digit):
[][]*[][][]=[][][][]
Where each digit 1-9 can only be used once.
The one the code I have made is solving is [][]*[][][]=4396
I have code that is free of errors, but will not do the intended action
Disclaimer: The code does not check if the digits 1-9 are only used once, that is up for the human to decide (for now, please do not add this function in any example code)
Here is the code:
public class MK1
{
public static void main(String[] args)
{
//the full sum
long sum = 4396;
long guess = 10000, guessCopy, otherSum = 0;
short count = 0;
//the digits used to guess the number
long[] digits = new long[5];
while(guess <= 99999)
{
//sets the different indexes of digits[] to the digits of guess
guessCopy = guess;
count = 0;
while(guessCopy > 0)
{
digits[count] = (guessCopy % 10);
guessCopy = guessCopy / 10;
count++;
}
//determining if the guess is correct
otherSum = ((digits[4]*10) + digits[3]) * ((digits[2]*100) + (digits[1]*10) + digits[0]);
if(otherSum == sum)
{
//Print out digits that work
for(int i = 0; i > digits.length; i++)
{
System.out.println(digits[i]);
//print out the separation between different solutions
if(i == digits.length -1)
{
System.out.println("next possible solution");
}
}
}
//iterating the guess
guess++;
}
}
}
For one, your digits are backwards in your otherSum calculation line. Also, your loop to print digits has the wrong comparison sign, it should be i < digits.length. Here is working code you should replace in:
//determining if the guess is correct
otherSum = ((digits[0]*10) + digits[1]) * ((digits[2]*100) + (digits[3]*10) + digits[4]);
if(otherSum == sum)
{
//Print out digits that work
for(int i = 0; i < digits.length; i++)
{
System.out.println(digits[i]);
//print out the separation between different solutions
if(i == digits.length -1)
{
System.out.println("next possible solution");
}
}
}
You might also want to consider switching your output to look better, right now its very vertical and tough to interpret.
I have a simple Java method, which is suppose to compute a list of prime divisors of a certain number.
public class Factors {
public static List<Integer> fac(List<Integer> factors, int number) {
if(number < 2) {
throw new IllegalArgumentException("Number must be greater than one");
}
for (int i = 2; i <= number; i++) {
while (number%i == 0) {
factors.add(i);
number /= i;
}
}
return factors;
}
public static void main(String [] args)
{
final long startTime = System.currentTimeMillis();
ArrayList<Integer> factors = new ArrayList<>();
System.out.println(fac(factors, 2147483647));
final long endTime = System.currentTimeMillis();
System.out.println("Total execution time: " + (endTime - startTime) );
}
}
This code works fine, except you feed Integer.MAX_VALUE into it; in that case giving:
java.lang.OutOfMemoryError: Java heap space
Initially, I thought, that this is due to, that ArrayList initialization was inside a method, but after removing, the same error persists.
Moreover, this:
public static List<Long> facrec2(List<Long> list, long number) {
if (number < 2) {
return list;
}
if (number == 2) {
list.add(2L);
return list;
}
for (long i = 2; i <= number; i++) {
while (number % i == 0) {
number /= i;
list.add(i);
return facrec2(list, number);
}
}
return null;
}
method works for max values (after changing signature to Integer, works for Integer max value too). Logic of both suppose to be the same, only recursive implementation of the second makes the difference...
for (int i = 2; i <= number; i++) {
The problem is here. If number == Integer.MAX_VALUE this loop will never terminate. Once i gets to Integer.MAX_VALUE, the next increment sets it to Integer.MIN_VALUE, which is very negative, and the loop continues to execute, so you will keep adding to the list forever and run out of memory.
The simplest solution is to change the loop condition to < and handle the case where number still has its original value separately (i.e. the case where number is prime). You can also exit the loop once number == 1.
This loop never terminates. When counter i reaches Integer.MAX_VALUE it rolls over. You should not allow equality in the loop condition.
The problem I'm trying to solve comes from ProjectEuler.
Some integers have following property:
n + reverse(n) = a number consisting entirely of odd digits.
For example:
14: 14 + 41 = 55
Numbers starting or ending with 0 aren't allowed.
How many of these "reversible" numbers are there below 10^9?
The problem also gives a hint:
there are 120 such numbers below 1000.
I'm quite new to Java, and I tried to solve this problem by writing a program that checks all the numbers up to a billion, which is not the best way, I know, but I'm ok with that.
The problem is that my program gives out a wrong amount of numbers and I couldn't figure out why! (The code will most likely contain some ugly things, feel free to improve it in any way)
int result = 0;
boolean isOdd = true;
boolean hasNo0 = true;
public int reverseNumber(int r) //this method should be working
{ //guess the main problem is in the second method
int n = 0;
String m = "";
if (r % 10 == 0) { hasNo0 = false; }
while (r > 0){
n = r % 10;
m = String.valueOf(m+n);
r /= 10;
}
result = Integer.parseInt(m);
return result;
}
public void isSumOdd(int max)
{
int number = 1;
int sum = 0;
Sums reverseIt = new Sums();
int amount = 0;
while (number <= max)
{
sum = reverseIt.reverseNumber(number) + number;
while (sum > 0)
{
int x = sum % 10;
if (x % 2 == 0) { isOdd = false; }
sum /= 10;
}
if (isOdd && hasNo0) { amount++; }
number++;
isOdd = true;
hasNo0 = true;
}
System.out.println(amount);
}
Called by
Sums first = new Sums();
first.reversibleNumbers(1000000000);
The most important problem in your code is the following line:
sum = reverseIt.reverseNumber(number) + number;
in isSumOdd(int max) function. Here the reverseIt object is a new instance of Sums class. Since you are using Sums member data (the boolean variables) to signal some conditions when you use the new instance the value of these member variables is not copied to the current caller object. You have to change the line to:
sum = this.reverseNumber(number) + number;
and remove the Sums reverseIt = new Sums(); declaration and initialization.
Edit: Attempt to explain why there is no need to instantiate new object instance to call a method - I've found the following answer which explains the difference between a function and a (object)method: https://stackoverflow.com/a/155655/25429. IMO the explanation should be enough (you don't need a new object because the member method already has access to the member data in the object).
You overwrite odd check for given digit when checking the next one with this code: isOdd = false;. So in the outcome you check only whether the first digit is odd.
You should replace this line with
idOdd = idOdd && (x % 2 == 0);
BTW. You should be able to track down an error like this easily with simple unit tests, the practice I would recommend.
One of the key problems here is that your reverseNumber method does two things: check if the number has a zero and reverses the number. I understand that you want to ignore the result (or really, you have no result) if the number is a multiple of 10. Therefore, you have two approaches:
Only send numbers into reverseNumber if they are not a multiple of 10. This is called a precondition of the method, and is probably the easiest solution.
Have a way for your method to give back no result. This is a popular technique in an area of programming called "Functional Programming", and is usually implemented with a tool called a Monad. In Java, these are implemented with the Optional<> class. These allow your method (which always has to return something) to return an object that means "nothing at all". These will allow you to know if your method was unable or unwilling to give you a result for some reason (in this case, the number had a zero in it).
I think that separating functionnalities will transform the problem to be easier. Here is a solution for your problem. Perhaps it isn't the best but that gives a good result:
public static void main(final String [] args) {
int counter = 0;
for (int i = 0; i < 20; i++) {
final int reversNumber = reverseNumber(i);
final int sum = i + reversNumber;
if (hasNoZeros(i) && isOdd(sum)) {
counter++;
System.out.println("i: " + i);
System.out.println("r: " + reversNumber);
System.out.println("s: " + sum);
}
}
System.out.println(counter);
}
public static boolean hasNoZeros(final int i){
final String s = String.valueOf(i);
if (s.startsWith("0") || s.endsWith("0")) {
return false;
}
return true;
}
public static int reverseNumber(final int i){
final StringBuilder sb = new StringBuilder(String.valueOf(i));
return Integer.parseInt(sb.reverse().toString());
}
public static boolean isOdd(final int i){
for (final char s : String.valueOf(i).toCharArray()) {
if (Integer.parseInt(String.valueOf(s))%2 == 0) {
return false;
}
}
return true;
}
the output is:
i: 12
r: 21
s: 33
i: 14
r: 41
s: 55
i: 16
r: 61
s: 77
i: 18
r: 81
s: 99
4
Here is a quick working snippet:
class Prgm
{
public static void main(String args[])
{
int max=(int)Math.pow(10, 3); //change it to (10, 9) for 10^9
for(int i=1;i<=max;i++)
{
if(i%10==0)
continue;
String num=Integer.toString(i);
String reverseNum=new StringBuffer(num).reverse().toString();
String sum=(new Long(i+Long.parseLong(reverseNum))).toString();
if(sum.matches("^[13579]+$"))
System.out.println(i);
}
}
}
It prints 1 number(satisfying the condition) per line, wc is word count linux program used here to count number of lines
$javac Prgm.java
$java Prgm
...//Prgm outputs numbers 1 per line
$java Prgm | wc --lines
120
This problem has me puzzled. I tried using a loop like this: Basically I tried to get the first digit from the input and do the formula but it doesn't seem to work. It looks so simple but I can't figure it out. Could you help me? Thanks.
public static int ISBN(String ninedigitNum) {
number = 9;
while (number > 0) {
int nextDigit = ninedigitNum.substring(0,1);
...
}
Checksums (Source: Princeton University). The International Standard
Book Number (ISBN) is a 10 digit code that uniquely specifies a book.
The rightmost digit is a checksum digit which can be uniquely
determined from the other 9 digits from the condition that d1 + 2d2 +
3d3 + ... + 10d10 must be a multiple of 11 (here di denotes the ith
digit from the right). The checksum digit d1 can be any value from 0
to 10: the ISBN convention is to use the value X to denote 10.
Example: the checksum digit corresponding to 020131452 is 5 since is
the only value of d1 between 0 and and 10 for which d1 + 2*2 + 3*5 +
4*4 + 5*1 + 6*3 + 7*1 + 8*0 + 9*2 + 10*0 is a multiple of 11. Create a
Java method ISBN() that takes a 9-digit integer as input, computes the
checksum, and returns the 10-digit ISBN number. Create 3 JUnit test
cases to test your method.
I got it, thanks a lot everyone!
What about it isn't working? Either way, I believe what you're missing is that you're continually getting the same substring, which will be the first number of the string: int nextDigit = ninedigitNum.substring(0,1);. In addition, you're going to want to use an int, not a String; you can technically convert from String to int if desired, but the problem itself calls for an int.
There are two ways to do this that jump to mind. I would do this by realizing that mod in powers of 10 will give you the respective digit of an integer, but the easier way is to convert to a char array and then access directly. Note that there's no error checking here; you'll have to add that yourself. In addition, there are a LOT of 'magic numbers' here: good code typically has very, very few. I would recommend learning more data structures before attempting problems like these; to be honest there's very few things you can do without at least arrays and linked lists.
char[] ISBN = ninedigitNum.toCharArray();
//Process each number
int total = 0;
for(int i=0; i<9; i++){
int current_int = Integer.parseInt(ISBN[i]);
total += current_int * (10 - i)
}
//Find value of d1
for(int i=0; i<9; i++){
if(((total + i) % 11) == 0){
total += i*100000000;
break;
}
}
return total;
In general: Use print outs with System.out.println(x); or use your compiler's debugger to see what's going on during processing.
So,
This is the piece of code that I wrote. I still think it could be made more efficient.
public class Problem3 {
public static String ISBN(String x)
{
char[]temp = x.toCharArray();
int counter = 2;
int sum = 0;
int j=0;
for(int i=8;i>=0;i--)
{
sum+= counter*Integer.parseInt(""+temp[i]);
counter+=1;
}
for(j=0;j<10;j++)
{
if((sum+j)%11==0)
{
break;
}
}
return x+""+j;
}
public static void main(String args[])
{
String a = "020131452";
System.out.println(ISBN(a));
}
}
Hope this helps.
This works:
public static int ISBN(String nineDigitNum){
int sum = 0;
for(int i = 0; i<nineDigitNum.length(); i++){
sum += Integer.parseInt(""+nineDigitNum.charAt(i))*(10-i);
}
return (sum%11);
}
Also I believe if the checksum is == to 10, it should return an X, so you could either change the return type and add an if statement somewhere, or just put the if statement outside wherever you are using this method.
Here is a short one without loops that uses only substring(), charAt() and length():
public static String ISBN(String nineDigits) {
int chkD = 11 - checkDigit(nineDigits, 0);
return nineDigits + ((chkD == 10) ? "X" : chkD);
}
public static int checkDigit(String nDsub, int chkD) {
if (nDsub.length() == 0)
return 0;
chkD = ((nDsub.charAt(0) - '0') * (nDsub.length() + 1));
return (chkD + checkDigit(nDsub.substring(1), chkD)) % 11;
}
Output:
> ISBN("123456789")
"123456789X"
> ISBN("123456780")
"1234567806"
I've come to a part in my code where I must generate a random number every time I press a button (r in this case). When I press this button, I want it to generate a number between 0 and n (3 in this case), but I don't want it to generate a number it previously generated. So I do not want the same number to be generated twice in a row. So 2 then 2 is bad. 2 then 0 then 2 is OK however.
I've looked around on here for questions similar to mine but none of them have really helped. Everyone else is generating once with the exception of numbers in an array or something. I'm constantly generating and I want to be able to detect the same number previous.
I am using the Random class, I have considered using the math.random class but that is between 0 and 1 so that isn't really too useful. Any help would be greatly appreciated, thanks! :D
Memorize what you generated last time; repeat generating until they are different
Say you want numbers 0-9
do
{
int n = Random.nextInt(10);
} while (n == prev) // prev is the number you generated previously
prev = n;
Since you have n possible values for the first, and only n-1 for the subsequent, just use randInt with a different argument depending on whether you're producing the first value or not. Trying to use randInt with the same arguments for all iterations will result in a non-flat distribution.
class NoAdjacentPRNG implements Iterator<Integer> {
private final Random rnd;
private final int range; // 3 to generate numbers in [0, 2).
private Integer last;
NoAdjacentPRNG(Random rnd, int range) {
this.rnd = rnd;
this.range = range;
}
public boolean hasNext() { return true; }
public Integer next() {
int n;
if (last == null) {
// The first time through, there are range possible values.
n = rnd.nextInt(range);
} else {
// There are only range-1 possible values given that the
// last is excluded.
n = rnd.nextInt(range - 1);
// Work around last.
if (n >= last) { ++n; }
}
last = n;
return n;
}
public void remove() { throw new UnsupportedOperationException(); }
}
You can do something like
int[] values = new int[360];
values[0] = random.nextInt(n+1);
for(int i = 0; i < values.length; i++) {
values[i] = random.nextInt(n);
if (values[i-1] == values[i]) values[i] = n;
}
You can even be super-simple:
public class NonRepeatingRandom extends Random {
private int last = -1;
#Override
public int nextInt(int i) {
int next = super.nextInt(i);
while ( next == last) {
next = super.nextInt(i);
}
return last = next;
}
}