I'm writing a program where I'm supposed to make a method that calculates if the passed number is odd. For this method, I also need to check that passed number is > 0, and if not, return false.
I am also supposed to make a second method with two parameters (start and end, which represents a range of numbers) and the method is supposed to use a for loop to sum all odd numbers within that range. The parameter end needs to be greater than or equal to start and both start and end parameters have to be greater than 0.
If those conditions are not satisfied return -1 from the method to indicate invalid input.
This is the assignment:
Write a method called isOdd with an int parameter and call it number. The method needs to return a boolean.
Check that number is > 0, if it is not return false.
If number is odd return true, otherwise return false.
Write a second method called sumOdd that has 2 int parameters start and end, which represent a range of numbers.
The method should use a for loop to sum all odd numbers in that range including the end and return the sum.
It should call the method isOdd to check if each number is odd.
The parameter end needs to be greater than or equal to start and both start and end parameters have to be greater than 0.
If those conditions are not satisfied return -1 from the method to indicate invalid input.
I've tried for over an hour now but I'm not doing it correctly because my output is wrong. I've written down the expected results and my results below my code.
This is my code:
public static boolean isOdd(int number){
boolean status = false;
if(number < 0){
status = false;
} else if(number % 2 != 0){
status = true;
}
return status;
}
public static int sumOdd(int start, int end){
int sum = 0;
if((end < start) || (start < 0) || (end < 0)){
return -1;
}
for(int i = 0; i <= end; i++){
if((isOdd(i))){
sum += i;
}
}
return sum;
}
The expected result is:
System.out.println(sumOdd(1, 100));// → should return 2500
System.out.println(sumOdd(-1, 100)); // → should return -1
System.out.println(sumOdd(100, 100));// → should return 0
System.out.println(sumOdd(13, 13));// → should return 13 (This set contains one number, 13, and it is odd)
System.out.println(sumOdd(100, -100));// → should return -1
System.out.println(sumOdd(100, 1000));// → should return 247500
My result:
2500
-1
2500
49
-1
250000
First, your isOdd method only needs to return true if two conditions are met: the number must be greater than zero and it must be odd. That can be done with a single return and a boolean and. Like,
public static boolean isOdd(int number) {
return number > 0 && number % 2 != 0;
}
Second, your loop should start at start (not zero). But, I would then test if start is even. If it is, increment it before the loop. Then we know we have an initial value that is odd so we no longer need to test for oddness in the loop (we can increment by two instead). Like,
public static int sumOdd(int start, int end) {
if (end < start || start < 0 || end < 0) {
return -1;
}
int sum = 0;
if (!isOdd(start)) {
start++;
}
for (int i = start; i <= end; i += 2) {
sum += i;
}
return sum;
}
Which should be quite a bit more efficient.
Don't declare variables at the begging of your method, only create them when they are needed. As pointed out by Jordan the problem is with for loop index, it should start from start, not 0:
public static boolean isOdd(int number) {
if (number < 0) {
return false;
}
return number % 2 != 0;
}
public static int sumOdd(int start, int end) {
if ((end < start) || (start < 0) || (end < 0)) {
return -1;
}
int sum = 0;
for (int i = start; i < end; i++) {
if (isOdd(i)) {
sum += i;
}
}
return sum;
}
Related
public class NumberPalindrome {
public static boolean isPalindrome(int number) {
int reverse = 0;
if (number<0){
number=number* -1;
}
while (number > 0) {
int lastDig = number % 10;
reverse = lastDig + reverse;
if (number<10) {break;}
reverse = reverse * 10 ;
number/=10;
}
if (number==reverse) {
return true;
}
return false;
}
}
why does my code not return true when I enter a palindrome number? I tried using it to print out the reverse value and it does it quite well, but just does not seem to get the boolean value straight though.
The problem was modifying the number variable, but then comparing it with the new generated reverse variable as if it was never edited.
Also, you were adding the last digit to the reverse variable before multiplying it by ten.
See the following code in Java:
public static boolean isPalindrome(int number) {
int reverse = 0;
if(number < 0) {
number *= -1;
}
int initialNumber = number;
while(number > 0) {
int lastDigit = number % 10;
reverse = (reverse * 10) + lastDigit;
if(number < 10) {
break;
}
number /= 10;
}
return initialNumber == reverse;
}
There are a few problems here. You need to save the original number for comparison with the the reversed number. The break statement confuses the logic.
To figure this out, I added some print statements to trace the progress. Adding print statements isn't elegant, but it is very useful.
Here is my version, with comments indicating what I changed.
public static boolean isPalindrome (int original)
{
// Need to save the original number for comparison
int number = original;
int reverse = 0;
if (number < 0)
{
number = number * -1;
}
while (number > 0)
{
int lastDig = number % 10;
// Update and shift reverse in one step
reverse = lastDig + reverse * 10;
number /= 10;
// Don't need extra break to terminate the loop
System.out.printf ("Check %d ; Reverse %d%n", number, reverse);
}
System.out.printf ("Final %d ; Reverse %d%n", number, reverse);
// Compare to original and return boolean value directly
return (original == reverse);
}
I had a test exam in java, that almost no one have succeeded in this question and I can't figure out the solution.
The question was like this:
Find the sum of an integer last and first number. For example 1234-->5, 137-->8, 4-->8. You are only allowed to use recursion and no helper function"
I tried various things. Here is my last attempt:
public static int sumOfFirstandLastdigits(int number)
{
int lastdigit=sumOfFirstandLastdigits(number/10);
if(number/10==0)
{
return number%10;
}
return lastdigit+sumOfFirstandLastdigits(number%10);
}
Assuming the input is supposed to be non-negative:
//If n < 0, return first digit of -n
//Otherwise, return sum of first and last digits of n
int sumLastAndFirstDigit(int n) {
if (n < -9)
return sumLastAndFirstDigit(-(-n/10));
if (n <= 0)
return -n;
if (n < 10)
return n+n;
return n%10 + sumLastAndFirstDigit(-(n/10));
}
You can do this by overloading the method and passing the last digit as a second parameter to keep track of it through the recursion without changing the value (AKA Default Parameter):
public static void main(String[] args) {
System.out.println(sumDigits(3891901));
System.out.println(sumDigits(1234));
System.out.println(sumDigits(5678));
}
private static int sumDigits(int i) {
return sumDigits(i, i % 10);
}
private static int sumDigits(int i, int j) {
if (i / 10 == 0) {
return i % 10 + j;
}
return sumDigits(i / 10, j);
}
Output:
4
5
13
This thread on default parameters might help learn more as well.
Found a solution using String, not sure it's the best :
public int sumLastAndFirstDigit(Integer firstDigit, int number) {
String numberAsString = String.valueOf(number);
//Set the first digit
if(firstDigit == null) {
firstDigit = Integer.valueOf(numberAsString.substring(0,1));
//If there is only one digit in number for the first loop, then return 2 x firstDigit
if(numberAsString.length() == 1) {
return 2 * firstDigit;
}
}
//Remove the first digit to create the new number
String newNumberAsString = numberAsString.substring(1);
Integer newNumber = Integer.valueOf(newNumberAsString);
if(newNumberAsString.length() == 1) {
//When it's the last digit, sum first and last
return firstDigit + newNumber;
}
return sumLastAndFirstDigit(firstDigit, newNumber);
}
Then do :
sumLastAndFirstDigit(null,1234);
sumLastAndFirstDigit(null,137);
sumLastAndFirstDigit(null,4);
Use the sign as a flag to recognize the initial call. Only works with positive numbers, of course.
public static int sum(int value){
if(value > 0)
// initial call
return value % 10 + sum(-value);
else
// recursive call
return -value < 10 ? -value : sum(value / 10);
}
This are the 2 different solutions my professor suggested, although he said no helper (the first one is without an helper).
public static int sumFirstAndLast2(int num) {
if (num < 10 )
return num+num;
return sumFirstAndLast2(num/10) - num%100/10 + num%10;
}
public static int sumFirstAndLast(int num) {
if ( num < 10 )
return num+num;
return sumFirstAndLastHelper(num,true);
}
private static int sumFirstAndLastHelper(int num, boolean isLast) {
if ( isLast )
return num%10 + sumFirstAndLastHelper(num/10,false);
if ( num < 10 )
return num;
return sumFirstAndLastHelper(num/10,false);
}
So the exercise is:
Using recursion only (no loops)
Find if there is sub ground of numbers that are equal to the given number in an array and follow the rule.
Let's say I have this array, I give the function a number for sum and it must adhere to this rule:
you cannot repeat the same number, and you can't sum 3 numbers in a row (can't do i+1 and i+2)
int[] a = {5,4,2,1,3};
So in this case:
num 8 = true (4+3+1) ( 5+3)
num 11 = false (4+5+2 are 3 but are three in a row) (5+2+1+3 also three in a row)
My attempt is:
public static boolean sumRule(int[] a , int num){
if (num == 0){
return true;
} else {
return sumRule(a,num,0,a.length);
}
}
private static boolean sumRule(int[] a, int num, int low,int high){
if(low >= high || low < 0){
return false;
}
if (a[low] == -1){
return false;
}
if(a[low] == num || num-a[low] == 0 ){
return true;
}
int temp = a[low];
a[low] = -1;
return sumRule(a,num,low,high) || sumRule(a,num-temp,low+3,high) || sumRule(a,num-temp,low+1,high) ;
}
But when I send 11 to this, it still returns true, anyone has an idea what am i missing here?
Thanks,
I have the full code answer below, and here's the explanation:
Essentially you need to break this problem down to a recurrence. What that means is, you look at the choice at each step (i.e. whether to use a number or not in the sum) and recursively calculate both options.
The base case:
If num == 0 then we know it's true. But if num != 0 and the array has length 0, then we know it's false
Recursive case:
We check if the first number in the array is less than or equal to num. If not, then we can't use it. So we do a recursive call with all the same parameters except the array is now the original array minus the first number
If we CAN use the number (i.e. a[0] <= num) then the true answer might use this or it may not use it. We make a recursive call for each case, and return true if either of the recursive calls return true.
The consecutive number rule:
This is easy to enforce. We add a parameter called 'left' which tells us the number of elements we can consecutively take from the beginning of the array. To start with, left is 2 because at most we can take 2 consecutive numbers. Then in the cases where we DO use the first number in the array in our sum, we decrement left. If we don't use the first number in the array, we reset left to 2. In the cases where left becomes 0, we have no choice but to skip the current number at the top of the array.
class Main {
public static void main(String[] args) {
int[] a = new int[] {5,4,2,1,3};
System.out.println(sumRule(a, 8));
System.out.println(sumRule(a, 11));
}
public static boolean sumRule(int[] a , int num){
if (num == 0){
return true;
} else {
return sumRule(a,num,2);
}
}
private static boolean sumRule(int[] a, int num, int left){
if (num == 0) {
return true;
}
if (a.length == 0) {
return false;
}
int[] a_new = new int[a.length-1];
for (int i = 1; i < a.length; i++) a_new[i-1] = a[i];
if (left == 0) {
return sumRule(a_new, num, 2);
}
boolean using_a0 = false;
if (a[0] <= num) {
using_a0 = sumRule(a_new, num-a[0], left-1);
}
boolean not_using_a0 = sumRule(a_new, num, 2);
return (not_using_a0 || using_a0);
}
}
Edit - A variation on the code above without copying the array:
class Main {
public static void main(String[] args) {
int[] a = new int[] {5,4,2,1,3};
System.out.println(sumRule(a, 8));
System.out.println(sumRule(a, 11));
}
public static boolean sumRule(int[] a , int num){
if (num == 0){
return true;
} else {
return sumRuleNoLoop(a,num,2,0);
}
}
private static boolean sumRuleNoLoop(int[] a, int num, int left, int startIdx){
if (num == 0) {
return true;
}
if (startIdx >= a.length) {
return false;
}
if (left == 0) {
return sumRuleNoLoop(a, num, 2, startIdx+1);
}
boolean using_a0 = false;
if (a[startIdx] <= num) {
using_a0 = sumRuleNoLoop(a, num-a[startIdx], left-1, startIdx+1);
}
boolean not_using_a0 = sumRuleNoLoop(a, num, 2, startIdx+1);
return (not_using_a0 || using_a0);
}
}
First thing you can add is a check to see not 3 numbers in a row being added. Also replacing a number in the array with -1 would have unintended side effects within recursive calls. Below is something I have. You can ignore the index param I have used to see the values used.
Explanation:
The recursive sumRule method divides the problem into two parts:
First part takes the value of current index and adds with the sum of values starting from next index.
Second part assumes, current value can’t be taken for the sum. It only checks if there is a sum within the subset starting from next value of the array.
In the method, lastIndex is keeping track of the index of last value picked up for the sum. So, in the first call the value is 0, 1 in second and so on.
(start - lastIndex <= 1 ? consecutive + 1 : 1) is to check whether value of consecutive should be increased or not. consecutive = 1 means, current value is added to the sum.
public static boolean sumRule(int[] a, int num) {
if (num == 0) {
return true;
} else {
return sumRule(a, num, 0, 0, 0, 0, "");
}
}
public static boolean sumRule(final int[] a, int num, int sum, int start, int consecutive, int lastIndex,
String index) {
if (consecutive == 3) {
return false;
}
if (sum == num) {
System.out.println(index);
return true;
}
if (start >= a.length) {
return false;
}
return sumRule(a, num, sum + a[start], start + 1, (start - lastIndex <= 1 ? consecutive + 1 : 1), start,
index + ", " + start) || sumRule(a, num, sum, start + 1, consecutive, lastIndex, index);
}
Here is my implementation. It contains comments explaining what the different parts do.
public class RecurSum {
/**
* Determines whether 'sum' equals 'target'.
*
* #param arr - its elements are summed
* #param sum - sum of some elements in 'arr'
* #param target - required value of 'sum'
* #param index - index in 'arr'
* #param consecutive - number of consecutive indexes summed to ensure don't exceed 3
* #param start - starting element in 'arr' which is used for back-tracking
*
* #return "true" if 'sum' equals 'target'
*/
private static boolean sumRule(int[] arr, int sum, int target, int index, int consecutive, int start) {
if (sum == target) {
return true;
}
else {
if (index >= arr.length) {
// if we have reached last element in 'arr' then back-track and start again
if (start < arr.length) {
return sumRule(arr, 0, target, start + 1, 0, start + 1);
}
// we have reached last element in 'arr' and cannot back-track
return false;
}
else {
consecutive++;
if (consecutive == 3) {
// skip 3rd consecutive element (because of the rule)
consecutive = 0;
return sumRule(arr, sum, target, index + 2, consecutive, start);
}
else {
if (sum + arr[index] > target) {
// recursive call but don't add current element of 'arr'
return sumRule(arr, sum, target, index + 1, 0, start);
}
// recursive call: add current element of 'arr' to 'sum' and proceed to next element
return sumRule(arr, sum + arr[index], target, index + 1, consecutive, start);
}
}
}
}
public static void main(String[] args) {
int[] arr = new int[]{5, 4, 2, 1, 3};
// initial call to recursive method with target = 11 (eleven)
System.out.println(sumRule(arr, 0, 11, 0, 0, 0));
// initial call to recursive method with target = 8
System.out.println(sumRule(arr, 0, 8, 0, 0, 0));
}
}
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;
}
I am practicing past exam papers for a basic java exam, and I am finding it difficult to make a for loop work for testing whether a number is prime. I don't want to complicate it by adding efficiency measures for larger numbers, just something that would at least work for 2 digit numbers.
At the moment it always returns false even if n IS a prime number.
I think my problem is that I am getting something wrong with the for loop itself and where to put the "return true;" and "return false;"... I'm sure it's a really basic mistake I'm making...
public boolean isPrime(int n) {
int i;
for (i = 2; i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
The reason I couldn't find help elsewhere on stackoverflow is because similar questions were asking for a more complicated implementation to have a more efficient way of doing it.
Your for loop has a little problem. It should be: -
for (i = 2; i < n; i++) // replace `i <= n` with `i < n`
Of course you don't want to check the remainder when n is divided by n. It will always give you 1.
In fact, you can even reduce the number of iterations by changing the condition to: - i <= n / 2. Since n can't be divided by a number greater than n / 2, except when we consider n, which we don't have to consider at all.
So, you can change your for loop to: -
for (i = 2; i <= n / 2; i++)
You can stop much earlier and skip through the loop faster with:
public boolean isPrime(long n) {
// fast even test.
if(n > 2 && (n & 1) == 0)
return false;
// only odd factors need to be tested up to n^0.5
for(int i = 3; i * i <= n; i += 2)
if (n % i == 0)
return false;
return true;
}
Error is i<=n
for (i = 2; i<n; i++){
You should write i < n, because the last iteration step will give you true.
public class PrimeNumberCheck {
private static int maxNumberToCheck = 100;
public PrimeNumberCheck() {
}
public static void main(String[] args) {
PrimeNumberCheck primeNumberCheck = new PrimeNumberCheck();
for(int ii=0;ii < maxNumberToCheck; ii++) {
boolean isPrimeNumber = primeNumberCheck.isPrime(ii);
System.out.println(ii + " is " + (isPrimeNumber == true ? "prime." : "not prime."));
}
}
private boolean isPrime(int numberToCheck) {
boolean isPrime = true;
if(numberToCheck < 2) {
isPrime = false;
}
for(int ii=2;ii<numberToCheck;ii++) {
if(numberToCheck%ii == 0) {
isPrime = false;
break;
}
}
return isPrime;
}
}
With this code number divisible by 3 will be skipped the for loop code initialization.
For loop iteration will also skip multiples of 3.
private static boolean isPrime(int n) {
if ((n > 2 && (n & 1) == 0) // check is it even
|| n <= 1 //check for -ve
|| (n > 3 && (n % 3 == 0))) { //check for 3 divisiable
return false;
}
int maxLookup = (int) Math.sqrt(n);
for (int i = 3; (i+2) <= maxLookup; i = i + 6) {
if (n % (i+2) == 0 || n % (i+4) == 0) {
return false;
}
}
return true;
}
You could also use some simple Math property for this in your for loop.
A number 'n' will be a prime number if and only if it is divisible by itself or 1.
If a number is not a prime number it will have two factors:
n = a * b
you can use the for loop to check till sqrt of the number 'n' instead of going all the way to 'n'. As in if 'a' and 'b' both are greater than the sqrt of the number 'n', a*b would be greater than 'n'. So at least one of the factors must be less than or equal to the square root.
so your loop would be something like below:
for(int i=2; i<=Math.sqrt(n); i++)
By doing this you would drastically reduce the run time complexity of the code.
I think it would come down to O(n/2).
One of the fastest way is looping only till the square root of n.
private static boolean isPrime(int n){
int square = (int)Math.ceil((Math.sqrt(n)));//find the square root
HashSet<Integer> nos = new HashSet<>();
for(int i=1;i<=square;i++){
if(n%i==0){
if(n/i==i){
nos.add(i);
}else{
nos.add(i);
int rem = n/i;
nos.add(rem);
}
}
}
return nos.size()==2;//if contains 1 and n then prime
}
You are checking i<=n.So when i==n, you will get 0 only and it will return false always.Try i<=(n/2).No need to check until i<n.
The mentioned above algorithm treats 1 as prime though it is not.
Hence here is the solution.
static boolean isPrime(int n) {
int perfect_modulo = 0;
boolean prime = false;
for ( int i = 1; i <= n; i++ ) {
if ( n % i == 0 ) {
perfect_modulo += 1;
}
}
if ( perfect_modulo == 2 ) {
prime = true;
}
return prime;
}
Doing it the Java 8 way is nicer and cleaner
private static boolean isPrimeA(final int number) {
return IntStream
.rangeClosed(2, number/2)
.noneMatch(i -> number%i == 0);
}