Iterate through each digit in a number - java

I am trying to create a program that will tell if a number given to it is a "Happy Number" or not. Finding a happy number requires each digit in the number to be squared, and the result of each digit's square to be added together.
In Python, you could use something like this:
SQUARE[d] for d in str(n)
But I can't find how to iterate through each digit in a number in Java. As you can tell, I am new to it, and can't find an answer in the Java docs.

You can use a modulo 10 operation to get the rightmost number and then divide the number by 10 to get the next number.
long addSquaresOfDigits(int number) {
long result = 0;
int tmp = 0;
while(number > 0) {
tmp = number % 10;
result += tmp * tmp;
number /= 10;
}
return result;
}
You could also put it in a string and turn that into a char array and iterate through it doing something like Math.pow(charArray[i] - '0', 2.0);

Assuming the number is an integer to begin with:
int num = 56;
String strNum = "" + num;
int strLength = strNum.length();
int sum = 0;
for (int i = 0; i < strLength; ++i) {
int digit = Integer.parseInt(strNum.charAt(i));
sum += (digit * digit);
}

I wondered which method would be quickest to split up a positive number into its digits in Java, String vs modulo
public static ArrayList<Integer> splitViaString(long number) {
ArrayList<Integer> result = new ArrayList<>();
String s = Long.toString(number);
for (int i = 0; i < s.length(); i++) {
result.add(s.charAt(i) - '0');
}
return result; // MSD at start of list
}
vs
public static ArrayList<Integer> splitViaModulo(long number) {
ArrayList<Integer> result = new ArrayList<>();
while (number > 0) {
int digit = (int) (number % 10);
result.add(digit);
number /= 10;
}
return result; // LSD at start of list
}
Testing each method by passing Long.MAX_VALUE 10,000,000 times, the string version took 2.090 seconds and the modulo version 2.334 seconds. (Oracle Java 8 on 64bit Ubuntu running in Eclipse Neon)
So not a lot in it really, but I was a bit surprised that String was faster

In the above example we can use:
int digit = Character.getNumericValue(strNum.charAt(i));
instead of
int digit = Integer.parseInt(strNum.charAt(i));

You can turn the integer into a string and iterate through each char in the string. As you do that turn that char into an integer

This code returns the first number (after 1) that fits your description.
public static void main(String[] args) {
int i=2;
// starting the search at 2, since 1 is also a happy number
while(true) {
int sum=0;
for(char ch:(i+"").toCharArray()) { // casting to string and looping through the characters.
int j=Character.getNumericValue(ch);
// getting the numeric value of the current char.
sum+=Math.pow(j, j);
// adding the current digit raised to the power of itself to the sum.
}
if(sum==i) {
// if the sum is equal to the initial number
// we have found a number that fits and exit.
System.out.println("found: "+i);
break;
}
// otherwise we keep on searching
i++;
}
}

Related

How to put numbers to array in while loop in java?

I am trying to add two binary numbers and then get their sum in binary system. I got their sum in decimal and now I am trying to turn it into binary. But there is problem that when I take their sum (in decimal) and divide by 2 and find remainders(in while loop), I need to put remainders into array in order print its reverse. However, there is an error in array part. Do you have any suggestions with my code? Thanks in advance.
Here is my code:
import java.util.Scanner;
public class ex1 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
int k = dec1(n)+dec2(m);
int i=0,c;
int[] arr= {};
while(k>0) {
c = k % 2;
k = k / 2;
arr[i++]=c; //The problem is here. It shows some //error
}
while (i >= 0) {
System.out.print(arr[i--]);
}
}
public static int dec1(int n) {
int a,i=0;
int dec1 = 0;
while(n>0) {
a=n%10;
n=n/10;
dec1= dec1 + (int) (a * Math.pow(2, i));
i++;
}
return dec1;
}
public static int dec2(int m) {
int b,j=0;
int dec2 = 0;
while(m>0) {
b=m%10;
m=m/10;
dec2= dec2 + (int) (b * Math.pow(2, j));
j++;
}
return dec2;
}
}
Here:
int[] arr= {};
creates an empty array. Arrays don't grow dynamically in Java. So any attempt to access any index of arr will result in an ArrayIndexOutOfBounds exception. Because empty arrays have no "index in bounds" at all.
So:
first ask the user for the count of numbers he wants to enter
then go like: int[] arr = new int[targetCountProvidedByUser];
The "more" real answer would be to use List<Integer> numbersFromUsers = new ArrayList<>(); as such Collection classes allow for dynamic adding/removing of elements. But for a Java newbie, you better learn how to deal with arrays first.
Why are you using two different methods to do the same conversion? All you need is one.
You could have done this in the main method.
int k = dec1(n)+dec1(m);
Instead of using Math.pow which returns a double and needs to be cast, another alternative is the following:
int dec = 0;
int mult = 1;
int bin = 10110110; // 128 + 48 + 6 = 182.
while (bin > 0) {
// get the right most bit
int bit = (bin % 10);
// validate
if (bit < 0 || bit > 1) {
throw new IllegalArgumentException("Not a binary number");
}
// Sum up each product, multiplied by a running power of 2.
// this is required since bits are taken from the right.
dec = dec + mult * bit;
bin /= 10;
mult *= 2; // next power of 2
}
System.out.println(dec); // prints 182
An alternative to that is to use a String to represent the binary number and take the bits from the left (high order position).
String bin1 = "10110110";
int dec1 = 0;
// Iterate over the characters, left to right (high to low)
for (char b : bin1.toCharArray()) {
// convert to a integer by subtracting off character '0'.
int bit = b - '0';
// validate
if (bit < 0 || bit > 1) {
throw new IllegalArgumentException("Not a binary number");
}
// going left to right, first multiply by 2 and then add the bit
// Each time thru, the sum will be multiplied by 2 which shifts everything left
// one bit.
dec1 = dec1 * 2 + bit;
}
System.out.println(dec1); // prints 182
One possible way to display the result in binary is to use a StringBuilder and simply insert the converted bits to characters.
public static String toBin(int dec) {
StringBuilder sb = new StringBuilder();
while (dec > 0) {
// by inserting at 0, the bits end up in
// correct order. Adding '0' to the low order
// bit of dec converts to a character.
sb.insert(0, (char) ((dec & 1) + '0'));
// shift right for next bit to convert.
dec >>= 1;
}
return sb.toString();
}

Printing number using recursion in java without its biggest digit

Using recursion I need to input a number and the console will print this number without its highest digit. If it's smaller than 10 it will return 0.
I already found the biggest digit but how can i remove it and print the number without it after?
This is the code for the biggest digit:
public static int remLastDigit(int n){
if(n==0)
return 0;
return Math.max(n%10, remLastDigit(n/10));
}
If i input 12345 i expect the output to be 1234. if i input 9 or less i expect the output to be 0.
Here is my solution:
// call this method
public static int removeLastDigit(int number) {
return removeLastDigitImpl(number, largestDigit(number));
}
private static int removeLastDigitImpl(int number, int largestDigit) {
if (number < 10) { // if the number is a single digit, decide what to do with it
if (number == largestDigit) {
return 0; // if it is the largest digit, remove it
} else {
return number; // if it is not, keep it
}
}
// handle the last digit of the number otherwise
if (number % 10 == largestDigit) {
// removing the digit
return removeLastDigitImpl(number / 10, largestDigit);
} else {
// not removing the digit
return removeLastDigitImpl(number / 10, largestDigit) * 10 + number % 10;
}
}
// this is the same as your attempt
private static int largestDigit(int n){
if(n==0)
return 0;
return Math.max(n%10, largestDigit(n/10));
}
Since you've already found the max digit nicely, here's how you can print the number without it.
public static void main(String[] args) {
printWithoutDigit(2349345, remLastDigit(2349345));
}
public static void printWithoutDigit(int number, int maxDigit) {
Integer.toString(number).chars().filter(digit -> Integer.valueOf(String.valueOf((char)digit))!=maxDigit).forEach(d -> System.out.print((char)d));
}
You could convert your number to a String, or more precisely to a char-array. Then, you can find out where in this array the biggest digit is, remove it and convert your char-array back to an integer.
This would roughly look like this:
int num = 12345; //the number from which you want to remove the biggest digit
char[] numC = String.valueOf(num).toCharArray();
int biggestDigit = 0;
int biggestDigitIndex = 0;
for (int i = 0; i < numC.length; i++) {
if (biggestDigit < Character.getNumericValue(numC[i])) {
biggestDigit = Character.getNumericValue(numC[i]);
biggestDigitIndex = i;
}
//Remove digit at index biggestDigitIndex from numC
//Convert numC back to int
}
Of course, you have to incorporate this into your recursion, which means returning the number you got after converting numC back to int and then feed this into your input parameter again. Also, of course you need to add a check if your number is < 9 in the beginning.

The sum of certain digits from an input number

I've been trying to sum a certain digit from a number, for example
Number: 5
Input: 54365
Output: The sum of 5's is 10
Second example:
Number: 5
Input: 5437555
Output: The sum of 5's is 20
I've managed to separate the digits yet I couldn't find the condition to sum
a certain number (for instance number 5 like the examples).
I'd appreciate to hear your idea of doing it
public static void main(String[] args) {
int sum = 0;
int number = MyConsole.readInt("Enter a number:");
while (number > 0) {
if (number % 10 == 8) {
sum += 8;
} else {
number /= 10;
}
}
System.out.println("The sum of 8's is:" + sum);
}
My way of separating the numbers.
Also i have a small program to get input instead of using scanner since we still haven't went through it in class.
Your requirement seems reasonably clear to me.
Given a number
final int number = 5;
And a starting number
final int input = 54365;
The easiest way is to convert that number to a String
final int inputStr = String.valueOf(input);
Then, you can filter each char for it, and sum them
final int sum =
inputStr.chars() // Get a Stream of ints, which represent the characters
.map(Character::getNumericValue) // Convert a char to its numeric representation
.filter(i -> i == number) // Filter for the designated number
.sum(); // Sum all the filtered integers
Output: 10
Using the same approach, but with an old-style for loop
final int input = 54365;
final int inputStr = String.valueOf(input);
final int number = 5;
int sum = 0;
for (final char c : inputStr.toCharArray()) {
final int n = Character.getNumericValue(c);
if (n == number) {
sum += number;
}
}
Your solution can work
int number = 5;
int input = 543655;
int sum = 0;
while (input > 0) {
if (input % 10 == number) {
sum += number;
}
input /= 10;
}

How can I get max number that consists of some digits of an integer number

I have a number. This number has many digits. I want to write a function which returns the largest number that consists of some digits of that number. While getting that largest number, the sequence of the digits should not change.
int myFunction(int n, int cat){
...
return max;
}
If n = 38462637 and cat = 3 the function has to return 86637, i.e. if cat = 3 the function is expected to return 5-digit number, as 8 - 3 = 5. The original number has many variations of 5 digits numbers, but the largest possible number is 86637. In this case, the most important requirement is that the digits should not change their place.
Be greedy - select the largest digit that can be leftmost in the answer(if there are several positions where this digit appears, choose its leftmost occurance). A digit may be leftmost if it is not 0 and we have at least n - cat - 1 digits to the right of it.
After that use the same algorithm to create the largest number on the right of the position of this digit that has exactly n - cat - 1 digits. Continue iterating until you have your number composed. Only note that the digits you select after the first iteration may be zero(as they will no longer be leftmost in the resulting number)
EDIT: best solution that uses the algorithm described above - use range minimum query to compute the highest value that is possible for each consecutive digit position. In theory this can be done in constant time per query and linear extra memory using linear precomputation, but the algorithm is so complex and hard to implement that it will only give you improvement for really big values of n. I personally suggest using a segment tree approach that will result in O(n*log(n)) time complexity.
This is probably a bit overcomplicated, but it seems to work:
public static int myFunction(int n, int cat) {
String numString = String.valueOf(n);
int finalLength = numString.length() - cat;
int[] positions = new int[finalLength];
StringBuilder answer = new StringBuilder();
for (int i = 0; i < finalLength; i++) {
for (int j = (i == 0 ? i : positions[i - 1] + 1); j <= numString.length() - finalLength + i; j++) {
if (positions[i] == 0 || numString.charAt(j) > numString.charAt(positions[i]) ) {
positions[i] = j;
}
}
answer.append(numString.charAt(positions[i]));
}
return Integer.parseInt(answer.toString());
}
[EDIT]: A cleaner version without all the String nonsense:
public static int myFunction(int n, int cat) {
List<Integer> digits = new ArrayList<Integer>();
int number = n;
while (number > 0) {
digits.add(number % 10);
number /= 10;
}
int finalLength = digits.size() - cat;
int lastIndex = digits.size();
int answer = 0;
for (int i = 0; i < finalLength; i++) {
int highestDigit = -1;
for (int j = lastIndex - 1; j >= finalLength - i - 1; j--) {
if (digits.get(j) > highestDigit) {
highestDigit = digits.get(j);
lastIndex = j;
}
}
answer = answer * 10 + highestDigit;
}
return answer;
}
If you have access to the code, store the number as a string with a seperator (space, comma, etc) in it, then use the string separator function to put each number (string character) into it's own array location. Parse the string array and make an integer array. Then run a quick sort on the array. When that is done, take the first X number of integers and that is your number.

Counting trailing zeros of numbers resulted from factorial

I'm trying to count trailing zeros of numbers that are resulted from factorials (meaning that the numbers get quite large). Following code takes a number, compute the factorial of the number, and count the trailing zeros. However, when the number is about as large as 25!, numZeros don't work.
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
double fact;
int answer;
try {
int number = Integer.parseInt(br.readLine());
fact = factorial(number);
answer = numZeros(fact);
}
catch (NumberFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static double factorial (int num) {
double total = 1;
for (int i = 1; i <= num; i++) {
total *= i;
}
return total;
}
public static int numZeros (double num) {
int count = 0;
int last = 0;
while (last == 0) {
last = (int) (num % 10);
num = num / 10;
count++;
}
return count-1;
}
I am not worrying about the efficiency of this code, and I know that there are multiple ways to make the efficiency of this code BETTER. What I'm trying to figure out is why the counting trailing zeros of numbers that are greater than 25! is not working.
Any ideas?
Your task is not to compute the factorial but the number of zeroes. A good solution uses the formula from http://en.wikipedia.org/wiki/Trailing_zeros (which you can try to prove)
def zeroes(n):
i = 1
result = 0
while n >= i:
i *= 5
result += n/i # (taking floor, just like Python or Java does)
return result
Hope you can translate this to Java. This simply computes [n / 5] + [n / 25] + [n / 125] + [n / 625] + ... and stops when the divisor gets larger than n.
DON'T use BigIntegers. This is a bozosort. Such solutions require seconds of time for large numbers.
You only really need to know how many 2s and 5s there are in the product. If you're counting trailing zeroes, then you're actually counting "How many times does ten divide this number?". if you represent n! as q*(2^a)*(5^b) where q is not divisible by 2 or 5. Then just taking the minimum of a and b in the second expression will give you how many times 10 divides the number. Actually doing the multiplication is overkill.
Edit: Counting the twos is also overkill, so you only really need the fives.
And for some python, I think this should work:
def countFives(n):
fives = 0
m = 5
while m <= n:
fives = fives + (n/m)
m = m*5
return fives
The double type has limited precision, so if the numbers you are working with get too big the double will be only an approximation. To work around this you can use something like BigInteger to make it work for arbitrarily large integers.
You can use a DecimalFormat to format big numbers. If you format your number this way you get the number in scientific notation then every number will be like 1.4567E7 this will make your work much easier. Because the number after the E - the number of characters behind the . are the number of trailing zeros I think.
I don't know if this is the exact pattern needed. You can see how to form the patterns here
DecimalFormat formater = new DecimalFormat("0.###E0");
My 2 cents: avoid to work with double since they are error-prone. A better datatype in this case is BigInteger, and here there is a small method that will help you:
public class CountTrailingZeroes {
public int countTrailingZeroes(double number) {
return countTrailingZeroes(String.format("%.0f", number));
}
public int countTrailingZeroes(String number) {
int c = 0;
int i = number.length() - 1;
while (number.charAt(i) == '0') {
i--;
c++;
}
return c;
}
#Test
public void $128() {
assertEquals(0, countTrailingZeroes("128"));
}
#Test
public void $120() {
assertEquals(1, countTrailingZeroes("120"));
}
#Test
public void $1200() {
assertEquals(2, countTrailingZeroes("1200"));
}
#Test
public void $12000() {
assertEquals(3, countTrailingZeroes("12000"));
}
#Test
public void $120000() {
assertEquals(4, countTrailingZeroes("120000"));
}
#Test
public void $102350000() {
assertEquals(4, countTrailingZeroes("102350000"));
}
#Test
public void $1023500000() {
assertEquals(5, countTrailingZeroes(1023500000.0));
}
}
This is how I made it, but with bigger > 25 factorial the long capacity is not enough and should be used the class Biginteger, with witch I am not familiar yet:)
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
System.out.print("Please enter a number : ");
long number = in.nextLong();
long numFactorial = 1;
for(long i = 1; i <= number; i++) {
numFactorial *= i;
}
long result = 0;
int divider = 5;
for( divider =5; (numFactorial % divider) == 0; divider*=5) {
result += 1;
}
System.out.println("Factorial of n is: " + numFactorial);
System.out.println("The number contains " + result + " zeroes at its end.");
in.close();
}
}
The best with logarithmic time complexity is the following:
public int trailingZeroes(int n) {
if (n < 0)
return -1;
int count = 0;
for (long i = 5; n / i >= 1; i *= 5) {
count += n / i;
}
return count;
}
shamelessly copied from http://www.programcreek.com/2014/04/leetcode-factorial-trailing-zeroes-java/
I had the same issue to solve in Javascript, and I solved it like:
var number = 1000010000;
var str = (number + '').split(''); //convert to string
var i = str.length - 1; // start from the right side of the array
var count = 0; //var where to leave result
for (;i>0 && str[i] === '0';i--){
count++;
}
console.log(count) // console shows 4
This solution gives you the number of trailing zeros.
var number = 1000010000;
var str = (number + '').split(''); //convert to string
var i = str.length - 1; // start from the right side of the array
var count = 0; //var where to leave result
for (;i>0 && str[i] === '0';i--){
count++;
}
console.log(count)
Java's doubles max out at a bit over 9 * 10 ^ 18 where as 25! is 1.5 * 10 ^ 25. If you want to be able to have factorials that high you might want to use BigInteger (similar to BigDecimal but doesn't do decimals).
I wrote this up real quick, I think it solves your problem accurately. I used the BigInteger class to avoid that cast from double to integer, which could be causing you problems. I tested it on several large numbers over 25, such as 101, which accurately returned 24 zeros.
The idea behind the method is that if you take 25! then the first calculation is 25 * 24 = 600, so you can knock two zeros off immediately and then do 6 * 23 = 138. So it calculates the factorial removing zeros as it goes.
public static int count(int number) {
final BigInteger zero = new BigInteger("0");
final BigInteger ten = new BigInteger("10");
int zeroCount = 0;
BigInteger mult = new BigInteger("1");
while (number > 0) {
mult = mult.multiply(new BigInteger(Integer.toString(number)));
while (mult.mod(ten).compareTo(zero) == 0){
mult = mult.divide(ten);
zeroCount += 1;
}
number -= 1;
}
return zeroCount;
}
Since you said you don't care about run time at all (not that my first was particularly efficient, just slightly more so) this one just does the factorial and then counts the zeros, so it's cenceptually simpler:
public static BigInteger factorial(int number) {
BigInteger ans = new BigInteger("1");
while (number > 0) {
ans = ans.multiply(new BigInteger(Integer.toString(number)));
number -= 1;
}
return ans;
}
public static int countZeros(int number) {
final BigInteger zero = new BigInteger("0");
final BigInteger ten = new BigInteger("10");
BigInteger fact = factorial(number);
int zeroCount = 0;
while (fact.mod(ten).compareTo(zero) == 0){
fact = fact.divide(ten);
zeroCount += 1;
}
}

Categories