I'm currently working on one of my assignments, and am looking for some help with the logic for one of my functions.
First off I have a array of numbers to be categorized, then a number interval, this number determines in which position each of the numbers being plotted goes into array2.
ie.
int interval = 2;
for(int i = 0; i < array1.length; i++) {
if((array1[i] > 0) && (array1[i] < interval)) {
array2[0]++;
}
}
However, the number from array1 is 3. I would then need another if statement like so:
...
}else if((array1[i] > 2) && (array1[i] < interval * 2)) {
array2[1]++;
}else if((array1[i] >
As you can start to see the problem with this is that I would need to continue for an infinite range of numbers. So my question is what is an easier way of achieving this goal? Or is there already a library which I can utilize to do so?
I'm sorry if I didn't make this clear enough, also I would prefer if code wasn't given to me. I would appreciate if someone would be able to tell me a more effective way about going about this, thanks in advance!
EDIT:
Assuming that the interval is set to 2, and the numbers from array1 are between 0 and 10, I would need to create a code that would do such:
2 < numFromArray1 > 0 == array2[0]++
4 < numFromArray1 > 2 == array2[1]++
6 < numFromArray1 > 4 == array2[2]++
8 < numFromArray1 > 6 == array2[3]++
10 < numFromArray1 > 8 == array2[4]++
However, the numbers from array1 can be positive or negative, whole or decimal.
Use a nested loop. Obviously it's not infinitely many possibilities for interval because array2 has a fixed size. So if you loop through all the cells in array2, and then do some math to figure out what your conditions need to be... I won't give complete code (you asked me not to, but it would look something like:
for ( ... ) {
for ( ... ) {
if (array1[i] > /* do some math here */ && ... ) {
array2[/* figure out what this should be too */]++;
}
}
}
Hopefully you can figure it out from this.
By the way, if you aren't required to use an array for array2, consider learning about LinkedList<?>for a data structure that can grow in size as you need it to.
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/LinkedList.html
http://www.dreamincode.net/forums/topic/143089-linked-list-tutorial/
Assuming I understood the question correct, and the interval would be 3, than occurrences of 0, 1 and 2 would increase array2[0], occurences of 3, 4 and 5 would increase array2[1] and so on, this would be a solution:
EDIT sorry, you did not want to see code. I can repost it, if you want. Think about a real easy way to determine which category a number will be in. I'll try to give a hint.
Interval = 3;
0,1,2 -> category 0
3,4,5 -> category 1
6,7,8 -> category 2
Once you know the category, it is easy to increment the desired number in array2.
It would look something like that:
for(int i = 0; i < array1.length; i++) {
int category = // determine category here
// increase correct position of array2
}
After some dicussion, here is my code:
for(int i = 0; i < array1.length; i++) {
int category = array1[i] / interval;
array2[category]++;
}
My solution won't work for negative numbers. Also it is not specified how to handle them
Here's what you can do to consider all cases: -
First find out what is the maximum value in your array: - array1.
Your range should be 0 to maxValueInArray1
Then inside your outer for loop, you can have another, that will run from 0 to the (maximum value) / 2. Because, you don't want to check for maximum value * 2 in your interval
And then for each value, you can check for the range, if it is in that range, use array2[j]
For E.G: -
for (...) // Outer loop {
for (int j = 0; j <= maximumValueinArray1 / 2; j++) {
// Make a range for each `j`
// use the `array2[j]` to put value in appropriate range.
}
}
In your inner loop, you might check for this condition, based on following reasoning: -
For interval = 2, and say maximumValueinArray1 is max, your range looks like: -
0 * interval ----- (1 * interval) --> in `array2[0]` (0 to 2)
1 * interval ----- (2 * interval) --> in `array2[1]` (2 to 4)
2 * interval ----- (3 * interval) --> in `array2[2]` (4 to 6)
and so on.
((max / 2) - 1) * interval ----- (max / 2) * interval (`max - 2` to max)
So, try relating these conditions, with the inner loop I posted, and your problem will be solved.
I'm not sure what exactly you're trying to do, but from your code snippets, I can come up with this inner for loop:
//OUTDATED CODE - please see code block in EDIT below
//for(int i = 0; i < array1.length; i++) {
// for (int j = 0; j < 100000; j++) { //or Integer.MAXVALUE or whatever
// if ((array1[i] > (j*2)) && (array1[i] < interval * ((j*2)==0?2:(j*2)) )) {
// array2[j]++;
// }
// }
//}
EDIT: Owing to your recent edit, this is more suitable and you don't have to run an inner loop!:
Loop through array1
For each element in array1, find array2 index by taking floor of element / interval
Add 1 to array2 element at found index.
DON'T LOOK AT THE CODE BELOW =)
for(int i = 0; i < array1.length; i++) {
int index = Math.floor(array1[i] / interval);
array2[index]++;
//the rest are actually not necessary as you just need to get the index
//and the element will be within range, left inclusive (lower <= value < upper)
//int lower_range = Math.floor(array1[i] / interval) * interval;
// //or int lower_range = index * interval;
//int upper_range = Math.ceil(array1[i] / interval) * interval;
//if ((array1[i] > lower_range) && (array1[i] < upper_range)) {
// array2[index]++;
//}
}
The relationships and pattern are hard to figure out. My attempt in interpreting what you want:
How about something like:
if ( array1[i] < interval * (interval - 2) ) {
array2[interval-2]++;
}
Related
for(i=0; i<array.length; i++){
sum = 4 * 5;
}
What I'm trying to do is add ((array.length - 1) - i) 0's to the value of sum. For this example assume array length is 3. sum equals 20. So for the first iteration of the loop i want to add ((3 - 1) - 0) 0's to the value of sum, so sum would be 2000. The next iteration would be ((3 - 1) - 1) 0's. so sum would equal 200 and so on. I hope what I am trying to achieve is clear.
So my questions are:
Is it possible to just shift an int to add extra digits? My search thus far suggests it is not.
If not, how can i achieve my desired goal?
Thankyou for reading my question and any help would be greatly apreciated.
You can just multiply it by 10 however many times.
200 * 10 = 2000
etc
So in your case, you'd have to use a for loop until the end of the array and multiply sum every iteration. Be careful though, because the max value of an int is 2^31, so it of surpasses that, it will roll back to 0
You can add n zeroes to the end of a number, sum by multiplying sum by 10 * n.
int sum = 20;
for (int i = 0; i < ary.length; ++i) {
int zeroesToAdd = ary.length - 1 - i
sum *= (zeroesToAdd > 0) ? zeroesToAdd * 10 : 1
}
System.out.println("Sum after loop: " + sum);
for(int i=array.length; i>0; i--){
sum = 20;
for(int j=0; j < (i - 1); j++)
{
sum *= 10;
}
}
Use inner loop to multiply by 10 the number of times i is for that iteration. You would need to reset sum in your outer loop each time.
You will want to check your for-loop condition: i>array.length. Since i starts at 0, this loop will not run unless the array's length is also 0 (an empty array). The correct condition is i < array.length.
This "shift" you want can be achieved by creating a temporary variable inside the loop that is equal to the sum times 10i. In Java's Math library, there is a pow(a,b) function that computes ab. With that in mind, what you want is something like this:
int oldSum = 4 * 5;
for (int i = 0; i < array.length; i++) {
int newSum = oldSum * Math.pow(10,i);
}
Multiply by 10 instead, and use < (not >) like
int sum = 20;
int[] array = { 1, 2, 3 };
for (int i = 0; i < array.length; i++) {
int powSum = sum;
for (int j = array.length - 1; j > i; j--) {
powSum *= 10;
}
System.out.println(powSum);
}
Output is (as requested)
2000
200
20
For array of length = n; you will end up adding (n - 1) + (n - 2) + ... + 2 + 1 + 0 zeros for i = 0, 1, ... n-2, n-1 respectively.
Therefore, number of zeros to append (z) = n * (n-1) / 2
So the answer is sum * (10 ^ z)
[EDIT]
The above can be used to find the answer after N iteration. (I miss read the question)
int n = array.length;
long sum = 20;
long pow = Math.pow(10, n-1); // for i = 0
for (int i = 0; i < n; i++) {
System.out.println(sum*pow);
pow /= 10;
}
I have come across many many solutions in StackOverflow for problem 4 in project Euler. My question is not about asking again a solution to problem 4 from project Euler which is already implemented in StackOverflow. Instead, i have come across an improved solution Improved solution by ROMANIA_engineer.
I have two questions against the improved solution. Anyways I have posted the solution below, for people to look into it.
public static void main(String[] args) {
int max = -1;
for ( int i = 999 ; i >= 100 ; i--) {
if ( max >= i*999 ) {
break;
}
for (int j = 999 ; j >= i ; j-- ) {
int p = i * j;
if ( max < p && isPalindrome(p) ) {
max = p;
}
}
}
System.out.println(max > -1? max : "No palindrome found");
}
Questions
Why there is a condition (max >= i * 999) ?. What are we going to achieve, by including such an inexpensive operation?
From the below snippet,
for (int j = 999 ; j >= i ; j-- ) {
int p = i * j;
if ( max < p && isPalindrome(p) ) {
max = p;
}
}
Instead of j >= 100, it is given j >= i. I can see a lot of time is saved, however, I wanted to know the intention behind it.
To answer question 1, the reason why there is a check (max >= i * 999) is that you may have already stumbled upon a product of two 3-digit numbers that is a palindrome but greater than i * 999. Since the outer for loop starts at i = 999, once you've found a new max, there is a possibility that the new max is greater than the max possible palindrome product from the decremented i value in the next iteration. For example, if we found a palindrome product of 926 * 998 where i = 926 and j = 998 and the new max was set to this product. Note that this is just a hypothetical, I have no idea if the product is even a palindrome. Then the inner for loop finishes on the iteration i = 926. Then on the next iteration of the outer for loop, i is now 925, and since 925 * 999 is less than 926 * 998, there's no need to continue finding the max palindrome product because it's already been found. The reason is that at this point 925 * 999 is the largest possible palindrome product that can be calculated going forward.
To answer question 2, the reason for j >= i is to avoid repeating the calculation of products. For example, let's say the condition was j >= 100 instead. On the first iteration of the inner for loop when j is 999 and i is also 999. We will end up calculating, possibly, products from 999 * 999, 999 * 998, all the way to 999 * 100. However, if the inner for loop is ever reached to a point where i is now 100 and j is 999, then you'll ultimately repeat the calculation 100 * 999. Note that this is just an example, it may not even get to this point.
Problem Statement:
Find the minimum number of steps required to reach a target number x from 0 (zero), using only two operations: +1 (add 1 to the number) or *2 (multiply 2 with the number).
So here's the Logic that I came up with:
The best way is to work backwards. Start from the number you need:
Subtract 1 if the number is odd.
Divide by 2 if the number if even.
Stop when you get to zero.
For example, for 29, you get 28, 14, 7, 6, 3, 2, 1, 0.
And, here's what I have tried doing (Java 7):
kValues is an array that has the x values for which the steps are needed to be computed and stored in an array called result.
static int[] countOperationsToK(long[] kValues) {
int size = kValues.length,x,i,steps;
int result[] = new int[size];
for (i = 0; i < size; ++i)
{
steps = 0;
for (x = (int)kValues[i]; x != 0 ; ++steps)
{
if((x % 2) == 0)
x /= 2;
else x--;
}
result[i] = steps;
}
return result;
}
My Problem:
This is a Hackerrank question and I am supposed to write an efficient code. I was successful with 7/11 test cases and others were timed out. Since, it is a Hackerrank question, I can't change the function definition or the return type. That is the reason why I am converting from long to int in my for loop, in order to use % (modulus). I would like to know where I am going wrong. Is my algorithm taking too long to compute (for the number of values close to a million)? Which is obviously the case, but how do I alter my algorithm in order to pass all the test cases?
Thank you in advance :)
for (x = (int)kValues[i]; x != 0 ; ++steps)
The fact that you are casting a long to an int is very suspicious. You might get a negative number when you do that.
Say x == -2: you divide it by 2 to give -1, then subtract 1 to give -2. You'll keep doing that indefinitely.
Just define x to be a long, and remove the cast.
So, here's the working code. I had forgotten to append L while using the modulo. Silly mistake led to so much of typing. LOL!!
static int[] countOperationsToK(long[] kValues) {
int size = kValues.length,i,steps;
int result[] = new int[size];
long x;
for (i = 0; i < size; ++i)
{
steps = 0;
for (x = kValues[i]; x != 0 ; ++steps)
{
if((x % 2L) == 0)
x /= 2L;
else x -= 1L;
}
result[i] = steps;
}
return result;
}
Here is a very short version, using bit-analysis:
static int[] countOperationsToK(long... input) {
int result[] = new int[input.length];
for (int i = 0; i < input.length; i++)
if (input[i] > 0)
result[i] = Long.bitCount(input[i]) + 63 - Long.numberOfLeadingZeros(input[i]);
return result;
}
The idea here is to look at the binary number, e.g. for 29 that is 11101. There are 4 bits set, so we'd need to do +1 four times, and the highest bit position is 4, so we need to left-shift (i.e. *2) four times, for a total of 8 operations: +1, *2, +1, *2, +1, *2, *2, +1.
numberOfBits = Long.bitCount(x)
highBitNumber = floor(log2(x)) = 63 - Long.numberOfLeadingZeros(x)
The highBitNumber part doesn't work if value is zero, hence the if statement.
For input number x,
Minimum no. of Ops = (int)log2(x) + Long.BitCount(x)
I am working on an exercise where a small piece of code based on a for-loop is converted to preform the same operation with a while loop. The conversion is wrong by purpose, and looks like this:
int sum = 0;
for (int i = 0; i < 4; i++) {
if (i % 3 == 0) continue;
sum += i;
}
System.out.println(sum); // prints 3
This is converted into:
int i = 0, sum = 0;
while (i < 4) {
if (i % 3 == 0) continue;
sum += i;
i++;
}
System.out.println(sum); // will not print
In the exercise, I am asked to explain why the conversion is wrong and then fix it. My thoughts are:
With the initial value of i = 0, this will trigger continue instantly after entering the will loop, since (0 % 3 == 0) will make the if-statement true. As long as the initial value is 0, this will execute the loop, for so to skip it an endless amount of times. I tried changing the initial value of i = 1, but noe sum is printed. Then I tried to increment i before executing the if-statement, and the program now prints the sum 7. The question here is; why won't the program print if i incremented after the if statement, even if the initial value of i = 1 suggests (in my head) that program should run properly?
I made a table for each program to compare the summing.
The for-loop version:
i = 0, sum += i not preformed (continue), i++
i = 1, sum = 1, i++
i = 2, sum = 3, i++
i = 3, sum += i not preformed (continue), i++
i = 4, i < 4 false, loop stopped
The while-loop version:
i = 0, i++, sum = 1
i = 1, i++, sum = 3
i = 2, i++, sum += i not preformed (continue)
i = 3, i++, sum = 7
i = 4, i < 4 false, loop stopped
In the while-loop, sum += i is preformed once more than in the for-loop. Is this the right way to convert the for-loop into a while-loop?
int i = 0, sum = 0;
while (i < 3) {
i++;
if (i % 3 == 0) continue;
sum += i;
}
System.out.println(sum);
Your 1 is focussing on it being the initial value, but that's not the point. The point is that i is never incremented when i % 3 == 0 is true, not that 0 is the initial value. So the while loop loops forever.
Your 2 doesn't make any sense: The while version will loop forever, never summing anything.
Is this the right way to convert the for-loop into a while-loop?
No, you're incrementing i at the wrong time.
Think bout how a for loop works:
Initialization - First it sets the variables to the values in the first expression.
Test - Then it tests the values using the second expression.
Execute - If the value is true, it executes the loop body.
Increment - When the loop body is complete, it executes the third (increment) expression. Note that this is after the loop body.
Make your while loop do what the for loop is doing. (I'm intentionally not doing that for you; this is a learning exercise. I'll note that the best way to convert that for loop will not use continue, however. "Best," of course, is subjective.)
In the exercise, I am asked to explain why the conversion is wrong and then fix it
The conversion is wrong simply because when you will reach a i value that modulo 3 equals 0 (the first iteration in that case), you will skip to the next iteration and re-validate. However, since you skipped directly without incrementing i , you will re-validate the same condition and re-validate ad-infinitum.
You could fix it easily by getting rid of the continue and negating the condition :
while (i < 4) {
if (i % 3 != 0)
sum += i;
i++;
}
The for-loop given by the question if converted to plain English, it means sum up from 0 to 3 and exclude all multiples of 3. (0+1+2=3)
for (int i = 0; i < 4; i++) {
if (i % 3 == 0) continue;
sum += i;
}
So now, we ask ourselves, how do we sum up 0 to x and exclude all multiples of 3 using a while-loop. We will do this without looking at the original for-loop. (Sometimes it is easier to do it this way since we already know the intention of the for-loop)
To sum up a number from 0 to 3:
int i = 0;
while(i < 4){
sum += i;
i++;
}
To sum a number from 0 to 3, excluding multiples of 3:
int i = 0;
while(i < 4){
if(i % 3 != 0)
sum += i;
i++;
}
To sum a number from 0 to 3, excluding multiples of 3 (using continue):
int i = 0;
while(i < 4){
if(i % 3 == 0){
i++; //Remember to increase i before continue
continue;
}
else
sum += i;
i++;
}
Since after the continue, all statements below it will be skipped, you have to remember to do an increment i++ before calling continue. There will be another i++ since you branch out into 2 conditions now.
According to the while loop logic, increment of variable i is conditional where as for for-loop it is unconditional. To make the increment logic uniform, you should increment in both cases.
I think the proper converting would be -
int i = 0, sum = 0;
while (i < 4) {
if (i % 3 == 0) {i++;continue;}
sum += i;
i++;
}
System.out.println(sum);
Normally the increment would be on the last line of a while loop. However, in this "disaster waiting to happen" code, there is a condition to skip to the end of the while block without incrementing i. If you are relying on i to increment, make sure it is always executed on any iteration. And also, at the end, because you want it to iterate the first time.
while (i < 4) {
if (i % 3 == 0) {
// skip!
} else {
sum += i;
}
i++;
}
I am working through a section of a text on determining complexity of nested loops using recurrence relations. In this particular example I am trying to determine how many times the count variable will be incremented as a function of n.
This is the loop I am analyzing:
for (int i = 1; i <= n; i++) {
int j = n;
while (j > 0) {
count++;
j = j / 2;
}
}
I think I understand that the first line would equate simply to n since it only executes for each value of n but it's the rest of it that I'm having trouble with. I think the answer would be something like n(n/2) except that this example is using integer division so I'm not sure how to represent that mathematically.
I've run through the loop by hand a few times on paper so I know that the count variable should equal 1, 4, 6, 12, 15, and 18 for n values of 1-6. I just can't seem to come up with the formula... Any help would be greatly appreciated!
The loop executes for n in the range [1, n]. It divides by 2 each time for the j variable, which is set to n, so the number of time the inner loop executes is floor(l2(n)) + 1, where l2 is the binary log function. Add up all such values from 1 to n (multiply by n).
The inner j loop adds the location of the first set bit to count.
Each divide by 2 is the same as a right shift until all the bits are zero.
So, 2 would be 10 in binary, and have a value of 2 for the inner loop.
4 would be 100 in binary, and have a value of 3 for the inner loop.
The outer loop seems to just multiply the location of the first set bit by the number itself.
Here is an example with n = 13.
13 in binary is 1101, so the first set bit is at location 4.
4 * 13 = 52. 52 is the final answer.
for (int i = 1; i <= n; i++) {
This loop at the top goes through the loop n times.
int j = n;
while (j > 0) {
count++;
j = j / 2;
}
This loop here goes through the loop log(n) times, noting that it is a base 2 log since you are dividing by 2 each time.
Hence, the total number of counts is n * ceiling(log(n))