SPOJ Factorial Problem - java

I am trying to develop code for SPOJ factorial problem number 11. The following is my code
import java.math.*;
import java.io.*;
public class Problem11 {
/**
* Count the number of zeroes at the end of
* the factorial value of a number.
*/
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int numOfInputs=0;
numOfInputs=Integer.parseInt(br.readLine());
BigInteger nextNum[]=new BigInteger[numOfInputs];
BigInteger factValue[]=new BigInteger[numOfInputs];
//Get all the numbers to be computed
for(int count=0;count<numOfInputs;count++)
{
nextNum[count]=new BigInteger(br.readLine());
}
//Obtain the factorial value for each number
for(int count=0;count<numOfInputs;count++)
{
factValue[count]=getFact(nextNum[count]);
}
//Obtain the number of trailing zeroes
for(int count=0;count<numOfInputs;count++)
{
//System.out.println(factValue[count]);
System.out.println(getZeroes(factValue[count]));
}
}
public static String getZeroes(BigInteger num)
{
int numOfZeroes=0;
while(num.remainder(BigInteger.TEN).equals(BigInteger.ZERO))
{
num=num.divide(BigInteger.TEN);
numOfZeroes++;
}
return String.valueOf(numOfZeroes);
}
public static BigInteger getFact(BigInteger num)
{
BigInteger factorial=BigInteger.ONE;
if(num.equals(0))
{
return (BigInteger.valueOf(1));
}
else
{
int count=1;
while((BigInteger.valueOf(count).compareTo(num))<=0)
{
factorial=factorial.multiply(BigInteger.valueOf(count));
count++;
}
}
return factorial;
}
}
The code works fine for numbers up to 5 digits with small delay and for the last number
8735373 it is taking too much time, if I submit my solution, the judge shows compilation error.. I am unable to figure out whats the error. Please have a look at my code and help me to trace the problem.

You might look at this method for finding the number of trailing zeros in n!.
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int count = in.nextInt();
for (int i = 0; i < count; i++) {
int n = in.nextInt();
int result = 0;
for (int d = 5; d <= n; d *= 5) {
result += n / d;
}
System.out.println(result);
}
}
}

Your approach (naive: counting the real factorial value and then counting the zeros manually) would NEVER pass no matter how. Take a look at the extreme case (i.e. upper limit of the factorial, I don't even think the given memory limit is enough to compute it). Look at the problem from different way, think what the real problem is, that's the art of problem solving ;)
Hint: what can produce and add more 0s to the end of a number, specifically by multiplication?

The reason for your error is it should be public class Main
Also your code will get TLE, you must observe that brute force will never work on SPOJ. The way to solve this is to see an interesting pattern with powers of 5 and the number of zeroes at the end.

Here is a solution in C. We don't need to compute the exact factorial for this problem.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX 1000000
int xpn(int x, int n){
int prod=1;
while(n){
prod*=x;
n--;
}
return prod;
}
int trail(int x){
int numZero=0;
int i=1;
int k;
for(;x/xpn(5,i);i++){
numZero+=(x/xpn(5,i));
}
return numZero;
}
int main(int argc, char **argv){
#if 1
int n;
int num[MAX];
int zero[MAX];
scanf("%d",&n);
int count=n;
int i=0;
while(count){
scanf("%d",&num[i]);
zero[i]=trail(num[i]);
printf("%d\n",zero[i]);
i++;
count--;
}
#endif
return 0;
}

import java.util.*;
import java.lang.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
Scanner s = new Scanner(System.in);
int t = s.nextInt();
while (t-->0){
int n = s.nextInt();
int count = 0;
while(n>0){
count +=n/5;
n/=5;
}
System.out.println(count);
}
}
}
This solution will work absolutely fine.
Let me explain it.
When you refer to quantitative aptitude there is a short formula for calculating the number of trailing zeroes for any factorial number. Divide the number directly by 5 and start adding quotient and then divide quotient with 5 and again add until the value start giving constant quotient. Refer to below example. If you don't even understand refer to quantitative aptitude from any source.
e.g.
1. 60! 60/5 = 12, 12/5 = 2, add all the quotient i.e equals to 14.
2. 500! 500/5 = 100, 100/5 = 20, 20/5 = 4, ans = 124.

Related

Recursion in Java, sum of k integers after integer m

I need to use recursion to make an algorithm which finds the sum of x integers after an integer m. For example, if m is 2 and n is 5, I would need to find the sum of 2+3+4+5+6 using recursion.
The code I have so far would (for the example illustrated above) works in such way: 2+3+3+3+3. Any help at all is greatly appreciated as I have an exam tomorrow and questions like these may be included.
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Input a value for n");
int n = input.nextInt();
System.out.println("Input a value for m");
int m = input.nextInt();
System.out.println(sho (m,n));
}
public static int sho (int m, int n){
int sum = 0;
if(n<=0){
return m;
}
sum = sho(m+1,n-1);
sum = sum +(m);
return sum;
}
You only need to implement the summation of a series using recursion. The starting and ending points are really just minor logic. The inductive case of the recursion is is that the current value is less than the end of the series. In this case, we return the current value plus a recursive call with the starting point increased by one. The base case occurs when we reach the end of the series. For the base case, we just return the max value and stop the recursion.
public static int sho(int curr, int max) {
if (curr == max) {
return curr;
}
else {
return curr + sho(curr + 1, max);
}
}
public static void main(String args[]) {
System.out.println(sho(10, 15)); // 10 11 12 13 14 15
}
One problem I see with your code is your recursion logic:
sum = sho(m+1, n-1);
I don't think that decreasing the upper bound is the way to go here. Instead, keep that bound fixed and advance through the series by making another recursive call. Decreasing the upper bound sounds like mixing recursion with an iterative approach.
Demo
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Input a value for n");
int n = input.nextInt();
System.out.println("Input a value for m");
int m = input.nextInt();
System.out.println(sho (m,n,0));
}
public static int sho (int m, int n,int sum){
if(n<=0){
return sum;
}
sum=sum+m;
sum = sho(m+1,n-1,sum);
return sum;
}
Try this

Why I cannot get the correct number of candies using this program?

This exercise required us to write a program for counting the number of candies the poor kids can get. The question is shown below:
You are requested to write a Java program to help these poor kids to answer this question. To generalize the solution, your program should be able to accept different values of n and m as input, where n = 10 and m = 2 in this question. To avoid infinite number of answers, you may assume that each candy has exactly one foil and it is not allowed to cut the foils.
And I follow the hints given to write the program using the provided formula and java recursion.
import java.util.Scanner;
public class MyFirstClass{
public static void main(String args[]){
Scanner a=new Scanner(System.in);
int n=0,m=0;
n = a.nextInt();
m = a.nextInt();
System.out.println("Candy " +n+" "+ m + " n="+ n+";m="+m+";No. of Candies="+total(n,m));
}
static int sum=0;
static int total(int n, int m)
{
int sum1=n;
sum1+=candy(n,m);
return sum1;
}
static int candy(int n,int m){
if((n+n%m)/m>1){
sum+=n/m+candy((n+(n%m))/m,m);
}
return sum;
}
}
However, when I set n=10 and m=2, the calculated total number of candies is less than the actual total number of candies by 1. What is the problem of my program? Thank you!
For your candy function:
static int candy(int n,int m){
if((n+n%m)/m>1){
sum+=n/m+candy((n+(n%m))/m,m);
}
return sum;
}
How does it even compile when sum is undefined?
In any case, the candy function needs to check the boundary condition of of when the first paramater is 0 or 1. And I'll assume negative numbers aren't valid input either.
int candy(int n, int m) {
if ((n <= 1) || (m == 0)) {
return 0;
}
return n/m + candy( ((n+n%m)/m), m);
}
And since it's "tail recursion", you can implement the entire thing with a while loop:
int candy(int n, int m) {
int result = 0;
while ((n > 1) && (m != 0))
{
result += n/m;
n = (n+n%m)/m;
}
return result;
}

Dynamic Programming Fibonacci Sequence

I was learning dynamic programming's application to the Fibonacci Sequence and had a question. Here is the code for reference:
import java.math.BigInteger;
import java.util.Arrays;
public class FibonacciNumbersB {
static BigInteger[] dp = new BigInteger[10000];
public static void main(String[] args) {
Arrays.fill(dp, BigInteger.ZERO);
dp[0] = BigInteger.ONE;
dp[1] = BigInteger.ONE;
for(int i = 4; i < 9999; i++)
System.out.println(fibRecurse(i).toString());
}
public static BigInteger fibRecurse(int N) {
for(int i = 2; i < N; i++) {
// For numerous calls to this function, this will save as it goes
if(dp[i].equals(BigInteger.ZERO))
dp[i] = dp[i - 1].add(dp[i - 2]);
}
return dp[N - 1];
}
}
I have a statement check if dp[i] equals 0 in the fibRecurse method (although fibRecurse isn't recursive).
Is it more efficient to check if dp[i] has been calculated already or to just let dp[i] equal to the sum of the previous two elements?
I would prefer a Map<Integer, BigInteger> over using a fixed BigInteger[] when performing this memoization. Note that your current approach is not recursive. The Map might be declared and initialized like
static Map<Integer, BigInteger> memo = new HashMap<>();
static {
memo.put(0, BigInteger.ONE);
memo.put(1, BigInteger.ONE);
}
Then check if the current n is present in the memo (if it is, return it) - otherwise, computer and store it. Like,
public static BigInteger fibRecurse(int n) {
if (memo.containsKey(n)) {
return memo.get(n);
}
BigInteger v = fibRecurse(n - 1).add(fibRecurse(n - 2));
memo.put(n, v);
return v;
}
A version without memoization would simply omit memo like
public static BigInteger fibRecurseSlow(int n) {
if (n == 0 || n == 1) return BigInteger.ONE;
BigInteger v = fibRecurse(n - 1).add(fibRecurse(n - 2));
return v;
}
I think you can infer from the method names I've chosen which is slower.
import java.math.BigInteger;
import java.util.Arrays;
public class FibonacciNumbersB {
static BigInteger[] dp = new BigInteger[10000];
public static void main(String[] args) {
dp[0] = BigInteger.ONE;
dp[1] = BigInteger.ONE;
int N = 9999;
fibRecurse(N);
for(int i = 0; i < N; i++)
System.out.println(dp[i].toString()) ;
}
public static void fibRecurse(int N) {
for(int i = 2; i < N; i++) {
dp[i] = dp[i - 1].add(dp[i - 2]);
}
}
}
The code that is for finding fibonacci sequence can be write easily.Let's consider recursive code for finding fibonacci number set.
import java.util.Scanner;
class fac{
public static void main(String a[]){
Scanner sc=new Scanner(System.in);
System.out.print("Enter Your number :");
int n=sc.nextInt();
System.out.print(fibonacci(n));
}
public static int fibonacci(int x){
if(x<2){
return 1;
}
else{
return (fibonacci(x-1)+fibonacci(x-2));
}
}
}
In this stage, there are many same subproblems are calculating again and again.So in this case, time complexity goes to height for large input. Because of that reason , dynamic programming technique was came ...In dynamic programming ,an extra table('lookUp' table) is maintained for storing previous calculated subproblems' values. before calculating next subproblems' value, check whether availability of the answer for the particular subproblem in created table('lookUp' table).If it is in the 'lookUp table', get the answer for particular subproblem. If it is not in the 'lookUp ' table, calculate value of the particular problem and store the 'lookUp ' table. That is the meaning of the dynamic programming technique.There are two ways for performing this technique.
1.Memoization -
memoization is the technique that calculating values of subproblems Top- Down manner.Let's consider the code of fibonacci sequence.
import java.util.Scanner;
class fab{
public static void main(String a[]){
Scanner sc=new Scanner(System.in);
System.out.print("Enter Your number :");
int n=sc.nextInt();
int[] lookUp=new int[n];
int i;
for(i=0;i<n;i++){
lookUp[i]=-1;
}
fibonachi(n);
}
public static void fibonachi(int x){
if(lookUp[x]==-1){
if(x<=1){
lookUp[x]=x;
}
else{
lookUp[x]=fibonachi(x-1)+fibonachi(x-2);
}
}
System.out.print(lookUp[x]);
}
}
2.Tabulation - This calculation goes to Bottom to Top manner.At first consider the base case and perform . Then perform the next steps using previous cases.Les's consider fibonacci sequence code with tabulation technique.
import java.util.Scanner;
class fac{
public static void main(String a[]){
Scanner sc=new Scanner(System.in);
System.out.print("Enter Your number :");
int n=sc.nextInt();
int[] lookUp=new int[n];
int i;
lookUp[0]=1; // store base case values in the 'lookUp' table
lookUp[1]=1;
for(i=2;i<n;i++){
lookUp[i]=lookUp[i-1]+lookUp[i-2];
}
System.out.print(lookUp[n-1]);
}
}
In this case , base case values are stored at first.then calculates next values using previous ones..In tabulation all the values must be calculated because new value calculated using previous vlues..so memoization is better than tabulation.That's all. I hope, you could get idea.Thank you!

How to reverse a number without using a n array and also without using any library function?

I want to reverse a number without using array.I want to know how would I save the number.I think for this step I need to also know whether the number is one digit or two digit etc.
Below is my code what I did.
#Edit
I have solved this problem by following method
public class ReverseNumber
{
public static void main(String[] args)
{
ReverseNumber obj = new ReverseNumber();
int result = obj.reverse(2199);
System.out.println(result);
}
public int reverse(int num)
{
int rnum1=0;
for(int i=num;i!=0;)
{
rnum1=(rnum1*10)+(i%10);
i=i/10;
// write your code here
}
return rnum1;
}
}
you almost had it! you're only missing the part where you need to multiply num1 with 10, and the choice of the loop is a bit unlucky:
public static int reverse(int num) {
int input = num;
int num1 = 0;
while (input>0) {
num1 = num1 * 10;
num1 = num1 + input%10;
input = input / 10;
}
return num1;
}
EDIT: had a mistake in the implemetation... now it's fixed
#Parker_Halo provided an excellent iterative solution. I am adding here a recursive solution for completeness:
public static int reverse(int number, int n) {
if (number == 0)
return n;
return reverse(number / 10, n * 10 + number % 10);
}
You would call it like this :
int rev = reverse(num, 0);

Java program that converts binary numbers to decimal numbers. The input is a string of zeros and ones

I have to create a java program that converts binary to decimal using the following steps. Being new at this I did something, but I don't know what I did wrong or how to continue.
public class BinaryToDecimal {
public static void main(String args[]){
long sum = 0;
int result;
String s = "1001010101011010111001011101010101010101";
for(int i = s.length()-1; i <= 0; i--){
result = (int)Math.pow(2, i);
if(s.charAt(i) == '1')
sum=sum + result;
}
System.out.println(sum);
}
}
Use a loop to read (charAt()) each digit (0/1 char) in the input string, scanning from right to left;
Use the loop to build the required powers of 2;
Use a conditional statement to deal with 0 and 1 separately;
Debug using simple input, e.g. 1, 10, 101, and print intermediate values in the loop.
Use your program to find the decimal value of the following binary number:
1001010101011010111001011101010101010101
Do this only if your decimal value is at most 2147483647 or the maximum value an int can be in Java. If you don't know, just check the length of your string. If it's less than or equal to 32 i.e. 4 bytes, then you can use parseInt.:
int decimalValue = Integer.parseInt(s, 2);
Refer HERE for more info on the Integer.parseInt();
But if it's more, you can use your code. I modified your loop which is where your problem was:
String s = "1001010101011010111001011101010101010101";
long result = 0;
for(int i = 0; i < s.length(); i++){
result = (long) (result + (s.charAt(i)-'0' )* Math.pow(2, s.length()-i-1));
}
System.out.println(result);
The first thing I notice is that your binary number has more than 32 bits. This cannot be represented in the space of an int, and will result in overflow.
As a simpler answer, I ran the following and got the correct value at the end, it just uses simple bit shifts.
For each index in the string, if the character is 1, it sets the corresponding bit in the result.
public class BinaryToDecimal {
public static void main(String[] args) {
long sum;
String bin = "1001010101011010111001011101010101010101";
sum = 0;
for (int i = 0; i < bin.length(); i++) {
char a = bin.charAt(i);
if (a == '1') {
sum |= 0x01;
}
sum <<= 1;
}
sum >>= 1;
System.out.println(sum);
}
}
The loop runs from i = s.length()-1 until i <= 0. This should be i>=0.
The next problem is "int result". It works fine with result as a long ;) (Reason: You calculate a 40-bit value at the MostSignificantBit, but Integers only use 32-bit)
Also: You start at the rightmost Bit with i=s.length()-1. But the power that you calculate for it is 2^(s.length()-1) though it should be 2^0=1.
The solution is: result = (long)Math.pow(2, s.length()-1-i)
Edit:
I really like the solution of user2316981 because of its clear structure (without Math.pow, should be faster by using shift instead). And loops from 0 to MSB as I do with Double&Add algorithm. Can't comment on it yet, but thanks for the reminder ;)
import java.util.*;
import java.lang.Math;
class deci {
int convert(int n) {
int tem=1,power=0;
int decimal=0;
for (int j=0;j<n;j++) {
if(n==0) {
break;
} else {
while(n>0) {
tem=n%10;
decimal+=(tem*(Math.pow(2,power)));
n=n/10;
power++;
}
}
}
return decimal;
}
public static void main(String args[]) {
System.out.print("enter the binary no");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
deci dc=new deci();
int i=dc.convert(n);
System.out.print(i);
}
}

Categories

Resources