Link to home
Create AccountLog in
Avatar of gudii9
gudii9Flag for United States of America

asked on

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
SOLUTION
Avatar of CPColin
CPColin
Flag of United States of America image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Avatar of gudii9

ASKER

how to look 2nd 3rd 4th etc digits?
The challenge description gives you a hint.
Avatar of d-glitch
Print out values for n%10 and n/10 for several values of n.

How do the answers relate to n.
Is it cheating to use String method? I remember krakatoa showed you how to do it on other challenges in the past.
The challenge specifically said to use % and / .
What are  13345/10   and   12345%10  ?
Avatar of gudii9

ASKER

13345/10   is 1334
and   12345%10  is 5
Avatar of gudii9

ASKER

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
Avatar of gudii9

ASKER

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?
12345%10  is 5
12345/10   is 1234

The answer is there if you think about it.
Avatar of gudii9

ASKER

i have to loop through each digit and check if it is one or not by doing both % and / ?
What does the Challenge say about using the / operator?
Avatar of gudii9

ASKER

/ to discard the rightmost digit.
Avatar of gudii9

ASKER

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?
After the discard, there is a new rightmost digit to check.
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.
The if statement is not the only looping control flow statement.  
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/while.html
ASKER CERTIFIED SOLUTION
Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
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.
Avatar of gudii9

ASKER

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
Avatar of gudii9

ASKER

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
Avatar of gudii9

ASKER

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
Avatar of gudii9

ASKER

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
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.
Yeah, try passing your code 10000 and see if that works. (The values Codingbat selected aren't very good!)
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.
Avatar of gudii9

ASKER

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
You need to work on your pseudo code not your code.
You need a control loop to solve this problem.
Avatar of gudii9

ASKER

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?
Avatar of gudii9

ASKER

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
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.
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.
Avatar of gudii9

ASKER

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
Avatar of gudii9

ASKER

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
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.
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?
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.
Avatar of gudii9

ASKER

"increment expression" is n = n / 10.
i thought increment expression means i++/i--only
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.)
Avatar of gudii9

ASKER

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
Avatar of gudii9

ASKER

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      
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.
Avatar of gudii9

ASKER

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
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.
An interesting fact is the equivalency of
while(true){} loop and   for(;;){} loop .
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.
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.
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
After you  get the for-loop solution posted, we can post the String methods solution and the recursive solution.
Avatar of gudii9

ASKER

ok
Avatar of gudii9

ASKER

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?
Nope, looks good.  Time to move on.
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

Avatar of gudii9

ASKER

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
SOLUTION
Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
Avatar of gudii9

ASKER

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;
                              
             

      }
Avatar of gudii9

ASKER

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
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?anchorAnswerId=41778800#a41778800