hasOne challenge

Hi,

I am working on below challenge
http://codingbat.com/prob/p191212

Psedo code:
1. for given number % with 10
2. if 1 return true
3. else return false

I wrote my code as below

public boolean hasOne(int n) {
  if(n%10==1){
  
 // if(n/10==1){
  return true;
 // }
  }
  return false;
  
}

Open in new window




I am not passing all tests
Expected      Run            
hasOne(10) → true      false      X      
hasOne(22) → false      false      OK      
hasOne(220) → false      false      OK      
hasOne(212) → true      false      X      
hasOne(1) → true      true      OK      
hasOne(9) → false      false      OK      
hasOne(211112) → true      false      X      
hasOne(121121) → true      true      OK      
hasOne(222222) → false      false      OK      
hasOne(56156) → true      false      X      
hasOne(56556) → false      false      OK      
other tests
X      

How to improve/modify my design, code and any other alternate approaches. please advise
LVL 7
gudii9Asked:
Who is Participating?
 
d-glitchConnect With a Mentor Commented:
The problem statement gives you almost the complete pseudo code:
[Loop until you have checked all the digits or found a 1] 
     use % to get [and check] the rightmost digit, and
     [then use] / to discard the rightmost digit.

Open in new window

0
 
CPColinConnect With a Mentor Senior Java ArchitectCommented:
You need to examine all the digits of the input and return true if you see a 1. Your code, as it's currently written, looks at only the right-most digit.
0
 
gudii9Author Commented:
how to look 2nd 3rd 4th etc digits?
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
CPColinSenior Java ArchitectCommented:
The challenge description gives you a hint.
0
 
d-glitchCommented:
Print out values for n%10 and n/10 for several values of n.

How do the answers relate to n.
0
 
rrzCommented:
Is it cheating to use String method? I remember krakatoa showed you how to do it on other challenges in the past.
0
 
d-glitchCommented:
The challenge specifically said to use % and / .
0
 
d-glitchCommented:
What are  13345/10   and   12345%10  ?
0
 
gudii9Author Commented:
13345/10   is 1334
and   12345%10  is 5
0
 
gudii9Author Commented:
Expected      Run            
hasOne(10) → true      false      X      
hasOne(22) → false      false      OK      
hasOne(220) → false      false      OK      
hasOne(212) → true      false      X      
hasOne(1) → true      true      OK      
hasOne(9) → false      false      OK      
hasOne(211112) → true      false      X      
hasOne(121121) → true      true      OK      
hasOne(222222) → false      false      OK      
hasOne(56156) → true      false      X      
hasOne(56556) → false      false      OK      
other tests
X      

i am failing above four tests
0
 
gudii9Author Commented:
10 then  212 then 211112 then 56156. how to cover those test cases and 1 is hiding somewhere in the middle in them not at beginning?
0
 
d-glitchCommented:
12345%10  is 5
12345/10   is 1234

The answer is there if you think about it.
0
 
gudii9Author Commented:
i have to loop through each digit and check if it is one or not by doing both % and / ?
0
 
d-glitchCommented:
What does the Challenge say about using the / operator?
0
 
gudii9Author Commented:
/ to discard the rightmost digit.
0
 
gudii9Author Commented:
public boolean hasOne(int n) {
 if (n % 10 == 1) {

  // if(n/10==1){
  return true;
  // }
 } else {
  if ((n / 10) % 10 == 1) {
   return true;
  } else {
   if ((n / 100) % 10 == 1) {
    return true;
   }
  }
 }
 return false;

}

Open in new window

above pased all tests. any improvements or alternate approaches?
0
 
d-glitchCommented:
After the discard, there is a new rightmost digit to check.
0
 
d-glitchCommented:
That code is not correct.  Post your actual results, and try some longer cases.

Like 12345

If n is a five digit number, then you have to do five tests.
0
 
rrzCommented:
The if statement is not the only looping control flow statement.  
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/while.html
1
 
d-glitchCommented:
Your most recent code is not correct.  
It will fail for  1,  21,  301,  1001,  10001, and an infinite number of other cases.

This checks the tens digit of two digit numbers:
if(n/10==1)   return true 

Open in new window

This checks the tens and hundreds digits of all numbers:
if ((n / 10) % 10 == 1)    return true
if ((n / 100) % 10 == 1)   return true 

Open in new window

But you never check the units digit, you don't check anything higher than the hundreds digit, and you don't use the / operator to trim rightmost digits as the challenge suggested.
0
 
gudii9Author Commented:
public boolean hasOne(int n) {
  if(n%10==1){
  
 // if(n/10==1){
  return true;
 // }
  }
  
  else {
  if( (n/10)%10==1 ){
    return true;
  }
  else {
  if( (n/100)%10==1 ){
    return true;
  }}
  }
  return false;
  
}

Open in new window


Expected      Run            
hasOne(10) → true      true      OK      
hasOne(22) → false      false      OK      
hasOne(220) → false      false      OK      
hasOne(212) → true      true      OK      
hasOne(1) → true      true      OK      
hasOne(9) → false      false      OK      
hasOne(211112) → true      true      OK      
hasOne(121121) → true      true      OK      
hasOne(222222) → false      false      OK      
hasOne(56156) → true      true      OK      
hasOne(56556) → false      false      OK      
other tests
OK

my code passes all test cases in codingbat but looks like it fails other test cases mentioned by you. let me refine my code further
0
 
gudii9Author Commented:
package com.solution;

public class HasOne {
	public static void main(String[] args) {
		System.out.println("value  is-->"+hasOne(21));
		
	}
	
	public static boolean hasOne(int n) {
		  if(n%10==1){
		  
		 // if(n/10==1){
		  return true;
		 // }
		  }
		  
		  else {
		  if( (n/10)%10==1 ){
		    return true;
		  }
		  else {
		  if( (n/100)%10==1 ){
		    return true;
		  }}
		  }
		  return false;
		  
		}


}
[code]

Open in new window

[/code]

my code passed for 21 as well
0
 
gudii9Author Commented:
Even it passed for 1 also
package com.solution;

public class HasOne {
	public static void main(String[] args) {
		System.out.println("value  is-->"+hasOne(1));
		
	}
	
	public static boolean hasOne(int n) {
		  if(n%10==1){
		  
		 // if(n/10==1){
		  return true;
		 // }
		  }
		  
		  else {
		  if( (n/10)%10==1 ){
		    return true;
		  }
		  else {
		  if( (n/100)%10==1 ){
		    return true;
		  }}
		  }
		  return false;
		  
		}


}

Open in new window


value  is-->true
0
 
gudii9Author Commented:
Even passed for 1001 also
[code]package com.solution;

public class HasOne {
	public static void main(String[] args) {
		System.out.println("value  is-->"+hasOne(1001));
		
	}
	
	public static boolean hasOne(int n) {
		  if(n%10==1){
		  
		 // if(n/10==1){
		  return true;
		 // }
		  }
		  
		  else {
		  if( (n/10)%10==1 ){
		    return true;
		  }
		  else {
		  if( (n/100)%10==1 ){
		    return true;
		  }}
		  }
		  return false;
		  
		}


}

Open in new window

[/code]

value  is-->true
0
 
d-glitchCommented:
What is your algorithm, approach, pseudo code?

How do you print out/find only the first/ones digit?
How do you print out/find only the second/tens digit?
How to print out the n digits that make up a number one at a time using the % and / operators?

How do you extend your approach to numbers with arbitrary numbers of digits?
How will you test all digits of a n-digit number like 1234567?
What is you control structure?
You can't do this without a loop, and you don't have one.

Stop trying to fix your code.  It is a mess.  Go back and think about the answers to the questions I have asked.
0
 
CPColinSenior Java ArchitectCommented:
Yeah, try passing your code 10000 and see if that works. (The values Codingbat selected aren't very good!)
0
 
rrzCommented:
My comment above here was wrong.
The if statement is not the only looping control flow statement.
I meant to post;
The for statement is not the only looping control flow statement.
There is also the while statement. It will come in handy for this challenge.
0
 
gudii9Author Commented:
Yeah, try passing your code 10000 and see if that works. (The values Codingbat selected aren't very good!)

above gives false instead of true(which is wrong)
package com.solution;

public class HasOne {
	public static void main(String[] args) {
		System.out.println("value  is-->" + hasOne(10000));

	}

	public static boolean hasOne(int n) {
		if (n % 10 == 1) {

			// if(n/10==1){
			return true;
			// }
		}

		else {
			if ((n / 10) % 10 == 1) {
				return true;
			} else {
				if ((n / 100) % 10 == 1) {
					return true;
				}
			}
		}
		return false;

	}

}

Open in new window


value  is-->false

let me refine my code
0
 
d-glitchCommented:
You need to work on your pseudo code not your code.
You need a control loop to solve this problem.
0
 
gudii9Author Commented:
There is also the while statement. It will come in handy for this challenge.

below passed all tests including 10000
public boolean hasOne(int n) {
  boolean result=false;

		while (n > 0) {
			if ((n % 10) == 1)
				result=true;
			n=(n/10);

		}
		return result;
	}

Open in new window


any improvements or alternate approach for this?
cannot i use for loop for this which i am more habituated with?
0
 
gudii9Author Commented:
psedo code is
1. loop though given array using while loop until given number greater than zero
2. if reminder of given number modulus 10 is 1 return true
3. else go to next digit by doing / on given number and again check % to see is 1
4. loop till end.
5. return false if no one found as any digiy
0
 
d-glitchCommented:
That took a long time, but it is perfect.  Yes, you can use any kind of loop you want.

The number of digits in an integer n is related to the logarithm of n to the base 10.
You could also assume that n has less than twenty (or some other large number) of digits.
Both of these techniques are less elegant and efficient than the while loop.
0
 
CPColinSenior Java ArchitectCommented:
The for loop isn't going to look or act all that different from the while loop. The one thing I would change is that as soon as you find a 1, you can return true right then and skip the rest of the loop.
1
 
gudii9Author Commented:
How to write using for loop?
package com.solution;

public class HasOne {
	public static void main(String[] args) {
		System.out.println("value  is-->" + hasOne(10000));

	}

	public static boolean hasOne(
			int n) {/*
					 * 
					 * while (n > 0) { if (n % 10 == 1) return true; n=n/10;
					 * 
					 * } return false;
					 */
		// }

		for (int i = n; i>0; i++) {
			if (n % 10 == 1)
				return true;
			n = n / 10;

			return false;
		}
		return false;

	}
}

Open in new window

above give wrong result
value  is-->false
0
 
gudii9Author Commented:
package com.solution;

public class HasOne {
	public static void main(String[] args) {
		System.out.println("value  is-->" + hasOne(10000));

	}

	public static boolean hasOne(
			int n) {/*
					 * 
					 * while (n > 0) { if (n % 10 == 1) return true; n=n/10;
					 * 
					 * } return false;
					 */
		// }

		for (int i = n; i>0; i--) {
			if (n % 10 == 1)
				return true;
			n = n / 10;

			return false;
		}
		return false;

	}
}

Open in new window

value  is-->false

even i-- also give false as above
0
 
CPColinSenior Java ArchitectCommented:
In general, this for loop:

for ( [initialize expression] ; [conditional expression] ; [increment expression] ) {
   [do some work]
}

Open in new window


is exactly equivalent to this code:

[initialize expression]
while ( [conditional expression] ) {
   [do some work]
   [increment expression]
}

Open in new window


In this case, you have no "initialize expression," your "conditional expression" is n > 0, and your "increment expression" is n = n / 10.
0
 
d-glitchCommented:
How do you now when to exit the loop?
How do you know when you have tested the last digit?

How many digits have you tested when you execute line 23?
0
 
d-glitchCommented:
You may be more familiar with the for loop, but there are cases (and this is one of them) where it will result in ugly or inefficient code.

Presumably that is why you are doing these challenges: to learn useful things that you don't already know.
0
 
gudii9Author Commented:
"increment expression" is n = n / 10.
i thought increment expression means i++/i--only
0
 
CPColinSenior Java ArchitectCommented:
In for loops, it doesn't necessarily have to be only an increment or decrement; you can increment, decrement, divide, call Iterator.next(), or all sorts of other things. (I called it the "increment expression" because that's what the tutorial calls it.)
0
 
gudii9Author Commented:
package com.solution;

public class HasOne {
	public static void main(String[] args) {
		System.out.println("value  is-->" + hasOne(10000));

	}

	public static boolean hasOne(
			int n) {/*
					 * 
					 * while (n > 0) { if (n % 10 == 1) return true; n=n/10;
					 * 
					 * } return false;
					 */
		// }
		for (int i=n; i>0;) {
			if (n % 10 == 1)
				return true;
			n = n / 10;

			
		}
		return false;

	}
}
/*In general, this for loop:
for ( [initialize expression] ; [conditional expression] ; [increment expression] ) {
   [do some work]
}
is exactly equivalent to this code:
[initialize expression]
while ( [conditional expression] ) {
   [do some work]
   [increment expression]
}
In this case, you have no "initialize expression," your "conditional expression" is n > 0, and your "increment expression" is n = n / 10.*/

Open in new window


above passed one test
0
 
gudii9Author Commented:
public boolean hasOne(int n) {
		for (int i=n; i>0;) {
			if (n % 10 == 1)
				return true;
			n = n / 10;

			
		}
		return false;

	}

Open in new window

fails some tests
Expected      Run            
hasOne(10) → true      true      OK      
hasOne(22) → false      Timed out      X      
hasOne(220) → false      Timed out      X      
hasOne(212) → true      Timed out      X      
hasOne(1) → true      Timed out      X      
hasOne(9) → false      Timed out      X      
hasOne(211112) → true      Timed out      X      
hasOne(121121) → true      Timed out      X      
hasOne(222222) → false      Timed out      X      
hasOne(56156) → true      Timed out      X      
hasOne(56556) → false      Timed out      X      
other tests
X      
0
 
CPColinSenior Java ArchitectCommented:
You can't have your conditional expression check i while your increment expression modifies n or your loop will never end. You have to modify the same variable you're checking.
0
 
gudii9Author Commented:
package com.solution;

public class HasOne {
	public static void main(String[] args) {
		System.out.println("value  is-->" + hasOne(10000));

	}

	public static boolean hasOne(
			int n) {/*
					 * 
					 * while (n > 0) { if (n % 10 == 1) return true; n=n/10;
					 * 
					 * } return false;
					 */
		// }
		for (int n=n; n>0;) {
			if (n % 10 == 1)
				return true;
			n = n / 10;

			
		}
		return false;

	}
}
/*In general, this for loop:
for ( [initialize expression] ; [conditional expression] ; [increment expression] ) {
   [do some work]
}
is exactly equivalent to this code:
[initialize expression]
while ( [conditional expression] ) {
   [do some work]
   [increment expression]
}
In this case, you have no "initialize expression," your "conditional expression" is n > 0, and your "increment expression" is n = n / 10.*/

Open in new window

how to intialize in this case of for loop as while loop do not have intialization?

eclipse gives below error


Multiple markers at this line
      - Duplicate local variable n
      - The assignment to variable n has
0
 
CPColinSenior Java ArchitectCommented:
Either initialize a new variable i and use only that variable inside the loop or just skip the initialize expression entirely. It's optional and n is already initialized, so you don't need it. This pattern, by the way, where you don't need the initialize expression and your increment expression isn't a simple ++ or --, is why d-glitch suggested using a while loop in the first place.
0
 
rrzCommented:
An interesting fact is the equivalency of
while(true){} loop and   for(;;){} loop .
0
 
d-glitchCommented:
Actually rrz suggested the while loop, although I think we were all aware of the possibility.
The reason you are having trouble with the for loop is because there is no need or reason to use i inside the loop.
There is definitely no reason to set it to n.
One reasonable choice  to set it to the number of digits in n.
0
 
CPColinSenior Java ArchitectCommented:
Oops, you're right. It was rrz. A reason you could want to use i inside the for loop, instead of n, is if your IDE is set to warn you when you change the value of a method parameter. At this point, though, I think we can all agree that the while loop does a better job of indicating what we're trying to do.
0
 
rrzCommented:
although I think we were all aware of the possibility

Yes, even  CodingBat itself.  
http://codingbat.com/doc/java-for-while-loops.html 
Here are quotes from that page.  
The for-loop is a variant of the while-loop,
The for-loop can actually be understood as equivalent to a while-loop version
0
 
rrzCommented:
After you  get the for-loop solution posted, we can post the String methods solution and the recursive solution.
0
 
gudii9Author Commented:
ok
0
 
gudii9Author Commented:
public boolean hasOne(int n) {/*
					 * 
					 * while (n > 0) { if (n % 10 == 1) return true; n=n/10;
					 * 
					 * } return false;
					 */
		// }
for (; n>0;) {
			if (n % 10 == 1)
				return true;
			n = n / 10;

			
		}
		return false;
	}

Open in new window


here is the for solution which passes all tests. Any improvements to it or alternative solutions to it?
0
 
d-glitchCommented:
Nope, looks good.  Time to move on.
0
 
rrzCommented:
I did it a little differently.
public boolean hasOne(int n) {
for(;n > 0; n = n/10){
  if(n % 10 == 1)return true;
}
		return false;
}

Open in new window

  Alternatively, we could use String methods.
public boolean hasOne(int n) {
  String inputString = Integer.toString(n);
  return inputString.contains("1");
}

Open in new window

Just for fun, I wrote a solution using recursion.
public boolean hasOne(int n) {
  if(n <= 0)return false;
  if(n % 10 == 1)return true;
  return hasOne(n/10);
}

Open in new window

1
 
gudii9Author Commented:
lets say my number is 321.
public boolean hasOne(int n) {
  if(n <= 0)return false;
  if(n % 10 == 1)return true;
  return hasOne(n/10);
}

Open in new window

using above recursion approach below  line

  if(n % 10 == 1)return true;

returns true and method wil be terminated right?
After that how flow comes to below line to call same method again?

 return hasOne(n/10);

Please advise
0
 
rrzConnect With a Mentor Commented:
returns true and method wil be terminated right?
Yes.
After that how flow comes to below line to call same method again?
It doesn't when input is 321.  
If we put debug statements, then we can see flow.  
public class HasOne{
	public static void main(String[] args){
	    System.out.println(" first test ");
		System.out.println(" input 321 gives output of " + hasOne(321));
		System.out.println(" second test ");
		System.out.println(" input 1234 gives output of " + hasOne(1234));
		System.out.println(" third test ");
		System.out.println(" input 789165432 gives output of " + hasOne(789165432));
	}
	public static boolean hasOne(int n) {
		System.out.println(" input to hasOne method was " + n);
		if(n <= 0)return false;
        if(n % 10 == 1)return true;
        return hasOne(n/10);
    }
}

Open in new window

The output is:
 first test
 input to hasOne method was 321
 input 321 gives output of true
 second test
 input to hasOne method was 1234
 input to hasOne method was 123
 input to hasOne method was 12
 input to hasOne method was 1
 input 1234 gives output of true
 third test
 input to hasOne method was 789165432
 input to hasOne method was 78916543
 input to hasOne method was 7891654
 input to hasOne method was 789165
 input to hasOne method was 78916
 input to hasOne method was 7891
 input 789165432 gives output of true
0
 
gudii9Author Commented:
public boolean hasOne(int n) {
 while (n > 0) { 
		if (n % 10 == 1)
		 return true;
 n=n/10;
 } 
 return false; 
		 	}

Open in new window


above is technically equivalent to below right


public boolean hasOne(int n) {
 while (n > 0) { 
		if (n % 10 == 1){
		  return true;
                }
n=n/10;
 } 
 return false; 

	}

Open in new window

i meant to say if(condition) statement without  begin { and end } will implicitly cover only next line as its statement right like above not like below


public boolean hasOne(int n) {
 while (n > 0) {
            if (n % 10 == 1){
              return true;
                  n=n/10;
               }
 }
 return false;
                              
             

      }
0
 
gudii9Author Commented:
public boolean hasOne(int n) {
 while (n > 0) { 
		if (n % 10 == 1){
		  return true;
      n=n/10;
		}
 } 
 return false;
					 
		 

	}

Open in new window


above give error saying

Compile problems:


Error:      n=n/10;
      ^^^^^^
Unreachable code
0
 
rrzCommented:
i meant to say if(condition) statement without  begin { and end } will implicitly cover only next line as its statement right
Yes.
Unreachable code
You just have to make the compiler happy.
Why not? do it like you did at
https://www.experts-exchange.com/questions/28966679/hasOne-challenge.html#a41778800
0
All Courses

From novice to tech pro — start learning today.