I'm having some trouble figuring this out. I have a while statement with an expression that should be evaluated on each loop. I feel like I am thinking about this wrong.
What I'm trying to do is loop through the expression experience >= experienceCap until it is false. The experienceCap is set correctly on each loop, but the while expression values never change even though the values actually do change on each loop.
public void refreshExperience() {
int experience = getExperience(); //10
int experienceCap = getExperienceCap(); //100
while (experience >= experienceCap) {
newExperienceCap();
refreshExperience();
}
}
This results in some log output like:
experience: 10
experienceCap: 100
experience: 10
experienceCap: 450
experience: 10
experienceCap: 1120
experience: 10
experienceCap: 2337
And an inevitable crash.
I would very much appreciate any input, thank you!
The loop values are not being updated, so it is confusing that in your output it shows experienceCap increases. Without seeing all the code i can only guess that the values you are logging are not the ones declared in refreshExperiece.
public class Test {
int experience = 10;
int experienceCap = 100;
public void refreshExperience() {
while (experience <= experienceCap) {
experience = getExperience();
experienceCap = getExperienceCap();
}
}
The above code shows experience and experienceCap being initialized to 10 and 100 respectively. Inside the loop these values are updated with the returned value from getExperience and getExperienceCap respectively. How you are updating experience and experienceCap is up to you but this is a simple example:
private int getExperience() {
return experience + 5;
}
private int getExperienceCap() {
return experienceCap - 10;
}
This is a typical value vs reference problem.
You seem to expect that int experience is a reference, but it is not.
Related
I'm trying to write a Java program to calculate the square root of an integer x, without using in-built functions like Math.pow() . This is the approach I tried -
class Solution {
public int mySqrt(int x) {
if(x==0 || x==1)
return x;
// if(x>=2147395600)
// return 46340;
int i;
for(i=1 ; i*i<=x ; i++) {}
return i-1;
}
}
Without the commented part, I start getting errors if x is in the range 2147395600 <= x <= 2^31-1 (which is the upper limit of an int's value range in Java). For instance, for the input x=2147395600, the expected output is 46340 but the actual output is 289398. Why is this happening? Thanks to all in advance.
PS - I am aware there are other (better) methods to solve this problem, but I'd really like to know why this code behaves this way.
Since 46340 * 46340 = 2147395600, when i=46340, x=2147395600 and you reach the condition i*i<=x it evaluates to true since 2147395600 = 2147395600. So the loop counter will incremnet by 1 and in the next iteration we will get i=46341 and i * i will cause an overflow - 46341*46341 = -2147479015.
The loop condition will still be true, since -2147479015 <= 2147395600, and the loop will not stop.
You can replace the <= with =, and check for edge cases that may occur now.
I am trying to get the hour component of an object, which is an int, and increment it by 1. So 5 would be 6. I tried to do clocks[i].getHour() = clocks[i].getHour()+1, but this was not allowed and would say I need a variable on the left.
public void daylightSavingsTime(Clock[] clocks) {
for(int i = 0; i <clocks.length; i++) {
int a = clocks[i].getHour()+1;
}
Probably you'd need to write/use a setter function setHour(int newHour) ,
and then you could do something along the lines of:
public void daylightSavingsTime(Clock[] clocks) {
for(int i = 0; i <clocks.length; i++) {
clocks[i].setHour(clocks[i].getHour()+1);
}
Explanation of your statement.
clocks[i].getHour() = clocks[i].getHour()+1;
//To simplify
Clock clock = clocks[i];
clock.getHour() = clock.getHour()+1; //thing you are trying to do.
Suppose clock hours field is 6. What the compiler will do. When it sees clock.getHours() it knows the value is 6. To compiler your statement looks like
6 = 6+1
Obviously no language wants to change the value of 6 to 7
But int a = clocks[i].getHour()+1; is a valid statement as a will be assigned to 7.
To increment the hour in clock just use just do
clock.hours = clocks[i].getHour()+1;
but now hours property is public and can be easily abused like clock.hours = 100; but we may not want it to be 100, but to increase the date as 100 > 24. So use set method like clock.setHour(a+1) this method will internally handle the hour like
Class Clock{
// like that.. it may be different..
void setHour(int hour){
this.day += hour/24;
this.hour += hour%24;
}
}
Like i sad , i am working on Euler problem 12 https://projecteuler.net/problem=12 , i believe that this program will give the correct answer but is too slow , i tried to wait it out but even after 9min it still cant finish it. How can i modify it to run faster ?
package highlydivisibletriangularnumber_ep12;
public class HighlyDivisibleTriangularNumber_EP12 {
public static void findTriangular(int triangularNum){
triangularValue = triangularNum * (triangularNum + 1)/2;
}
static long triangularValue = 0l;
public static void main(String[] args) {
long n = 1l;
int counter = 0;
int i = 1;
while(true){
findTriangular(i);
while(n<=triangularValue){
if(triangularValue%n==0){
counter++;
}
n++;
}
if(counter>500){
break;
}else{
counter = 0;
}
n=1;
i++;
}
System.out.println(triangularValue);
}
}
Just two simple tricks:
When x%n == 0, then also x%m == 0 with m = x/n. This way you need to consider only n <= Math.ceil(sqrt(x)), which is a huge speed up. With each divisor smaller than the square root, you get another one for free. Beware of the case of equality. The speed gain is huge.
As your x is a product of two numbers i and i+1, you can generate all its divisors as product of the divisors of i and i+1. What makes it more complicated is the fact that in general, the same product can be created using different factors. Can it happen here? Do you need to generate products or can you just count them? Again, the speed gain is huge.
You could use prime factorization, but I'm sure, these tricks alone are sufficient.
It appears to me that your algorithm is a bit too brute-force, and due to this, will consume an enormous amount of cpu time regardless of how you might rearrange it.
What is needed is an algorithm that implements a formula that calculates at least part of the solution, instead of brute-forcing the whole thing.
If you get stuck, you can use your favorite search engine to find a number of solutions, with varying degrees of efficiency.
class LargestPrimeFactor{
public static void main(String args[]){
long p=0L;
long n=600851475143L;
for(long i=2L;i<(n/2);i++){
if((BigInteger.valueOf(i)).isProbablePrime(1)){
if(n%i==0){
p=i;
}
}
}
System.out.println(p);
}
}
It's problem 3 from Project Euler. I compiled it and no errors showed up. But am not getting any output. Whats the reason?
It is working (just add a print method inside the loop to check i for example).
You are currently using the Brute-Force method:
http://www.mathblog.dk/project-euler-problem-3/
If you visit the link the guy tells you an alternative solution for it.
The problem I see without having much knowledge about this is
that the operations you currently do are way too many.
You got the value "600851475143" stored in a long datatype and you try to
reach the half (300425737571,5) using the int i (counter in your for-loop).
https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#MAX_VALUE
This tells us: "A constant holding the maximum value an int can have,
2^(31)-1." = 2147483647
This is just 0,00715 (0,7%) of what you actually need.
So this leads us to an "Overflow".
Think of using the alternative method (first link)
and change the counter of your for-loop to type "long".
int maximum value is 2147483647 which is smaller than 600851475143/2
when index i reaches max value it will wrap around and start with negative number (-2147483648)
you should make your index i a long value
You have an infinite loop on the second for iteration you can only see it when you add logging before the end of the loop. It's not because it's not printing the value, when you stare at the console the iterator is still circling through 6857.
Try running the code with extra logging below.
public static void main(String args[]) {
int p = 0;
long n = 600851475143L;
for (int i = 2; i < (n / 2); i++) {
if ((BigInteger.valueOf(i)).isProbablePrime(1)) {
if (BigInteger.valueOf(n % i).compareTo(BigInteger.valueOf(0)) == 0) {
p = i;
System.out.println("Check == true Iteration"+p);
}
System.err.println("Second iterator"+p);
}
}
System.out.println("Final Value of P: "+p);
}
EDITED
The int data type can store values upto 2,147,483,647. To store numbers beyond that, use long.
long n = 600851475143L;
Not 600851475143 L, as that one space before L causes the system to not register it.
Also, int i in the for loop should be long i.
This is my first UVa submission so I had a few problems in the way. The biggest hurdle that took my time so far was probably getting all the formats correctly (I know, shouldn't have been too hard but I kept getting runtime error without knowing what that actually meant in this context). I did finally get past that runtime error, but I still get "Wrong answer."
Listed below are the things I've done for this problem. I've been working on this for the last few hours, and I honestly thought about just dropping it altogether, but this will bother me so much, so this is my last hope.
Things I've done:
considered int overflow so changed to long at applicable places
got the whole list (1-1000000) in the beginning through memorization for computation time
submitted to uDebug. Critical input and Random input both show matching output.
submitted to to UVa online judge and got "Wrong Answer" with 0.13~0.15 runtime.
Things I'm not too sure about:
I think I read that UVa doesn't want its classes to be public. So I left mine as class Main instead of the usual public class Main. Someone from another place mentioned that it should be the latter. Not sure which one UVa online judge likes.
input. I used BufferedReader(new InputStreaReader (System.in)) for this. Also not sure if UVa online judge likes this.
I thought my algorithm was correct but because of "Wrong answer," I'm not so sure. If my code is hard to read, I'll try to describe what I did after the code.
Here is my code:
class Main {
public static int mainMethod(long i, int c, List<Integer> l) {
if (i==1)
return ++c;
else if (i%2==0) {
if (i<1000000&&l.get((int)i)!=null)
return l.get((int)i)+c;
else {
c++;
return mainMethod(i/2, c, l);
}
}
else {
if (i<1000000&&l.get((int)i)!=null)
return l.get((int)i)+c;
else {
c++;
return mainMethod(i*3+1, c, l);
}
}
}
public static int countMax(int x, int y, List<Integer> l) {
int max=0;
if (x>y) {
int temp = x;
x= y;
y = temp;
}
for (int i=x; i<=y; i++) {
if (l.get(i)>max)
max = l.get(i);
}
return max;
}
public static void main(String[] args) {
List<Integer> fixed = Arrays.asList(new Integer[1000000]);
for (long i=1; i<1000000; i++) {
fixed.set((int)i, mainMethod(i,0,fixed));
}
String s;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while ((s = br.readLine())!=null) {
int x = -1;
int y = -1;
for (String split : s.split("\\s+")) {
if (!split.equals("\\s+") && x==-1) {
x = Integer.parseInt(split);
} else if (!split.equals("\\s+") && x!=-1) {
y = Integer.parseInt(split);
}
}
if (x!=-1&&y!=-1)
System.out.println(Integer.toString(x) + " " + Integer.toString(y) + " " + Integer.toString(countMax(x,y,fixed)));
}
} catch (IOException e) {
} catch (NumberFormatException e) {
}
}
}
I apologize for generic names for methods and variables. mainMethod deals with memorization and creating the initial list. countMax deals with the input from the problem (15 20) and finding the max length using the list. The for loop within the main method deals with potential empty lines and too many spaces.
So my (if not so obvious) question is, what is wrong with my code? Again, this worked perfectly fine on uDebug's Random Input and Critical Input. For some reason, however, UVa online judge says that it's wrong. I'm just clueless as to where it is. I'm a student so I'm still learning. Thank you!
Haven't spotted your error yet, but a few things that may make it easier to spot.
First off:
int goes to 2^31, so declaring i in mainMethod to be long is unnecessary. It also states in the problem specification that no operation will overflow an int, doesn't it? Getting rid of the extraneous longs (and (int) casts) would make it easier to comprehend.
Second:
It's probably clearer to make your recursive call with c + 1 than ++c or doing c++ before it. Those have side effects, and it makes it harder to follow what you're doing (because if you're incrementing c, there must be a reason, right?) What you're writing is technically correct, but it's unidiomatic enough that it distracts.
Third:
So, am I missing something, or are you never actually setting any of the values in the List in your memoization function? If I'm not blind (which is a possibility) that would certainly keep it from passing as-is. Wait, no, definitely blind - you're doing it in the loop that calls it. With this sort of function, I'd expect it to mutate the List in the function. When you call it for i=1, you're computing i=4 (3 * 1 + 1) - you may as well save it.