How can I make the following allow negative numbers and treats them as positives. Ex. -91 = 10
It currently works for taking int n and adding all digits, but just for positives. Thanks!
public static int sumOfDigits(int n) {
int sum = 0;
while (n > 0) {
sum += n % 10;
n = n / 10;
}
return sum;
}
Simple solution: add n = Math.abs(n) as the first line of the function. This solution works for all numbers, except Integer.MIN_VALUE.
Always correct solution: replace loop condition by n != 0 and return Math.abs(sum) as the result.
public static int sumOfDigits(int n) {
if (n == 0) return 0;
else return (n % 10) + sumOfDigits(n / 10);
}
Related
Trying to create a method to return the first number below "n" which can be entirely divided by both the first and second divisor. Currently my program is returning the default value of "answer" being 0, I want the value which is calculated within the loop to be translated outside the loop to be returned. Yes I am a beginner :(
static int highestNumberBelowNDivisibleByTwoNumbers(int firstDivisor, int secondDivisor, int n) {
int multipliedDivisors = firstDivisor * secondDivisor;
int answer = 0;
int remainder = 0;
for (int i = n; i <= 1; i--) {
remainder = multipliedDivisors / i;
if (remainder == 0){
answer = i;
break;
}
}
return answer;
}
Based on your description of:
Trying to create a method to return the first number below "n" which
can be entirely divided by both the first and second divisor.
Try something more like below with the % operator (remainder/modulo):
static int highestNumberBelowNDivisibleByTwoNumbers(int firstDivisor, int secondDivisor, int n) {
while (n>0) {
if ((n % firstDivisor == 0) && (n % secondDivisor == 0)) {
return n;
}
n--;
}
return -1; // no answer found
}
Your code
for (int i = n; i <= 1; i--) {
remainder = multipliedDivisors / i;
if (remainder == 0){
answer = i;
break;
}
Decreases the counter from n down to 1. HOWEVER, your answer is not updated UNLESS remainder equals to zero. If that condition is never met, the default value of n will be returned (which is zero).
The problem? remainder = multipliedDivisors / i when will remainder be zero?
Because of this assignment, int multipliedDivisors = firstDivisor * secondDivisor;, only if one of the "divisor" variables is zero.
Redo your logic.
I finished a Kata on Codewars, which is the multiplicative persistence method. For those who aren't aware of the challenge, it goes as follows:
The function takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit. For example:
persistence(39) === 3 // because 3*9 = 27, 2*7 = 14, 1*4=4
// and 4 has only one digit
persistence(999) === 4 // because 9*9*9 = 729, 7*2*9 = 126,
// 1*2*6 = 12, and finally 1*2 = 2
persistence(4) === 0 // because 4 is already a one-digit number
My solution, which works, uses two while loops (below). I am now attempting to write the method using recursion. However, I see that I may run into threading issues (since I need to return the number of times I am multiplying the digits). Is it possible to use recursion? If so, how?
This is my code using iteration:
public static int persistence(long n) {
int count = 0;
if(n < 10) return count;
long num = 1;
while(n >= 10) {
while(n != 0) {
num*=(n % 10);
n/=10;
}
n = num;
num = 1;
count++;
}
return count;
}
As of now, I only know that:
The base case would be
if(n < 10) return 0;
This is if n is a single digit.
The recursive case is what I am stuck in. Thanks!
You can easily eliminate the outer loop with recursion:
public static int persistence(long n) {
if(n < 10) return 0;
long num = 1;
while(n != 0) {
num*=(n % 10);
n/=10;
}
if (num > 10) {
return 1 + persistence (num);
} else {
return 1;
}
}
Or even simpler:
public static int persistence(long n) {
if(n < 10) return 0;
long num = 1;
while(n != 0) {
num*=(n % 10);
n/=10;
}
return 1 + persistence (num);
}
Given a range of [1, 1000000000] we need to find prime numbers and all the digits of the prime number must be odd. (Example: 23 is not okay, 31 is okay)
If we go on by looping through each number and checking if it is prime etc, it is very slow. Is there a way to make this close to O(N) ?
I tried to eliminate as much as possible by looking at digits first. But after eliminating numbers with even digits the prime test is too slow.
for all numbers in [1, N]
check all digits, if any even digit, continue
check primality (this step is very slow)
And the primality test should not be very complex (probabilistic etc. is not possible, it must be possible to implement in a few minutes). The one I use is:
private static boolean isPrime(int n) {
boolean isPrime = true;
for (int divisor = 2; divisor <= n / 2; divisor++) {
if (n % divisor == 0) {
isPrime = false;
break;
}
}
return isPrime;
}
Maybe there is a trick to ensure a quick primality test but I couldn't find. Any suggestions? Thanks for reading.
You don't need to check all milliard numbers. Generate all numbers with only odd digits - there are at most 5^9~2 millions of them. Exclude those ending with 5 and not generate numbers divisible by 3 (in the moment of the last digit generation)
Then check these numbers for primality. Note that loop limit might be sqrt(n)
Ideone
class Ideone
{
static int oddcnt;
public static void checkprime(int x) {
for (int i=3; i <= Math.sqrt(x); i +=2)
if ((x % i) == 0)
return;
oddcnt++;
}
public static void genodd(int x, int curlen, int maxlen) {
x *= 10;
for (int i=1; i<10; i+=2) {
int nx = x + i;
checkprime(nx);
if (curlen < maxlen)
genodd(nx, curlen + 1, maxlen);
}
}
public static void main (String[] args) throws java.lang.Exception
{
genodd(0, 1, 8);
System.out.println(oddcnt);
}
}
The best way I can think of is to run a Prime Sieve of Eratosthenes to find all the primes in the range (0; sqrt(1000000000)) - which is around (0, 31622) - and time complexity O(n*log(log(n))) where n=31622. We will need those prime for a faster primality test.
Then, just loop through each number with odd digits - there are 5^10 = 9765625 ~ 10000000 such numbers. You saved 1000 times compared to iterating through all number in the original range.
The primality test using the primes we found in step 1 can be fast, as you only need to check with primes < sqrt(n), and you already have the primes. Even for the largest number in the range which is 999999999, the number of candidate primes is just 3432.
The following is a Java implementation
public class Execute {
private ArrayList<Long> primes = new ArrayList<>();
#org.junit.Test
public void findOddDecimalPrimes() {
primeSieve(32000);
System.out.println(primes.size());
for (int i = 0; i < 9765625; i++) {
String inBase5 = convertFromBaseToBase(i);
long evenDec = convertToOddDecimal(inBase5);
if (isPrime(evenDec)) {
System.out.println(evenDec);
}
}
}
private String convertFromBaseToBase(long i) {
return Long.toString(i, 5);
}
private long convertToOddDecimal(String str) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
s.append(1 + 2 * Integer.parseInt("" + str.charAt(i)));
}
return Long.parseLong(s.toString());
}
private boolean isPrime(long n) {
for (int i = 0; i < primes.size(); i++) {
if (primes.get(i) * primes.get(i) > n) break;
long divisor = n / primes.get(i);
if (divisor * primes.get(i) == n) return false;
}
return true;
}
/**
* References: www.geeksforgeeks.org
*/
private void primeSieve(int n)
{
// Create a boolean array "prime[0..n]" and initialize
// all entries it as true. A value in prime[i] will
// finally be false if i is Not a prime, else true.
boolean prime[] = new boolean[n+1];
for(int i=0;i<n;i++)
prime[i] = true;
for(int p = 2; p*p <=n; p++)
{
// If prime[p] is not changed, then it is a prime
if(prime[p] == true)
{
// Update all multiples of p
for(int i = p*p; i <= n; i += p)
prime[i] = false;
}
}
for (int i = 2; i < prime.length; i++) {
if (prime[i]) this.primes.add(Long.valueOf(i));
}
}
}
If your numbers are in order, you can optimize your isPrime function.
Here is a js sample version.
var primes = [];
function checkDigits(n) {
while(n > 1) {
var d = n % 10;
if ( d % 2 == 0) { return false; }
n = parseInt(n/10,10);
}
return true;
}
function isPrime(n) {
for(var i = 1; i < primes.length; i++) {
if(n % primes[i] == 0) {
return false;
}
}
var lastPrime = primes.length > 2 ? primes[primes.length - 1] : 1;
var inc = 2;
for(var i = lastPrime + inc; i < Math.sqrt(n); i += inc) {
if(n % i == 0) {
return false;
}
}
primes.push(n);
return true;
}
for(var i = 1; i < 100; i++) {
if(checkDigits(i) && isPrime(i)) {
console.log(i);
}
}
This is an open question in math and computer science in general.
In a nutshell no, there is no know way to solve that problem in O(1) to get your loop running in O(N) over the whole range.
If you solve that, dont tell anyone, and go get rich by breaking most of the encryptions today that use large prime numbers.
What you could do though, is make the loop over the devisor a bit smaller by useing sqrt(n).
That will bring that inner loop down from O(N^2) to O(sqrt(N))
And the whole complexity from O(N^2) to O(N*sqrt(N))=O(N^(3/2))
Anotger optimization would be to check the odd digits first beforre doing the complex Prime calculation
Here is the problem that I am solving.
Write a method evenDigits that accepts an integer parameter n and that
returns the integer formed by removing the odd digits from n. The
following table shows several calls and their expected return values:
Call Valued Returned
evenDigits(8342116); 8426
evenDigits(4109); 40
evenDigits(8); 8
evenDigits(-34512); -42
evenDigits(-163505); -60
evenDigits(3052); 2
evenDigits(7010496); 46
evenDigits(35179); 0
evenDigits(5307); 0
evenDigits(7); 0
If a negative number with even digits other than 0 is passed to the method, the result should also be negative, as shown above when -34512 is passed.
Leading zeros in the result should be ignored and if there are no even digits other than 0 in the number, the method should return 0, as shown in the last three outputs.
I have this so far -
public static int evenDigits(int n) {
if (n != 0) {
int new_x = 0;
int temp = 0;
String subS = "";
String x_str = Integer.toString(n);
if (x_str.substring(0, 1).equals("-")) {
temp = Integer.parseInt(x_str.substring(0, 2));
subS = x_str.substring(2);
} else {
temp = Integer.parseInt(x_str.substring(0, 1));
subS = x_str.substring(1);
}
if (subS.length() != 0) {
new_x = Integer.parseInt(x_str.substring(1));
}
if (temp % 2 == 0) {
return Integer.parseInt((Integer.toString(temp) + evenDigits(new_x)));
} else {
return evenDigits(new_x);
}
}
return 0;
}
Why do people seem always to want to convert to String to deal with digits? Java has perfectly good arithmetic primitives for handling the job. For example:
public static int evenDigits(int n) {
int rev = 0;
int digitCount = 0;
// handle negative arguments
if (n < 0) return -evenDigits(-n);
// Extract the even digits to variable rev
while (n != 0) {
if (n % 2 == 0) {
rev = rev * 10 + n % 10;
digitCount += 1;
}
n /= 10;
}
// The digits were extracted in reverse order; reverse them again
while (digitCount > 0) {
n = n * 10 + rev % 10;
rev /= 10;
digitCount -= 1;
}
// The result is in n
return n;
}
Although it makes no difference for a simple academic exercise such as this one, handling the job via arithmetic alone can be expected to perform better than anything involving converting to String.
It's often easier to start with a recursive solution and then work you way back to iterative (if you must):
public static int evenDigits(int n) {
if (n < 0) {
return -evenDigits(-n);
} else if (n == 0) {
return 0;
} else if (n % 2 == 1) {
return evenDigits(n / 10);
} else {
return 10 * evenDigits(n / 10) + (n % 10);
}
}
int n = 8342116;
StringBuilder sb = new StringBuilder();
Integer.toString(n).chars()
.filter(x -> x % 2 == 0)
.mapToObj(i -> (char) i)
.forEachOrdered(sb::append);
int result = Integer.valueOf(sb.toString());
System.out.println(result); // 8426
public int evenDigits(int n) {
int r = 0;
boolean neg = false;
String evenDigits = "";
if (n < 0) { neg = true; n = abs(n); }
// keep dividing n until n = 0
while (n > 0) {
r = n % 10;
n = n / 10; // int division
if (r % 2 == 0) { evenDigits = Integer.toString(r) + evenDigits; }
}
int result = Integer.parseInt(evenDigits);
if (neg) { result -= 2 * result; }
return result;
}
This is more or less a pseudo code, but I think you get my idea. I have used this method for the same problem before.
A layman's solution that's based on Strings:
public static int evenDigits(int n) {
StringBuilder evenDigitsBuffer = new StringBuilder();
for (char digitChar : String.valueOf(n).toCharArray()) {
int digit = Character.getNumericValue(digitChar);
if (digit % 2 == 0) {
evenDigitsBuffer.append(digit);
}
}
return evenDigitsBuffer.length() > 0
? Integer.signum(n) * Integer.parseInt(evenDigitsBuffer.toString())
: 0;
}
I am trying to sum every other digit in the card number by doing this:
/*
Return the sum of the odd-place digits.
*/
public static int sumOfoddPlace(long number)
{
int maxDigitLength = 16;
int sum = 0;
for (int i = 1; i <= maxDigitLength; i++)
{
if (i % 2 == 1)
{
sum = sum + (int)(number % 10);
}
break;
}
return sum;
}
All I get is 6. The sum I am looking for is supposed to be 37.
You're breaking out of the loop on the very first iteration only. So, you won't go past to another iteration.
However, removing the break too won't solve your problem. number % 10 will always give you the last digit of the number, and not every alternate number. You should follow this approach:
num % 10 - Will give you last digit.
Then update the num by trimming off the last 2 digits.
Repeat
Try this ... this should work for you
public static int sumOfoddPlace(long number)
{
int maxDigitLength = 16;
int sum = 0;
for (int i = 0; i < maxDigitLength; i++)
{
if (i % 2 != 0)
{
sum = (sum + (int)(number % 10));
number = number/10;
}else {
number = number/10;
}
}
return sum;
}
What I have done here is if i is odd, I take a mod of the number so I get the last digit of the number and then add it to sum and then I get rid of the last digit by dividing it with 10 and if the number is even I just get rid of the digit in the ith position.
Here I am collecting the digits in odd places in reverse order.
I haven't seen the minimum solution yet, so here goes:
public static int sumOddDigits(long input) {
int sum = 0;
for (long temp = input; temp > 0; temp /= 100) {
sum += temp % 10;
}
return sum;
}
You don't need to divide by 10 and check if it's an even number, you can just divide by 100 every time.
Demo: http://ideone.com/sDZfpU
Here is updated code in which i have removed logic of flag.This is shorter and easier to understand.
public static int sumOfOddDigits(long number){
int sum = 0;
String newString = new StringBuilder(String.valueOf(number)).reverse().toString();
number = Long.parseLong(newString);
while (number != 0){
sum = (int) (sum + number % 10);
number = number / 100;
}
return sum;
}