Fibonacci calculation using memoization in Java - java

I tried below code sniped, while i am initializing mem[] array out of the method it is taking 1ms to execute the code but if i am initializing it inside the method it is taking ~16000 ms to execute. I am not able to understand, why?, please help me out.
public class FiboMemoization {
//public static long [] mem = new long[41];
public static long fibo(int n){
// long [] mem = new long[41];
if(mem[n] == 0){
if(n <= 1){
mem[n] = n;
}else if(mem[n] != 0)
mem[n] = mem[n];
else
mem[n] = fibo(n-1)+fibo(n-2);
}
return mem[n];
}
}

It's only memorized if the memory (i.e. long[] mem) is stored outside the function.
long[] mem inside the function causes two issues:
Reallocates memory every call (slow)
Does not do memoization since the array is empty on every function call (new arrays are 0 in Java)

import java.math.BigInteger;
import java.util.Arrays;
public class Main {
private static int _memo_length;
private static int _memo_idx;
private static BigInteger[] _memo;
static {
_memo_length = 1024;
_memo = new BigInteger[_memo_length];
_memo[0] = BigInteger.ONE;
_memo[1] = BigInteger.ONE;
_memo_idx = 1;
}
public static void main(String[] args) {
int xIndex = 4000; //locate the 4000th fibo member.
BigInteger output = locateFibonacciMember(xIndex - 1);
System.out.println(output);
}
public static BigInteger locateFibonacciMember(int idx) {
if (idx <= _memo_idx) {
return _memo[idx];
}
while (idx > _memo_idx) {
if (++_memo_idx >= _memo.length) {
if (!_extendMemo()) return BigInteger.ZERO;
}
_memo[_memo_idx] = _memo[_memo_idx - 1].add(_memo[_memo_idx - 2]);
}
return _memo[_memo_idx];
}
private static boolean _extendMemo() {
try {
_memo = Arrays.copyOf(_memo, _memo.length + _memo_length);
} catch (Exception e) {
return false;
}
return true;
}
}

Related

Java Threads (Beginner)

I'm having an issue dealing with my java code here.
I was sure I've used al recommandation I've founded online. But it still doesn't work.
import java.util.*;
import java.util.concurrent.*;
import java.util.Map;
public class GradeCounterImpl implements GradeCounter {
ConcurrentHashMap<String, GradeCount> save;
public GradeCount[] count(String[] grades, int nThreads) {
if (grades == null) {
return new GradeCount[0];
}
if (grades.length == 0) {
return new GradeCount[0];
}
save = new ConcurrentHashMap<>();
class WorkUnit implements Runnable {
final String[] positions;
public WorkUnit(String[] i) {
this.positions = i;
}
public void run() {
for (String pos : positions)
if (pos != null) {
if (save.containsKey(pos)) {
save.get(pos).count++;
} else {
save.put(pos, new GradeCount(pos, 1));
}
}
}
}
int divide = (grades.length / nThreads);
ExecutorService exe = Executors.newFixedThreadPool(nThreads);
for (int i = 0; i < nThreads; i++)
exe.execute(new WorkUnit(arrayBetween(i * divide, (i + 1) * divide, grades)));
exe.shutdown();
try {
exe.awaitTermination(30, TimeUnit.MINUTES);
} catch (InterruptedException error) {
error.printStackTrace();
}
Collection<GradeCount> c = save.values();
return c.toArray(new GradeCount[c.size()]);
}
private String[] arrayBetween(int start, int end, String[] target) {
String[] ans = new String[end - start];
for (int i = start; i < end; i++)
if (i < target.length)
ans[i - start] = target[i];
return ans;
}
}
public class GradeCount implements Comparable<GradeCount> {
public String grade;
public int count;
public GradeCount(final String grade, final int count) {
this.grade = grade;
this.count = count;
}
public int compareTo(final GradeCount other) {
final int gradeCmp = this.grade.compareTo(other.grade);
return gradeCmp == 0 ? Integer.compare(this.count, other.count) : gradeCmp;
}
}
What it's to do ?
The code must be counting every String appearing in the grades array and saving the results in the hashmap and then returning their values.
What's the problem ?
The code isn't (as you can guest with the title) not working fine. It doesn't count well and I'm having huge difference between big arrays tests.
Observations :
When I test with small arrays (0 - 50 values), the program run well
Now : What should I do ?
Thanks you for reading all here and I hope you can help me.
The problem is here:
if (save.containsKey(pos)) {
save.get(pos).count++;
} else {
save.put(pos, new GradeCount(pos, 1));
}
You have a ConcurrentHashMap but your GradeCounter is not synchornized, hence call to count++ will not correct
I think your GradeCount look like {grade, count} so I suggest you to use Map<String, AtomicInteger> isntead

java program giving blank output

The program works fine for small numbers but as soon as i take a big number like this it doesn't work
here is my code
public class Main {
public static void main(String[] args) {
long no=600851475143L,i;
int result=0;
for(i=(no/2);i>=2;i--){
if(no%i==0){
if(checkPrime(i)){
System.out.println("Longest Prime Factor is: " + i);
break;
}
}
}
}
private static boolean checkPrime(long i){
for(long j=2L;j<=(int)Math.sqrt(i);j++){
if(i%j==0)
return false;
}
return true;
}
}
to assign long variable value we does not require write L at last on value Remove L.
It will take time to display the answer. Just try with small number(1000000 ) almost 10 to 15 min for above code.
Try this
public class Main {
public static void main(String[] args) {
//long no=600851475143L,i;
System.out.println(largestPrimeFactor(600851475143L));
}
public static int largestPrimeFactor(long number) {
int i;
for (i = 2; i <= number; i++) {
if (number % i == 0) {
number /= i;
i--;
}
}
return i;
}
}
[1]https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

StackOverFlowError in java program [duplicate]

This question already has answers here:
What is a StackOverflowError?
(16 answers)
Closed 7 years ago.
I am trying to solve a problem which asks to find the smallest prime palindrome, which comes after a given number which means that if the input is 24, the output would be 101 as it is the smallest number after 24 which is both prime and a palindrome.
Now my code works perfectly for small values but the moment I plug in something like 543212 as input, I end up with a StackOverFlowError on line 20, followed by multiple instances of StackOverFlowErrors on line 24. Here is my code :
package nisarg;
import java.util.Scanner;
public class Chef_prime_palindromes {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
long num = input.nextLong();
isPalindrome(num + 1);
}
public static boolean isPrime(long num) {
long i;
for (i = 2; i < num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
public static void isPalindrome(long num) {
String word = Long.toString(num);
int i;
for (i = 0; i < word.length() / 2; i++) {
if (word.charAt(i) != word.charAt(word.length() - i - 1)) {
isPalindrome(num + 1);
}
}
if (i == word.length() / 2) {
if (isPrime(num)) {
System.out.println(num);
System.exit(0);
} else {
isPalindrome(num + 1);
}
}
}
}
All shown exiting solutions use recursion and have the problem that at some point they will reach the point where a StackOverflowException will occur.
A better solution which would also be parallelizable would be to change it into a loop.
It could be something like:
package nisarg;
import java.math.BigInteger;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;
public class Chef_prime_palindromes {
private static final CopyOnWriteArrayList<BigInteger> PRIMESCACHE
= new CopyOnWriteArrayList<>();
public static void main(String[] args) {
try (Scanner input = new Scanner(System.in)) {
BigInteger num = new BigInteger(input.nextLine());
initPrimes(num);
for (num = num.add(BigInteger.ONE);
!isPrimePalindrome(num);
num = num.add(BigInteger.ONE));
System.out.println(num.toString());
}
}
private static void initPrimes(BigInteger upTo) {
BigInteger i;
for (i = new BigInteger("2"); i.compareTo(upTo) <= 0 ; i = i.add(BigInteger.ONE)) {
isPrime(i);
}
}
public static boolean isPrimePalindrome(BigInteger num) {
return isPrime(num) && isPalindrome(num);
}
// could be optimized
public static boolean isPrime(BigInteger num) {
for (int idx = PRIMESCACHE.size() - 1; idx >= 0; --idx) {
if (num.mod(PRIMESCACHE.get(idx)).compareTo(BigInteger.ZERO) == 0) {
return false;
}
}
if (!PRIMESCACHE.contains(num)) {
PRIMESCACHE.add(num);
}
return true;
}
public static boolean isPalindrome(BigInteger num) {
String word = num.toString();
int i;
for (i = 0; i < word.length() / 2; i++) {
if (word.charAt(i) != word.charAt(word.length() - i - 1)) {
return false;
}
}
return true;
}
}
A new String object is created in each recursive call and placed onto stack (the place where all variables created in methods are stored until you leave the method), which for a deep enough recursion makes JVM reach the end of allocated stack space.
I changed the locality of the String object by placing it into a separate method, thus reducing its locality and bounding its creation and destruction (freeing of stack space) to one recursive call.
package com.company;
import java.util.Scanner;
public class Chef_prime_palindromes {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
long num = input.nextLong();
isPalindrom(num + 1);
}
public static boolean isPrime(long num) {
long i;
for (i = 2; i < num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
private static void isPalindrom(long num) {
for (; ; ) {
if (isPalindrome(num)) {
if (isPrime(num)) {
System.out.println(num);
System.exit(0);
} else {
num++;
}
} else {
num++;
}
}
}
public static boolean isPalindrome(long num) {
String string = String.valueOf(num);
return string.equals(new StringBuilder(string).reverse().toString());
}
}
First thing you should be aware of is the fact that your resources are limited. Even if your implementation was precise and all recursive calls were correct, you may still get the error. The error indicates your JVM stack ran out of space. Try to increase the size of your JVM stack ( see here for details).
Another important thing is to look for the distribution of prime and palindrome numbers. Your code runs by testing every num+1 against palindrome property. This is incorrect. You test for palindrome only when the number is prime. This will make the computation much much easier (and reduce recursive calls). I have edited your code accordingly and got the closest palindrome number after 543212 (1003001) . Here it is:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
long num = input.nextLong();
//isPalindrome(num+1);
nextPrimePalindrome(num+1);
}
public static void nextPrimePalindrome(long num)
{
boolean flag=true;
while(flag)
{
if(isPrime(num))
if(isPalindrome(num))
{
System.out.println(num);
flag=false;
}
num++;
}
}
public static boolean isPrime(long num){
long i;
for(i=2;i<num;i++){
if(num%i == 0){
return false;
}
}
return true;
}
public static boolean isPalindrome(long num)
{
String word=Long.toString(num);
for(int i=0;i<word.length()/2;i++)
if(word.charAt(i)!=word.charAt(word.length()-i-1))
return false;
return true;
}
}

Java recursion to find prime factors doesn't work

I am trying to get all prime factors of a number. The for loop should work until it finds the match and it should break and jump to the next if statement which checks if number is not equal to zero.
public class Factor {
public static ArrayList <Integer> HoldNum = new ArrayList();
public static void main(String[]args){
Factor object = new Factor();
object.Factor(104);
System.out.println(HoldNum.get(0));
}
public static int Factor(int number){
int new_numb = 0;
int n=0;
for( n = 1; n < 9; n++) {
if (number % n == 0) {
HoldNum.add(n);
new_numb = number/n;
break;
}
}
System.out.println(new_numb);
if(new_numb < 0) {
HoldNum.add(new_numb);
return 1;
} else {
return Factor(new_numb);
}
}
}
There are at least three errors :
As okiharaherbst wrote, your counter is not incremented.
you start your loop at 1, so yourval % 1 always equals to 0 and new_numb is always equals to your input val, so you'll loop endlessly on 104.
new_numb will never be lesser than 0.
You asked for a recursive solution. Here you go:
public class Example {
public static void main(String[] args) {
System.out.println(factors(104));
}
public static List<Integer> factors(int number) {
return factors(number, new ArrayList<Integer>());
}
private static List<Integer> factors(int number, List<Integer> primes) {
for (int prim = 2; prim <= number; prim++) {
if (number % prim == 0) {
primes.add(prim);
return factors(number / prim, primes);
}
}
return primes;
}
}
The code is not bullet-proof, it is only a quick-and-dirty example.
Java implementation...
public class PrimeFactor {
public int divisor=2;
void printPrimeFactors(int num)
{
if(num == 1)
return;
if(num%divisor!=0)
{
while(num%divisor!=0)
++divisor;
}
if(num%divisor==0){
System.out.println(divisor);
printPrimeFactors(num/divisor);
}
}
public static void main(String[] args)
{
PrimeFactor obj = new PrimeFactor();
obj.printPrimeFactors(90);
}
}

Java - Error Message Help

In the Code, mem is a of Class Memory and getMDR and getMAR ruturn ints. When I try to compile the code I get the following errors.....how can I fix this?
Computer.java:25: write(int,int) in Memory cannot be applied to (int)
Input.getInt(mem.write(cpu.getMDR()));
^
Computer.java:28: write(int,int) in Memory cannot be applied to (int)
mem.write(cpu.getMAR());
Here is the code for Computer:
class Computer{
private Cpu cpu;
private Input in;
private OutPut out;
private Memory mem;
public Computer()
{
Memory mem = new Memory(100);
Input in = new Input();
OutPut out = new OutPut();
Cpu cpu = new Cpu();
System.out.println(in.getInt());
}
public void run()
{
cpu.reset();
cpu.setMDR(mem.read(cpu.getMAR()));
cpu.fetch2();
while (!cpu.stop())
{
cpu.decode();
if (cpu.OutFlag())
OutPut.display(mem.read(cpu.getMAR()));
if (cpu.InFlag())
Input.getInt(mem.write(cpu.getMDR()));
if (cpu.StoreFlag())
{
mem.write(cpu.getMAR());
cpu.getMDR();
}
else
{
cpu.setMDR(mem.read(cpu.getMAR()));
cpu.execute();
cpu.fetch();
cpu.setMDR(mem.read(cpu.getMAR()));
cpu.fetch2();
}
}
}
Here is the code for Memory:
class Memory{
private MemEl[] memArray;
private int size;
public Memory(int s)
{size = s;
memArray = new MemEl[s];
for(int i = 0; i < s; i++)
memArray[i] = new MemEl();
}
public void write (int loc, int val)
{if (loc >=0 && loc < size)
memArray[loc].write(val);
else
System.out.println("Index Not in Domain");
}
public int read (int loc)
{return memArray[loc].read();
}
public void dump()
{
for(int i = 0; i < size; i++)
if(i%1 == 0)
System.out.println(memArray[i].read());
else
System.out.print(memArray[i].read());
}
}
Here is the code for getMAR and getMDR:
public int getMAR()
{
return ir.getOpcode();
}
public int getMDR()
{
return mdr.read();
}
Your Memory class has a method write(int, int).
You call it with a single int. As if it was write(int).
Java complains about that: "Computer.java:28: write(int,int) in Memory cannot be applied to (int)". So either you are missing your location (loc) parameter or your value (val) parameter; depending on what code is supposed to be actually doing.

Categories