why the program is skipping while loop - java

Why does my program skip the while loop?
class DigitRepeat
{
public static void main(String args[])
{
int n=133,dig=3,digit,count=0;
while(n!=0)
{
digit=n%10;
if(dig==digit)
{
count=count++;
}
n=n/10;
}
if(count==0)
System.out.println("digit not found");
else
System.out.println("digit occurs "+count+" times.");
}
}

> count=count++;
should be
> count++;
explain:
> count=count++;
is
a_temp_var=count;
count=count+1;
count=a_temp_var;
equals to:
a_temp_var=count;
count=a_temp_var;
equals to do nothing.

If I look at the code in my IDE it warns
The value changed at count++ is never used.
i.e. it is warning me that the value calculated is discarded.
If I step through the code in my debugger, I can see the loop is executed but the line
count = count++;
does not change count.
You want either
count++;
count+=1;
count=count+1;

I do not know what do you mean that the program skips something.
But I think I can see your bug. It is here:
count=count++;
++ operator increments count after the assumption, so the variable count remains 0 forever.
I think that you wanted to say count++;

You've got a little error in your code:
count = count++;
Should be change to:
count++;
Have a look over here for a running example, all I did was remove the assignment.
(Included for completeness)
int n = 133;
int dig = 3;
int digit;
int count = 0;
while (n != 0)
{
digit = n % 10;
if (dig == digit)
{
count++;
}
n = n / 10;
}
if(count = =0)
System.out.println("digit not found");
else
System.out.println("digit occurs " + count + " times.");

First advice: when you think your program is skipping a loop add a print after the while it will help you narrow down the problem.
Then you have to be careful with post increments. the value countRight is assigned to countLeft then countLeft is incremented but it doesn't matter because the value of count is already set. the value of count is copied therefore when the ++ takes effect its on a different count (sorry if this isn't so clear).
you can use :
count++;
count = count +1;
count += 1;
or count = ++count;
the last one pre increment works because the value is incremented before being copied ^^
(read up on this because it always turns up in interviews ^^

Here is kinda what you're trying to code in C#:
class Program
{
static void Main(string[] args)
{
var number = 12289;
var search = 2;
var count = Search(number, search);
}
static int Search(int number, int search)
{
return number < 10 ?
(number == search ? 1 : 0) :
(number % 10 == search ? 1 : 0)
+ Search((int)Math.Floor(number / (double)10), search);
}
}

Related

Multiplicative Sum Solver not functioning

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.

This code runs and compiles but nothing happens when I enter a very large number. (Euler project, problem 3)

I'm a newbie.
So I've been doing the project Euler problems to sharpen my java skills and I got past the first 2. I'm stuck on the third one. It says :
"The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?"
I wrote the following code:
public class Exercise {
public static void main(String[] args) {
long a = 600851475143L;
long i = 1;
boolean isPrime = true;
long currentNum = 0;
while (i <= a) {
if (a % i == 0) {
for (long j = 1; j < a; j++) {
if (a == i || a % j == 0) {
isPrime = false;
} else {
currentNum = i;
}
}
}
i++;
}
System.out.println("the largest prime factor of " + a + " is " + currentNum);
}
}
It works perfectly for smaller numbers like 10,20,55,100,560523 etc but when I enter a large number like 600851475143L, the code compiles and runs but nothing happens.
Any help appreciated, thanks !
Look at your a variable. It's 600851475143L.
That means that your processor has to do up to 600851475143 loop cycles, based on your condition:
while (i <= a) {
i++;
}
I do not take into consideration the code inside the while() loop, but even without it that is too much, even for modern computers :)
If you want to calculate prime factors of numbers of that range... you should consider using some more efficient ways than simple iteration.
You have nested conditions, executions of which will hop CPU.
while (i <= a) {// This condition will be executed 600851475143 times
if (a % i == 0) {
for (long j = 1; j < a; j++) {// This condition will be executed 600851475143 times
So far a=600851475143, code will execute 600851475143*600851475143 times. That's why you don't see output as CPU is busy executing so many conditions.
Also reason you saw output for a=100 because for this input number of iterations = 100*100 which won't take much time on any modern machine
public class Exercise {
public static void main(String[] r)
{
try{
long a = 600851475143L;
System.out.println("the largest prime factor of " + a+ " is " +largestPrimeFactor(a) );
}catch(Exception e)
{
e.printStackTrace();
}
}
public static int largestPrimeFactor(long number) {
int i;
long copyOfInput = number;
for (i = 2; i <= copyOfInput; i++) {
if (copyOfInput % i == 0) {
copyOfInput /= i;
i--;
}
}
return i;
}
}
Try this one
The answer given by Pavel Smirnov is correct. Actually, the code is running for value 600851475143L as well. It's just that the input number is huge so the code is taking hell lot of time to finish. Even the code is not in the deadlocked state. Still, to prove the point to you, you can add a log in the inner-loop body like:
System.out.println("Testing Prime for Number :"+j);
in the inner-loop for (long j = 1; j < a; j++){}
Doing this, you will see that the code is actually running.
P.S.: This algorithm will loop 600851475143L * 600851475143L times, which is really time-consuming.

All digits in int are divisible by certain int

I am trying to figure out how to count all numbers between two ints(a and b), where all of the digits are divisible with another int(k) and 0 counts as divisible.Here is what I've made so far, but it is looping forever.
for (int i = a; i<=b; i++){
while (i < 10) {
digit = i % 10;
if(digit % k == 0 || digit == 0){
count ++;
}
i = i / 10;
}
}
Also I was thinking about comparing if all of the digits were divisible by counting them and comparing with number of digits int length = (int)Math.Log10(Math.Abs(number)) + 1;
Any help would be appreciated. Thank you!
Once you get in to your while block you're never going to get out of it. The while condition is when i less than 10. You're dividing i by 10 at the end of the whole block. i will never have a chance of getting above 10.
Try this one
public class Calculator {
public static void main(String[] args) {
int a = 2;
int b = 150;
int k = 3;
int count = 0;
for (int i = a; i <= b; i++) {
boolean isDivisible = true;
int num = i;
while (num != 0) {
int digit = num % 10;
if (digit % k != 0) {
isDivisible = false;
break;
}
num /= 10;
}
if (isDivisible) {
count++;
System.out.println(i+" is one such number.");
}
}
System.out.println("Total " + count + " numbers are divisible by " + k);
}
}
Ok, so there are quite a few things going on here, so we'll take this a piece at a time.
for (int i = a; i <= b; i++){
// This line is part of the biggest problem. This will cause the
// loop to skip entirely when you start with a >= 10. I'm assuming
// this is not the case, as you are seeing an infinite loop - which
// will happen when a < 10, for reasons I'll show below.
while (i < 10) {
digit = i % 10;
if(digit % k == 0 || digit == 0){
count ++;
// A missing line here will cause you to get incorrect
// results. You don't terminate the loop, so what you are
// actually counting is every digit that is divisible by k
// in every number between a and b.
}
// This is the other part of the biggest problem. This line
// causes the infinite loop because you are modifying the
// variable you are using as the loop counter. Mutable state is
// tricky like that.
i = i / 10;
}
}
It's possible to re-write this with minimal changes, but there are some improvements you can make that will provide a more readable result. This code is untested, but does compile, and should get you most of the way there.
// Extracting this out into a function is often a good idea.
private int countOfNumbersWithAllDigitsDivisibleByN(final int modBy, final int start, final int end) {
int count = 0;
// I prefer += to ++, as each statement should do only one thing,
// it's easier to reason about
for (int i = start; i <= end; i += 1) {
// Pulling this into a separate function prevents leaking
// state, which was the bulk of the issue in the original.
// Ternary if adds 1 or 0, depending on the result of the
// method call. When the methods are named sensibly, I find
// this can be more readable than a regular if construct.
count += ifAllDigitsDivisibleByN(modBy, i) ? 1 : 0;
}
return count;
}
private boolean ifAllDigitsDivisibleByN(final int modBy, final int i) {
// For smaller numbers, this won't make much of a difference, but
// in principle, there's no real reason to check every instance of
// a particular digit.
for(Integer digit : uniqueDigitsInN(i)) {
if ( !isDigitDivisibleBy(modBy, digit) ) {
return false;
}
}
return true;
}
// The switch to Integer is to avoid Java's auto-boxing, which
// can get expensive inside of a tight loop.
private boolean isDigitDivisibleBy(final Integer modBy, final Integer digit) {
// Always include parens to group sub-expressions, forgetting the
// precedence rules between && and || is a good way to introduce
// bugs.
return digit == 0 || (digit % modBy == 0);
}
private Set<Integer> uniqueDigitsInN(final int number) {
// Sets are an easy and efficient way to cull duplicates.
Set<Integer> digitsInN = new HashSet<>();
for (int n = number; n != 0; n /= 10) {
digitsInN.add(n % 10);
}
return digitsInN;
}

Euler 14 - Runtime too long (Not really duplicate, I didn't understand how to solve it from similar answer)

So I'm solving Question #14 on ProjectEuler and my code's output is not coming out. The method is good, if I use the example from the website I get the same result BUT I think I get stuck in loop, I don't get a result even if I use a number like "3" or "4" not 1,000,000. What I'm doing wrong? I tried to understand the last question and I didn't really get much with that cache stuff.Here is my code:
import java.util.Arrays;
public class problem_14 {
// n->n/2 (even)
// n->3n+1(odd)
static long max=0;
static long counter = 0;
//Which starting number, under one million, produces the longest chain?
public static long dochain(long n){
while(n!=1){
if(n%2==0){
n=n/2;
counter++;
}
else {
n=(3*n)+1;
counter++;
}
}
counter++;
return counter;
}
public static void main(String args[]){
long chain=0;;
long nr=0;
for(int i=0;i<1000000;i++){
chain = dochain(i);
if (chain>max){
max = chain;
nr = i;
}
System.out.println("nr="+nr+" lungime="+max);
}
}
}
Your dochain() method goes into an infinite loop if you give it a 0.
while (n != 1) {
if (n % 2 == 0) { // true for n == 0
n = n / 2; // n is still 0
counter++;
} else {
n = (3 * n) + 1;
counter++;
}
}
You are checking if it's divisible by 2, which it is, then dividing by 2, which leaves n == 0 and looping forever.
Since your main for loop starts at 0...
You are starting your for loop from i = 0 which is causing dochain() to run infinitely.
Start from i =1.

Why will my for loop not read my last char of the string?

I am trying to write a basic java program to compress a java string from an input; such as aabbccdddd, into a2b2c2d4. The program does what I ask except it doesn't process the last char, I am getting an output of a2b2c2 instead of the a2b2c2d4. What am I doing wrong?
for(x = 0, y = 1; x<input.length()-1; x++)
{
if (input.charAt(x) != input.charAt(x+1) && count == 1)
{
System.out.print(input.charAt(x));
System.out.print(count);
}
else if (input.charAt(x) == input.charAt(x+y))
{
count++;
}
else if (input.charAt(x) != input.charAt(x+1) && count >= 2)
{
System.out.print(input.charAt(x));
System.out.print(count);
count = 1;
}
else
{
System.out.println("fail");
}
}
You print the count when the next character is not same as the current one. There is no next character for the last character. That is why it is not displayed in the output.
Approach 1
You should add following two lines after the loop:
System.out.print(input.charAt(input.length()-1));
System.out.println(count);
Approach 2
If you do not have problem with modifying the original input. You can add a additional character in the end of the input. This additional character must be a character which will never appear in the original string. Say it is #
Do this before beginning of the loop:
input += "#";
for(...)
The loop is incorrect, you have "-1" after input.length(). Try:
for(x = 0, y = 1; x<input.length(); x++) {
// CODE HERE...
}
Your for loop ends before you hit a condition that forces you to print out what's being buffered, ie. count of 4 for the current (last) character. You need to print out the last character and the current count after the loop.
The following should do what you want
public static void main(String[] args) throws Exception {
String input = "aabbccdddd";
int count= 1;
int x, y;
for (x = 0, y = 1; x < input.length() - 1; x++) {
char charAtX = input.charAt(x);
char charAtXPlus1 = input.charAt(x + 1);
if ( charAtX != charAtXPlus1 && count == 1) {
System.out.print(input.charAt(x));
System.out.print(count);
}
else if (charAtX == input.charAt(x + y)) {
count++;
}
else if (charAtX != charAtXPlus1 && count >= 2) {
System.out.print(input.charAt(x));
System.out.print(count);
count = 1;
} else {
System.out.println("fail");
}
}
System.out.print(input.charAt(x));
System.out.println(count);
}
You should learn how to use a proper debugger and use proper debugging techniques. For example, I've assigned the value returned by input.charAt(x) to a variable because we reuse that value in the various if-else conditions and because it's easier to see it in a debug window.
You are not able to get the desired result because of the condition
else if(input.charAt(x)!=input.charAt(x+1)&&count>=2)
that fails as there is not character at x+1 location.
So, you could add another condition to check if it's the last character and then go ahead with your code
while (input.charAt(x) != input.length()-1)

Categories

Resources