Having trouble recursively calling my algorithm - java

I'm writing a divide and conquer algorithm but I'm having trouble recursively calling it. It says it cannot find the symbol method Multiply and the variables m, e, m
public class Multiply {
private static int randomInt(int size) {
int maxval = (1 << size) - 1;
return (int)(Math.random()*maxval);
}
public static int[] naive(int size, int x, int y) {
int[] result = new int[3];
if (size == 1) {
result[0] = x*y;
}
else {
int m = size/2;
int a = x/2;
int b = x % (int)Math.pow(2,m);
int c = y / (int)Math.pow(2,m);
int d = y % (int)Math.pow(2,m);
int e = Multiply(a,c,m);
int f = Multiply(b,d,m);
int g = Multiply(b,c,m);
int h = Multiply(a,d,m);
}
return ((int)Math.pow(2,2*m)*e) + ((int)Math.pow(2,m)*(g+h)) + f;
}

Try Multiply.naive(x,y,z) instead of Multiply(x,y,z)

Related

Sum of numbers in a given Fibonacci sequence

My task is to determine whether the sum of numbers in the Fibonacci series from A to B is divisible by the number D.
I use the fast doubling algorithm to find the required number in the series, and use the formula: Fa + ... + Fb = Fb+2 - 1 - (Fa+1 - 1) - to determine the sum of the series, but this is not enough. For testing, I took a series from A = 10,000,000 to B = 20,000,000, the number D = 987654, the program was executed in 3.3 seconds, this is a lot. Are there ways to optimize my code?
class Solution {
private static Map<BigDecimal, BigDecimal> previousValuesHolder;
static {
previousValuesHolder = new HashMap<>();
previousValuesHolder.put(BigDecimal.ZERO, BigDecimal.ZERO);
previousValuesHolder.put(BigDecimal.ONE, BigDecimal.ONE);
}
private static BigInteger totalSum;
public static void main(String args[]) {
Scanner in = new Scanner(System.in);
int nb = in.nextInt();
for (int i = 0; i < nb; i++) {
int a = in.nextInt();
int b = in.nextInt();
int d = in.nextInt();
totalSum = calculateTotalSum(a, b);
System.out.println(checkSum(totalSum, a, b, d));
}
}
private static BigInteger calculateTotalSum(int start, int finish) {
BigInteger res1 = fibDoubleFast(finish + 2).subtract(BigInteger.valueOf(1));
BigInteger res2 = fibDoubleFast(start + 1).subtract(BigInteger.valueOf(1));
return res1.subtract(res2);
}
private static String checkSum(BigInteger sum, int start, int finish, int d) {
BigInteger result = sum.remainder(BigInteger.valueOf(d));
return result.longValue() > 0
? String.format("F_%s + ... + F_%s is NOT divisible by %s", start, finish, d)
: String.format("F_%s + ... + F_%s is divisible by %s", start, finish, d);
}
private static BigInteger fibDoubleFast(int n) {
BigInteger a = BigInteger.ZERO;
BigInteger b = BigInteger.ONE;
int m = 0;
for (int bit = Integer.highestOneBit(n); bit != 0; bit >>>= 1) {
BigInteger d = multiply(a, b.shiftLeft(1).subtract(a));
BigInteger e = multiply(a, a).add(multiply(b, b));
a = d;
b = e;
m *= 2;
if ((n & bit) != 0) {
BigInteger c = a.add(b);
a = b;
b = c;
m++;
}
}
return a;
}
private static BigInteger multiply(BigInteger x, BigInteger y) {
return x.multiply(y);
}
}
For small values of D (less than 2^31, I think) , you could do the whole code using long, and do mod D for every intermediate result.
private static long fibDoubleFastModD(int n, long m) {
...
long d = (...) % m;
long e = (...) % m;
...
}

How to replace SortedSet with something faster or speed it up

I'm trying to resolve the problem from LeetCode https://leetcode.com/problems/nth-magical-number/ . I can submit my solution, but I would like to speed it up, I suppose one of the ways to do so is remove using of collections
class Solution {
private static final int MODULO = (int) (Math.pow(10, 9) + 7);
private static int modulate(final long result) {
return (int) (result % MODULO);
}
private static SortedSet<Integer> steps(final int smaller, final int larger) {
final int lcm = lowestCommonMultiple(smaller, larger);
final SortedSet<Integer> result = new TreeSet<>();
final int max = lcm / smaller;
final int min = lcm / larger;
for (int i = 1; i <= max; i++) {
result.add(i * smaller);
if (i <= min) {
result.add(i * larger);
}
}
return result;
}
private static long nthNonZeroMagicalNumber(final int N, final int smaller, final int larger) {
final SortedSet<Integer> stepsInCycle = steps(smaller, larger);
final long lcm = stepsInCycle.last();
final int inOneCycle = stepsInCycle.size();
final int fullCycleCount = N / inOneCycle;
int count = fullCycleCount * inOneCycle;
final long evaluated = fullCycleCount * lcm;
if (count == N) {
return evaluated;
}
final int remainder = N - count - 1;
return stepsInCycle.toArray(new Integer[stepsInCycle.size()])[remainder] + evaluated;
}
private static int greatestCommonDenominator(int a, int b) {
while (b > 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
private static int lowestCommonMultiple(final int a, final int b) {
return a * (b / greatestCommonDenominator(a, b));
}
public static int nthMagicalNumber(final int N, final int A, final int B) {
if (N == 0) {
return 0;
} else if (A == B) {
final long result = (long) A * (long) N;
return modulate(result);
} else if (N == 1) {
return modulate(Math.min(A, B));
}
return modulate(nthNonZeroMagicalNumber(N, Math.min(A, B), Math.max(A, B)));
}
}
I suppose it is possible to replace it with a standard array or something like that. Thank you in advance guys!
This is an example of how doing with array only instead of SortedSet:
import java.util.Arrays;
import java.util.Objects;
class Solution {
private static final int MODULO = (int) (Math.pow(10, 9) + 7);
private static int modulate(final long result) {
return (int) (result % MODULO);
}
private static Integer[] steps(final int smaller, final int larger) {
final int lcm = lowestCommonMultiple(smaller, larger);
final int max = lcm / smaller;
final int min = lcm / larger;
final Integer[] result = new Integer[max * 2];
int pos = 0;
for (int i = 1; i <= max; i++) {
result[pos++] = (i * smaller);
if (i <= min) {
result[pos++] = (i * larger);
}
}
return Arrays.stream(result)
.filter(Objects::nonNull)
.sorted()
.distinct()
.toArray(Integer[]::new);
}
private static long nthNonZeroMagicalNumber(final int N, final int smaller, final int larger) {
final Integer[] stepsInCycle = steps(smaller, larger);
final long lcm = stepsInCycle[stepsInCycle.length - 1];
final int inOneCycle = stepsInCycle.length;
final int fullCycleCount = N / inOneCycle;
int count = fullCycleCount * inOneCycle;
final long evaluated = fullCycleCount * lcm;
if (count == N) {
return evaluated;
}
final int remainder = N - count - 1;
return stepsInCycle[remainder] + evaluated;
}
private static int greatestCommonDenominator(int a, int b) {
while (b > 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
private static int lowestCommonMultiple(final int a, final int b) {
return a * (b / greatestCommonDenominator(a, b));
}
public static int nthMagicalNumber(final int N, final int A, final int B) {
if (N == 0) {
return 0;
} else if (A == B) {
final long result = (long) A * (long) N;
return modulate(result);
} else if (N == 1) {
return modulate(Math.min(A, B));
}
return modulate(nthNonZeroMagicalNumber(N, Math.min(A, B), Math.max(A, B)));
}
}
If you have an example of value that causes the performance concern, you could use and compare both solutions or post here and I can try to help in adapting.
You don't need a Set or arrays to solve this problem:
public static final long MAX_N = Double.valueOf(Math.pow(10.0, 9.0)).longValue();
public static final long MODULO_VALUE = MAX_N + 7L;
public static long nthMagicalNumber(long n, long a, long b) {
long count = 0L;
long sample = Math.min(a, b);
long result = sample;
do {
result = sample;
long nextA = ((sample / a) * a) + a;
long nextB = ((sample / b) * b) + b;
sample = Math.min(nextA, nextB);
count++;
} while(count < n);
return result % MODULO_VALUE;
}

What is wrong with my solution of SPOJ ACTIV?

Here is the link for the problem:SPOJ - ACTIV
I came up with the recurrence for the problem as:
F(i) = 1+F(i+1)+F(next(activities[i].endtime))
where next() finds out the index of the activity with start time>= end time of the current activity, while the activities have been sorted in increasing order of their Start time.
This is my java solution, although it passes many test cases of SPOJ toolkit, however it does give WA for some. What is the problem in my concept/solution?
import java.util.*;
import java.io.*;
class Pair<T>{
final T x;
final T y;
Pair(T a, T b){
this.x = a;
this.y = b;
}
}
public class Activities{
private static int search(Pair<Integer> []p,int key, int l, int h)
{
int ll=l;
while(l<h)
{
int mid = (l+h)/2;
if(p[mid].x < key)l=mid+1;
else if(p[mid].x == key){
while(mid>=ll && p[mid].x == key)mid--;
return mid+1;
}
else h=mid;
}
if(l==h && l>=0 && p[l].x>=key)return l;
return -1;
}
public static void main(String[] args)throws IOException {
final long mod = 100000000;
BufferedReader buff = new BufferedReader(new InputStreamReader(System.in));
while(true)
{
int n = Integer.parseInt(buff.readLine());
if(n==-1)return;
Pair <Integer> p [] = new Pair[n];
for(int i=0;i<n;i++){
String [] in = buff.readLine().split(" ");
int x = Integer.parseInt(in[0]), y = Integer.parseInt(in[1]);
p[i] = new <Integer>Pair(x,y);
}
Arrays.sort(p, new Comparator<Pair<Integer>>(){
public int compare(Pair<Integer> p1, Pair<Integer> p2){
if(p1.x == p2.x)return p1.y - p2.y;
else return p1.x - p2.x;
}
});
long dp[] = new long[n];
dp[n-1] = 1;
for(int i=n-2;i>=0;i--)
{
int idx = search(p,p[i].y,i,n-1);
dp[i] = 1+dp[i+1];
if(idx != -1)dp[i]=dp[i]+dp[idx];
}
String res = (dp[0]%mod)+"";
while(res.length()<8)res = '0'+res;
System.out.println(res);
}
}
}
Your code is able to exceed a long type scope. You should perform your calculation with more frequent casting to the [0, mod) range. This should be enough to fix your issue and solve this Spoj's problem:
for(int i=n-2;i>=0;i--)
{
int idx = search(p,p[i].y,i,n-1);
dp[i] = 1+dp[i+1]%mod;
if(idx != -1)dp[i]=(dp[i]%mod+dp[idx]%mod)%mod;
}

Implementing RSA algorithm

I had the task to implement RSA algorithm, I read about it in Cormen's book and got most of information from there. I thought it worked good until I faced large p and q primes. For numbers about 250 and lower encryption and decryption works good, however if they are larger, modular exponentation returns negative numbers, which doesn't make sense.
I know that encrypted number can't be larger than n. I read that I can also compute inverse modulo by using extended GCD algorithm and taking x as that value, but when I tried calling extendedEuclid(phi, e)[1] it returned different values than function in RSA class. How can I fix it ?
Here is code for all needed components to compute keys.
Euclid Algorithm
public class Euclid {
public static int euclid(int a, int b) {
if (a < b) {
int tmp = a;
a = b;
b = tmp;
}
if (b == 0) {
return a;
} else {
return euclid(b, a % b);
}
}
public static int[] extendedEuclid(int a, int b) {
if (a < b) {
int tmp = a;
a = b;
b = tmp;
}
if (b == 0) {
return new int[]{a, 1, 0};
} else {
int vals[] = extendedEuclid(b, a % b);
int d = vals[0];
int x = vals[2];
int y = vals[1] - (int) Math.floor(a / b) * vals[2];
return new int[]{d, x, y};
}
}
}
Modular Exponentation
public class Modular {
public static int modularExponentation(int a, int b, int n) {
int c = 0;
int d = 1;
String binaryString = Integer.toBinaryString(b);
for (int i = 0; i < binaryString.length(); i++) {
c = 2 * c;
d = (d * d) % n;
if (binaryString.charAt(i) == '1') {
c = c + 1;
d = (d * a) % n;
}
}
return d;
}
}
RSA generator
public class RsaKeyGenerator {
int d;
int e;
int n;
public RsaKeyGenerator() {
int p = 827;
int q = 907;
n = p * q;
int phi = (p - 1) * (q - 1);
e = computeCoPrime(phi);
d = invMod(e, phi);
System.out.println("Public: " + e);
System.out.println("Private: " + d);
}
private static int computeCoPrime(int phi) {
int e = 2;
while (Euclid.euclid(e, phi) != 1) {
e++;
}
return e;
}
private int invMod(int a, int n) {
int a0, n0, p0, p1, q, r, t;
p0 = 0;
p1 = 1;
a0 = a;
n0 = n;
q = n0 / a0;
r = n0 % a0;
while (r > 0) {
t = p0 - q * p1;
if (t >= 0) {
t = t % n;
} else {
t = n - ((-t) % n);
}
p0 = p1;
p1 = t;
n0 = a0;
a0 = r;
q = n0 / a0;
r = n0 % a0;
}
return p1;
}
public int encrypt(int num) {
return Modular.modularExponentation(num, e, n);
}
public int decrypt(int cipher) {
return Modular.modularExponentation(cipher, d, n);
}
public static void main(String[] args) {
RsaKeyGenerator rsa = new RsaKeyGenerator();
int cip = rsa.encrypt(1343);
System.out.println(cip);
System.out.println(rsa.decrypt(cip));
}
}
The problem you're facing is integer overflow so if you're trying to store a number higher than 2^31 -1 in a signed integer which just isn't possible. So what ends up happening when you hit that limit is that the number wraps around to -2^31 -1.
What you want to do is look into the BigInteger class which will let you store much bigger numbers and should work fine.
The integer overflow happens at this line in the ModularExponentiation class:
d = (d * a) % n;

LCM (lowest common multiple) in Java

I need help with this loop. One of my course assignments is to make a LCM program.
Sample output:
(8,12) LCM is 24
(4,3) LCM is 12
(5,10,20) LCM is 20
(18,24,52) LCM is 936
(12,10,26) LCM is 780
(99,63,24) LCM is 5544
(62,16,24) LCM is 1488
I have this so far for 2 numbers but I'm not sure how to do 3 numbers. We're supposed to use methods on other classes so this is what I have for the LCM class.
public class LCM {
private int n, x, s = 1, t = 1;
public LCM()
{
n = 0;
x = 0;
s = 1;
t = 1;
}
public int lcmFind(int i, int y) {
for (n = 1;; n++) {
s = i * n;
for (x = 1; t < s; x++) {
t = y * x;
}
if (s == t)
break;
}
return (s);
}
}
If you want to get LCM of 3+ numbers you can use your method lcmFind in following way:
int a = 2;
int b = 3;
int c = 5;
LCM l = new LCM();
int lcm = l.lcmFind(l.lcmFind(a, b), c);
Reccomendations:
Make n,x, s and t variables local in lcmFind. Because you need them ONLY in lcmFind method and you need to reset their values in every invocation of lcmFind.
Make your lcmFind method static. You don't need to instantiate new object in order to calc lcm. This way you can use it like LCM.lcmFind(3,4), or even better rename method and use something like LCM.find(3,4).
EDIT
If you need to make method that takes variable number of argument you should check varargs. So you'll get something like:
public int lcmFind(int.. args) {
// args is actually array of ints.
// calculate lcm of all values in array.
// usage: lcmFind(1,4) or lcmFind(1,5,6,3)
}
You can use your first version of lcmFind that takes 2 arguments and calculate lcm of many values using it.
EDIT 2
If you need only 2 and 3-args version of lcmFind than you can just add 3-arg version:
public int lcmFind(int a, int b, int c) {
return lcmFind(lcmFind(a, b), c);
}
I found this link and I guess this is most simple and clean solution:
/**
* Calculate Lowest Common Multiplier
*/
public static int LCM(int a, int b) {
return (a * b) / GCF(a, b);
}
/**
* Calculate Greatest Common Factor
*/
public static int GCF(int a, int b) {
if (b == 0) {
return a;
} else {
return (GCF(b, a % b));
}
}
try
public int lcm(int... a) {
for (int m = 1;; m++) {
int n = a.length;
for (int i : a) {
if (m % i != 0) {
break;
}
if (--n == 0) {
return m;
}
}
}
}
public static int gcd(int a, int b){
return (b == 0) ? a : gcd(b, a % b);
}
public static int gcd(int... args){
int r = args[0];
int i = 0;
while(i < args.length - 1)
r = gcd(r,args[++i]);
return r;
}
public static int lcm(int a, int b){
return a * b / gcd(a,b);
}
public static int lcm(int... args){
int r = args[0];
int i = 0;
while(i < args.length - 1)
r = lcm(r,args[++i]);
return r;
}
static int getLCM(int a,int b)
{
int x;
int y;
if(a<b)
{
x=a;
y=b;
}
else
{
x=b;
y=a;
}
int i=1;
while(true)
{
int x1=x*i;
int y1=y*i;
for(int j=1;j<=i;j++)
{
if(x1==y*j)
{
return x1;
}
}
i++;
}
}
I think you have the answer already, since it's an old post. still posting my answer. Below is the code to find the LCM for an array:
import java.util.Arrays;
import java.util.Scanner;
public class ArrayEqualAmz {
static int lcm =1;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int [] arr = new int[n];
for(int i=0; i<n; i++){
arr[i] = sc.nextInt();
}
System.out.println("lcm = "+lcm(arr));
}
// find the factor
public static int divisor(int x[]){
Arrays.sort(x);
int num=0;
for(int i=x.length-1; i>=0; i--){
if(x[i] != 1 )
num=x[i];
}
for(int j=2; j<=num; j++){
if(num%j==0){
return j;}
}
return num;
}
//finding the lcm
public static int lcm(int arr[]){
while(true){
int j = divisor(arr);
if(j==0){break;}
lcm = lcm*j;
for(int i=0; i<arr.length; i++){
if(arr[i]%j==0){
arr[i] = arr[i]/j;}
System.out.print(arr[i]+",");
}
System.out.println( " factor= "+lcm);
return lcm(arr);
}
return lcm;
}
}
Try this
int n1 = 72, n2 = 120, lcm;
// maximum number between n1 and n2 is stored in lcm
lcm = (n1 > n2) ? n1 : n2;
// Always true
while(true)
{
if( lcm % n1 == 0 && lcm % n2 == 0 )
{
System.out.printf("The LCM of %d and %d is %d.", n1, n2, lcm);
break;
}
++lcm;
}
You can re use the same function written for lcm of two numbers. Just pass one of the arguments as follows:
The function code can be like this:
public static int lcm(int num1,int num2) {
boolean flag = false;
int lcm = 0;
for(int i= 1;!flag; i++){
flag = (num1 < num2)?(num2*i)%num1==0:(num1*i)%num2==0;
lcm = num1<num2?num2*i:num1*i;
}
return lcm;
}
Call the function like this:
public static void main(String[] args) {
System.out.println("lcm "+lcm(lcm(20,80),40));
}

Categories

Resources