I want to optimize this program. Currently my program is working slow because functions in the program are very much dependent on other functions in the program. What is the best way to optimize this?
public class MyClass {
public static void main(String args[]) {
int[] testValues = {3, 5, 10};
for (int i = 0; i < testValues.length; ++i) {
System.out.println(first(testValues[i]));
}
}
public static int first(int a) {
int b;
if (a <= 1) {
if (a == 1) {
b = convertOne(a);
} else {
b = convertTwo(a - 1);
}
} else {
return next(a);
}
return b;
}
public static int convertOne(int c) {
return++c;
}
public static int convertTwo(int d) {
int i = 1;
for (i = d * 11; i > d; i--) {
i--;
}
return i;
}
public static int next(int e) {
int container = first(e - 1);
return container + first(e - 2);
}
}
As I suspected, this is some kind of joke or code-golf puzzle. The function is a kind of Fibonacci function with -11 and 2 as the first terms.
The first method refactors to:
public static int first(int a) {
if (a <= 0) {
return (a - 1) * 11;
}
if (a == 1) {
return 2;
}
int n0 = -11;
int n1 = 2;
for (int i = 2; i <= a; i++) {
int t = n0 + n1;
n0 = n1;
n1 = t;
}
return n1;
}
All the rest is junk, or more likely, deliberate obfuscation.
1) One golden rule is; try to avoid Nesting as much as possible.
if (a <= 1) {
if (a == 1) {
b = convertOne(a);
} else {
b = convertTwo(a - 1);
}
} else {
return next(a);
}
2) You have used i-- twice, if its required do it like i-=2 in a loop.
public static int convertTwo(int d) {
int i = 1;
for (i = d * 11; i > d; i--) {
i--;
}
return i;
}
3) Following code is executing inadequate logic.
if (a <= 1) {
if (a == 1) {
b = convertOne(a);
} else {
b = convertTwo(a - 1);
}// this else is executing for cases < 1, but logic of "convertTwo(a - 1)" is ambiguous, try dry running it for -1
} else {
return next(a);
}
4) Logic of following code also does not need to be in function
public static int convertOne(int c) {
return ++c;
}
5) Functions are used to perform single reusable operation. In your next(int e) function you are doing nothing single. Do this in the first(int a) method.
Related
How I find among all pairs a and b with a "least common multiple" LCM(a,b) = 498960 and a "greatest common divisor" GDM(a, b) = 12 a pair with minimum sum a + b?
I solved this with O(n^2) time:
public class FindLcmAndGcdClass {
private int findGcd(int a, int b) {
if (a % b == 0) {
return b;
}
return findGcd(b, a % b);
}
private int findLcm(int a, int b, int gcd) {
return (a * b) / gcd;
}
private void run() {
int minSum = Integer.MAX_VALUE;
int foundNumberOne = 0;
int foundNumberTwo = 0;
for (int i = 12; i <= 498960; i += 12) {
for (int j = i; j <= 498960; j += 12) {
int gcd;
if (i < j) {
gcd = findGcd(j, i);
} else {
gcd = findGcd(i, j);
}
int lcm = findLcm(i, j, gcd);
if (gcd == 12 && lcm == 498960 && i + j < minSum) {
minSum = i + j;
foundNumberOne = i;
foundNumberTwo = j;
}
}
}
System.out.println(minSum);
System.out.println(foundNumberOne);
System.out.println(foundNumberTwo);
}
public static void main(String[] args) {
var o = new FindLcmAndGcdClass();
o.run();
}
}
And it executes quite slowly! I guess the problem can be solved with Dynamic Programming. Can anyone help with more fast solution?
I am not sure if this question can be solved with dynamic programming, but I think of a solution with time complexity O(sqrt(LCM * GCD)).
It is well known that for any two integers a and b, LCM(a, b) * GCD(a, b) = a * b. Therefore, you can first calculate the product of the gcd and lcm, (which is 5987520 in this question). Then for all its factors under sqrt(LCM * GCD), let a be one of the factors, then b = LCM * GCD / a. Test if gcd(a, b) = the required gcd, if so calculate the sum a + b, then find the minimum among the sums, and you are done.
I have a problem, I have the correct(PART 1) and incorrect code (PART 2). I cant figure out why the incorrect code is incorrect.
the
static int sum = 0
part is the incorrect part of the code in PART 2. If that line of code is moved to the same location at PART 1. The code works.
if the range is from 10 to 20. PART 2 outputs an incorrect sum of 111. The sum should be 75. There are 3 possible combinations to get 111.
18 + 18 + correct sum
17 +19 + correct sum
16 + 20 + correct sum
Im guessing PART 2 passes through 18 + 18? but how?!
PART 1 Correct Code
ublic class SumOddRange {
public static boolean isOdd(int number){
if (number <= 0) {
return false;
}
return number % 2 != 0;
}
public static int sumOdd(int start, int end){
if ( (end < start) || (start < 0) || (end < 0) ){
return -1;
}
int sum = 0;
for (int i = start; i<=end; i++){
if (isOdd(i)){
sum +=i;
}
}
return sum;
}
PART 2 INCORRECT CODE
public class SumOddRange {
public static boolean isOdd(int number) {
if((number > 0) && (number % 2 != 0)) {
return true;
}
else {
return false;
}
}
static int startOne = 0;
static int sum = 0;
public static int sumOdd(int start, int end) {
if ((end >= start) && (end > 0) && (start > 0)) {
for (startOne = start; startOne <= end; startOne++) {
if (isOdd(startOne)) {
sum += startOne;
}
}
return sum;
} else
return -1;
}
The problem is that you are using static variables.
What does static mean?
After creating a class, you can create instances (also called objects) of this class. This is what happens, when you use a command like
SumOddRange a = new SumOddRange();
SumOddRange b = new SumOddRange();
As you probably know, there are methods and variables in a class. These methods and classes can be seperated into
Class methods and variables
Object methods and variables (object variables are most often called attributes)
This means that some methods and variables do belong to the class, so all the instances of this class share this variable or method. This is what static is used for. So if the class in the image above has a static attribute named staticAttributeName, a.staticAttributeName and b.staticAttributeName have to be the same.
If a variable isn't static, this variable is not shared by the instances. All instances have their own instance of this variable. So although their name is the same, the values saved in the variables doen't have to be the same. So if the class in the image above has a non-static attribute named attributeName, a.attributeName and b.attributeName doesn't have to be the same.
An example:
public class Add {
public static int sum = 0;
public static void addOne() {
sum = sum + 1;
}
}
public class Test {
public static void main(String[] args) {
Add a = new Add();
Add b = new Add();
a.addOne();
b.addOne();
System.out.println("a " + a.sum);
System.out.println("b " + b.sum);
}
}
As you can see, the variable sum is static. This means that a.sum and b.sum are the same. In the main-method, we are calling the method addOne two times, so the two outputs are "a 2" and "b 2".
public class Add {
public int sum = 0;
public void addOne() {
sum = sum + 1;
}
}
public class Test {
public static void main(String[] args) {
Add a = new Add();
Add b = new Add();
a.addOne();
b.addOne();
b.addOne();
System.out.println("a " + a.sum);
System.out.println("b " + b.sum);
}
}
We now have a non-static variable sum in the class Add.
a: We are calling the method addOne one time, so the first output is "a 1".
b: The method addOne is called two times, so the output is "b 2".
Solving the problem
public class Test {
public static void main(String[] args) {
SumOddRange s = new SumOddRange(); //Using class given in PART2 of question
SumOddRange t = new SumOddRange();
System.out.println(s.sumOdd(10,20));
System.out.println(s.sumOdd(10,20));
}
}
This class produces the outputs 75 and 150. This is the case, because s and t use the same variable sum, so the first time, the sum is correct, but the second calculation returns 75+sumOdd(10,20) = 75+75 = 150 as the result.
As we now know, the main problem is that the variable(s) are static. This brings up the idea to just use non-static variables, which is the best idea here:
public class SumOddRange {
public boolean isOdd(int number) {
if((number > 0) && (number % 2 != 0)) {
return true;
}
else {
return false;
}
}
int startOne = 0;
int sum = 0;
public int sumOdd(int start, int end) {
sum = 0;
if ((end >= start) && (end > 0) && (start > 0)) {
for (startOne = start; startOne <= end; startOne++) {
if (isOdd(startOne)) {
sum += startOne;
}
}
return sum;
} else {
return -1;
}
}
}
Another option is to just reset the variable sum before actually calculating the sum. The disadvantage of this approach is that you will not be able to access earlier results anymore:
static int startOne = 0;
static int sum = 0;
public static int sumOdd(int start, int end) {
sum = 0;
if ((end >= start) && (end > 0) && (start > 0)) {
for (startOne = start; startOne <= end; startOne++) {
if (isOdd(startOne)) {
sum += startOne;
}
}
return sum;
} else {
return -1;
}
}
Here is my implementation of the fibonacci sequence using java
/**
* Returns nth fibonacci number
*/
public class fib {
public static void main(String[] args){
System.out.println(fibonacci(12));
}
public static int fibonacci(int n) {
if (n == 0){
return 0;
} else if (n == 1){
return 1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}
But visualization of this method using recursion made me think it would be a lot faster.
Here is a visualization of fib(5). http://imgur.com/a/2Rgxs
But this got my thinking, notice at the bottom when we bubble up from the bottom of the recursive path we calculate fib(2), fib(3) and fib(4) but then we recalculate fib(3) on the very top right branch. So I was thinking when we are bubbling back up why not save fib(3) calculated from the left branch so we don't do any calculations on the right branch like my method currently does, like a hashtable while coming back up.
My question is, how do I implement this idea?
When you want to add the HashMap and stay with your original approach, try this:
static HashMap<Integer, Integer> values = new HashMap<Integer, Integer>();
public static void main(String[] args){
values.put(0, 0);
values.put(1, 1);
System.out.println(fibonacci(12));
}
public static int fibonacci(int n) {
if (values.containsKey(n)){
return values.get(n);
} else {
int left = values.containsKey(n - 1) ? values.get(n - 1) : fibonacci(n - 1);
values.put(n - 1, left);
int right = values.containsKey(n - 2) ? values.get(n - 2) : fibonacci(n - 2);
values.put(n - 2, right);
return left + right;
}
}
This approach could be very fast if you call it more often because the fibonacci results are already stored in the values (for sure this could also be done with other approaches):
public static void main(String[] args){
values.put(0, 0);
values.put(1, 1);
System.out.println(fibonacci(12));
System.out.println(fibonacci(11));
System.out.println(fibonacci(10));
}
For a fast calculation, you do not need recursion at all - just shift the intermediate results
public static int fibonacci(int n) {
if (n == 0) {
return 0;
} else {
int npp = 0; // pre-previous number
int np = 1; // previouse number
int r = 1; // current number, eventually the result
for (int i = 2; i <= n; i++) {
r = np + npp;
npp = np;
np = r;
}
return r;
}
}
In order to avoid repeated calculations, you can use dynamic programming. BTW, this is not a memory optimized solution, but it can be faster than the recursive one.
public static int fibonacci(int n)
{
int f[] = new int[n+1];
for (int i = 0; i <= n; i++) {
if(i == 0 || i == 1) {
f[i] = i;
}
else {
f[i] = f[i-1] + f[i-2];
}
}
return f[n];
}
Guys I am doing polynomial evaluation and using algorithms such as Naive, Horner and FFT
now there is one statement in my question that states.
Run a variation of the naïve algorithm, where the exponentiation
is performed by repeated squaring, a decrease-by-half algorithm
I do not understand it, My current Naive algorithm is:
public Complex naive(Polynomial poly, Complex x) {
Complex p = new Complex();
for (int i = poly.getCoef().length - 1; i >= 0; i--) {
Complex power = new Complex(1, 0);
for (int j = 1; j <= i; j++) {
power = power.multiply(x);
}
p = p.add(poly.getCoef()[i].multiply(power));
multiplyCountNaive++;
}
return p;
}
Kindly explain what needs to be modified.
Thank you
I got it it was supposed to be like this
public Complex naive2(Polynomial poly, Complex x) {
Complex p = new Complex();
for (int i = poly.getCoef().length - 1; i >= 0; i--) {
p = p.add(poly.getCoef()[i].multiply(expo(x, i)));
multiplyCountNaive2++;
}
return p;
}
private Complex expo(Complex a, int b) {
if (b == 0) {
return new Complex(1, 0);
} else if (b == 1) {
return a;
}
if (b % 2 == 0) {
return expo(a.multiply(a), b / 2);
} else {
return a.multiply(expo(a.multiply(a), (b - 1) / 2));
}
}
public class Problem3 {
public static void main (String args[]) {
System.out.print(primeMod(60085147514L));
}
public static double primeMod(long d) {
long max = 0;
int count = 0;
for (long i = 2; i < d; i++) {
if (d % i == 0) {
boolean isPrime = primeCounter(i);
if(isPrime == true) {
max = i;
System.out.println(max);
}
} else {
max = max;
}
}
return max;
}
public static boolean primeCounter(long x) {
int count = 0;
for (int s = 1; s <= x; s++) {
if (x % s == 0) {
count++;
}
}
if (count == 2) {
return true;
} else {
return false;
}
}
}
My program works for smaller numbers but it Throws an Arthmetic Exception for Divide by 0 when its not dividing by zero.please dont give me the answer,just wanna understand it and improve my skills
thank you
My guess would be that s is overflowing, leading eventually to a divide by zero. Make s a long instead.