I have :
#include <stdio.h>
int main(void) {
int s,i,t[] = { 0, 1, 2, 3, 4, 5 };
s = 1;
for(i = 2; i < 6 ; i += i + 1)
s += t[i];
printf("%d",s);
return 0;
}
Why is the result 8?
What I'm thinking:
first loop: 2<6 True
i+=i+1 is 5
s=1+t[5] =>1+5=6
second loop : 5<6 True
i=5+5+2=11
s=6+t[11]???
The loop increment expression (i += i + 1 in your case) happens after the loop body, not before.
So in the first iteration you do
s = 1 + t[2];
More generally, any for loop could be expressed as a while loop:
for (a; b; c)
{
d;
}
is equivalent to
{
a;
while (b)
{
{
d;
}
c;
}
}
For your specific case it's:
{
i = 2;
while (i < 6)
{
{
s += t[i];
}
i += i + 1;
}
}
I will guide you to the for loop reference:
iteration-expression is evaluated after the loop body and its result
is discarded. After evaluating iteration-expression, control is
transferred to cond-expression.
In your example, i += i + 1, which is the iteration expression we're talking about, is evaluated after the loop body.
Taking this into account, the result will be 8
Look attentively at the third expression in the for loop
s = 1;
for(i = 2; i < 6 ; i += i + 1)
s += t[i];
It is i += i + 1. So in iterations of the loop the variable i will be changed the following way
i = 2 (initially)
i = 5 ( i += i + 1 => i += 2 + 1 => i += 3 => i = 2 + 3)
After the second iteration of the loop the variable i will be already greater than 6. (i += i + 1 => i += 5 + 1 => i += 6 => i = 5 + 6)
So this statement
s += t[i];
in fact produces the following sum
1 + t[2] + t[5] = 1 + 2 + 5
that is equal to 8.
Related
I tried to solve it on my own way, but instead of giving me consecutive odd numbers, it gave me the result of a cubic number. How can I make so it'll give me, after the compilation, consecutive odd numbers whose sum equals to n^3(cubic number) like the examples shown above? Thanks in advance and also do not forget to explain me how you did it. Please use C, when giving a much more viable solution.
#include <stdio.h>
#include <math.h>
int main()
{
int n, sum;
printf("Value of n= ");
scanf("%d",&n);
for(int n=1; n<=20; n++)
{
if(n%2!=0);
}
printf("%d", sum=pow(n,3));
return 0;
}
Instead of thinking it like that, I tried a few numbers and found the solution in math. I guess this is not what you wanted, but it does work and consists of only odd numbers.
1^3=1
2^3=3+5
3^3=7+9+11
4^3=13+15+17+19
5^3=21+23+25+27+29
...
x^3=[x*(x-1)+1]+[x*(x-1)+3]+...+[x*(x-1)+2x-1]
for math proof, define it as a series:
An=x^2-x+1+2(n-1)=x^2-x+1+2n-2=x^2-x+2n-1
Sx=(A1+Ax)*x/2=[(x^2-x+1)+(x^2-x+2x-1)]*x/2=(2x^2)*x/2=x^3
Also, because n(n-1) is always even, the numbers must be odd.
to write it as code:
void printOddNumbers(int n)
{
int a1 = n * (n - 1) + 1;
for(int i = 0; i < n; i++)
{
printf("%d+", a1 + 2 * i);
}
printf("\b=%d^3=%d\n", n, n * n * n);
}
So the output will look like: 13+15+17+19=4^3=64.
So, you have an input, n, which is the number of consecutive odd numbers, which should yield a given sum as a result. So, this is how it looks alike:
sum = k + (k + 2) + ... + (k + 2n - 2) =
= n * k + 2 * (1 + 2 + ... + n - 1) =
= n * k + 2 (n * (n - 1) / 2) =
= n * k + n * (n - 1) =
= n * (n + k - 1)
n is known, k is an unkown odd number. So, for sum = 27 and n = 3 this would mean
3 * (3 + k - 1) = 27
3 + k - 1 = 9
k + 2 = 9
k = 7
7 + 9 + 11 = 27
For sum = 125, k = 5:
5 * (5 + k - 1) = 125
5 + k - 1 = 25
k = 21
21 + 23 + 25 + 27 + 29 = 125
So, the implementation would look like this:
int getK(int n, int sum) {
int k = (sum / n) - n + 1;
int currentSum = k;
int result = k;
for (int i = 1; i < n; i++) currentSum += 2 * i + k;
return ((currentSum == sum) && (k % 2)) ? k : 0;
}
Explanation: We return the smallest of the set when the problem is solvable. If it is not an odd, then we return 0 as a sign of error. Also, if the sum does not add up, then the problem is unsolvable and we return 0.
We are asked to write some code that takes a 4 digit number as input, and does the following:
Take any four-digit number, using at least two different digits.
Arrange the digits in descending and then in ascending order to get two four-digit numbers
Subtract the smaller number from the bigger number.
Go back to step 2 and repeat.
The end result will always freeze at kaprekar's constant 1674 and we must print the algorithm's resulting number each and every time . In the end we also have to print the number of times we had to run the algorithm to get there .
I worked it out as loop , storing the digits in 2 arrays and sorting the first in ascending order and the second in descending order over and over again till i get to 1674 but for some reason the "process" loop won't stop . Any help would be appreciated .
#include <stdio.h>
#include <stdlib.h>
int main()
{
long int pow1(int x, int n)
{
int i, result = 1;
for (i = 0; i < n; i++)
{ // Power Function //
result *= x;
}
return (result);
}
int a, s;
int val[] = {
0,
0,
0,
0};
int value[] = {
0,
0,
0,
0};
int ex = 0;
scanf(" %d", &a);
if (a / 1000 != 0 && a / 1000 < 10)
{
// Extracting the digits and storing them in the arrays .
for (int i = 0; i <= 3; ++i)
{
value[i] = val[i] = (a % pow1(10, i + 1) - a % pow1(10, i)) / pow1(10, i);
if (i > 0)
{
if (val[i] == val[i - 1])
{
ex++;
}
}
}
if (ex == 3)
{
printf("Wrong input");
exit(0);
}
int j = 0, k = a;
// Start of process
while (k != 6174)
{
while (1)
{
s = 0;
for (int i = 0; i <= 3; i++)
{
if (val[i] > val[i + 1])
{
int temp = val[i];
val[i] = val[i + 1];
val[i + 1] = temp;
s = 1;
}
}
if (s == 0)
{
break;
}
}
while (1)
{
s = 0;
for (int i = 0; i <= 3; i++)
{
if (value[i] < value[i + 1])
{
int temp = value[i];
value[i] = value[i + 1];
value[i + 1] = temp;
s = 1;
}
}
if (s == 0)
{
break;
}
}
j++;
printf("max:%d min: %d ", value[0] * 1000 + value[1] * 100 + value[2] * 10 + value[3], val[0] * 1000 + val[1] * 100 + val[2] * 10 + val[3]);
k = value[0] * 1000 + value[1] * 100 + value[2] * 10 + value[3] - (val[0] * 1000 + val[1] * 100 + val[2] * 10 + val[3]);
printf("diff:%d\n", k);
for (int i = 0; i <= 3; ++i)
{
value[i] = val[i] = (k % pow1(10, i + 1) - k % pow1(10, i)) / pow1(10, i);
}
}
printf("Took %d turns", j);
}
else
{
printf("Wrong input");
}
return 0;
}
You have defined val and value as 4 element [0..3], yet in your loops you access and modify both over [0..4] eg: val[i+1] = temp.
I proper sized them (int val[5] = {0}, value[5] = {0}), and your test yielded:
max:2211 min: 112 diff:2099
max:9920 min: 229 diff:9691
max:9961 min: 1699 diff:8262
max:8622 min: 2268 diff:6354
max:6543 min: 3456 diff:3087
max:8730 min: 378 diff:8352
max:8532 min: 2358 diff:6174
Took 7 turns
Because your sort isn't quite right.
If you change your sort to be:
for (int i = 1; i < 4; i++)
{
if (val[i-1] > val[i])
{
int temp = val[i];
val[i] = val[i - 1];
val[i - 1] = temp;
s = 1;
}
}
it will respect its boundaries, and be correct; so you can go back to len 4 vectors. Remember to change the other one as well.
ps: It is more work for me to complain that you didn't put a main wrapper in your example than to put one in. That doesn't excuse not doing the least you can do.
Problem Statement:
Given an array, the task is to divide it into two sets S1 and S2 such that the absolute difference between their sums is minimum.
Sample Inputs,
[1,6,5,11] => 1. The 2 subsets are {1,5,6} and {11} with sums being 12 and 11. Hence answer is 1.
[36,7,46,40] => 23. The 2 subsets are {7,46} and {36,40} with sums being 53 and 76. Hence answer is 23.
Constraints
1 <= size of array <= 50
1 <= a[i] <= 50
My Effort:
int someFunction(int n, int *arr) {
qsort(arr, n, sizeof(int), compare);// sorted it for simplicity
int i, j;
int dp[55][3000]; // sum of the array won't go beyond 3000 and size of array is less than or equal to 50(for the rows)
// initialize
for (i = 0; i < 55; ++i) {
for (j = 0; j < 3000; ++j)
dp[i][j] = 0;
}
int sum = 0;
for (i = 0; i < n; ++i)
sum += arr[i];
for (i = 0; i < n; ++i) {
for (j = 0; j <= sum; ++j) {
dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]);
if (j >= arr[i])
dp[i + 1][j + 1] = max(dp[i + 1][j + 1], arr[i] + dp[i][j + 1 - arr[i]]);
}
}
for (i = 0; i < n; ++i) {
for (j = 0; j <= sum; ++j)
printf("%d ", dp[i + 1][j + 1]);
printf("\n");
}
return 0;// irrelevant for now as I am yet to understand what to do next to get the minimum.
}
OUTPUT
Let's say for input [1,5,6,11], I am getting the dp array output as below.
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
0 1 1 1 1 5 6 7 7 7 7 11 12 12 12 12 12 12 12 12 12 12 12 12
0 1 1 1 1 5 6 7 7 7 7 11 12 12 12 12 16 17 18 18 18 18 22 23
Now, how to decide the 2 subsets to get the minimum?
P.S - I have already seen this link but explanation is not good enough for a DP beginner like me.
You have to solve subset sum problem for SumValue = OverallSum / 2
Note that you don't need to solve any optimization problem (as using max operation in your code reveals).
Just fill linear table (1D array A) of size (SumValue + 1) with possible sums, get the closest to the last cell non-zero result (scan A backward) wint index M and calculate final result as abs(OverallSum - M - M).
To start, set 0-th entry to 1.
Then for every source array item D[i] scan array A from the end to beginning:
A[0] = 1;
for (i = 0; i < D.Length(); i++)
{
for (j = SumValue; j >= D[i]; j--)
{
if (A[j - D[i]] == 1)
// we can compose sum j from D[i] and previously made sum
A[j] = 1;
}
}
For example D = [1,6,5,11] you have SumValue = 12, make array A[13], and calculate possible sums
A array after filling: [0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1]
working Python code:
def besthalf(d):
s = sum(d)
half = s // 2
a = [1] + [0] * half
for v in d:
for j in range(half, v - 1, -1):
if (a[j -v] == 1):
a[j] = 1
for j in range(half, 0, -1):
if (a[j] == 1):
m = j
break
return(s - 2 * m)
print(besthalf([1,5,6,11]))
print(besthalf([1,1,1,50]))
>>1
>>47
I'll convert this problem to subset sum problem
let's take array int[] A = { 10,20,15,5,25,33 };
it should be divided into {25 20 10} and { 33 20 } and answer is 55-53=2
Notations : SUM == sum of whole array
sum1 == sum of subset1
sum2 == sum of subset1
step 1: get sum of whole array SUM=108
step 2: whichever way we divide our array into two part one thing will remain true
sum1+ sum2= SUM
step 3: if our intention is to get minimum sum difference then
sum1 and sum2 should be near SUM/2 (example sum1=54 and sum2=54 then diff=0 )
steon 4: let's try combinations
sum1 = 54 AND sum2 = 54 (not possible to divide like this)
sum1 = 55 AND sum2 = 53 (possible and our solution, should break here)
sum1 = 56 AND sum2 = 52
sum1 = 57 AND sum2 = 51 .......so on
pseudo code
SUM=Array.sum();
sum1 = SUM/2;
sum2 = SUM-sum1;
while(true){
if(subSetSuMProblem(A,sum1) && subSetSuMProblem(A,sum2){
print "possible"
break;
}
else{
sum1++;
sum2--;
}
}
Java code for the same
import java.util.ArrayList;
import java.util.List;
public class MinimumSumSubsetPrint {
public static void main(String[] args) {
int[] A = {10, 20, 15, 5, 25, 32};
int sum = 0;
for (int i = 0; i < A.length; i++) {
sum += A[i];
}
subsetSumDynamic(A, sum);
}
private static boolean subsetSumDynamic(int[] A, int sum) {
int n = A.length;
boolean[][] T = new boolean[n + 1][sum + 1];
// sum2[0][0]=true;
for (int i = 0; i <= n; i++) {
T[i][0] = true;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= sum; j++) {
if (A[i - 1] > j) {
T[i][j] = T[i - 1][j];
} else {
T[i][j] = T[i - 1][j] || T[i - 1][j - A[i - 1]];
}
}
}
int sum1 = sum / 2;
int sum2 = sum - sum1;
while (true) {
if (T[n][sum1] && T[n][sum2]) {
printSubsets(T, sum1, n, A);
printSubsets(T, sum2, n, A);
break;
} else {
sum1 = sum1 - 1;
sum2 = sum - sum1;
System.out.println(sum1 + ":" + sum2);
}
}
return T[n][sum];
}
private static void printSubsets(boolean[][] T, int sum, int n, int[] A) {
List<Integer> sumvals = new ArrayList<Integer>();
int i = n;
int j = sum;
while (i > 0 && j > 0) {
if (T[i][j] == T[i - 1][j]) {
i--;
} else {
sumvals.add(A[i - 1]);
j = j - A[i - 1];
i--;
}
}
System.out.println();
for (int p : sumvals) {
System.out.print(p + " ");
}
System.out.println();
}
}
Working Java code if anyone is interested but the idea remains the same as what #MBo has answered
class Solution{
public int minDifference(int arr[]) {
int sum = 0;
for(int x : arr) sum += x;
int half = (sum >> 1) + (sum & 1);
boolean[] sums = new boolean[half + 1];
sums[0] = true;
for(int i = 0; i < arr.length; ++i){
if(arr[i] > half) continue;
for(int j = half; j >= arr[i]; --j){
if(sums[j - arr[i]]){
sums[j] = true;
}
}
}
for(int i = sums.length - 1; i >= 1; --i){
if(sums[i]) return Math.abs((sum - i) - i);
}
return sum; // for arrays like [2] or [100] etc
}
}
I'm having a hard time optimizing the following while loop by means of Loop Unswitching. I have tried applying the example from wiki, however I am having a hard time applying it to a while loop. I have the following code:
int n = 5,
m = 5,
i = 0,
val = 0;
while (i < n ) {
j = 0;
while (j < m ) {
if (i < j ) {
val = val + i ;
}
else if ( j == i ) {
val = val - 1;
}
else {
val = val + j ;
}
j = j + 1;
}
i = i + 1;
}
And have tried unswitching it the following way:
while (i < n ) {
j = 0;
if (i < j ) {
while (j < m ) {
val = val + i;
j = j + 1;
}
}
if ( j == i ) {
while (j < m) {
val = val - 1;
j = j + 1;
}
}
if (i > j) {
while (j < m) {
val = val + j;
j = j + 1;
}
}
i = i + 1;
}
What could I be doing wrong.
Such loops are best unrolled with the help of pencil and paper. You want the sum of the following grid:
0 1 2 3 4 | 5 n
0 -1 0 0 0 0 | 0 0
1 0 -1 1 1 1 | 1 1
2 0 1 -1 2 2 | 2 2
3 0 1 2 -1 3 | 3 3
m 0 1 2 3 -1 | 4 4
The grid can be subdivided into three parts: the diagonal, the upper and lower triangles next to the diagonal in the square part and the rectangular block when n and m differ.
Let's represent the dimension of the grid by means of the square part, k² and the rectangular part, k·r:
k = min(n, m)
r = max(m, n) - k
Now you can see which sums the three parts contribute:
val = 2·∑(k - i - 1)·i # two triangles
+ r·∑(i) # rectangle
- k # diagonal
(All sums run from i = 0; i < n; i++.) This sum can be rearranged to:
val = 2·(k - 1)·∑(i) - 2*∑(i²) + r·(i) - k
= (2·k + r - 2)·∑(i) - 2*∑(i²) - k
This reduces your two nested loops two two independent loops to do the sums of the natural numbers and of their squares. Fortunately, these sums can be expressed by simple relations:
∑(i) = (n - 1)·n / 2
∑(i²) = (2·n - 1)·(n - 1)·n / 6
You now have a constant-time formula for your resulting sum:
int val(int n, int m)
{
int k = (n < m) ? n : m;
int r = ((n > m) ? n : m) - k;
return (2*k + r - 2) * (k - 1) * k / 2
- (2*k - 1) * k * (k - 1) / 3 - k;
}
All this doesn't have anything to do with loop unrolling, of course.
Loop unswitching according to wikipedia is a compiler optimization so I'm a little confused about why you'd need to do this yourself, but I think this is as good as it gets in terms of breaking apart the for..ifs
for (i = 0; i < n; ++i) {
// j < i
for (j = 0; j < i; ++j) {
val = val + j;
}
// j == i
val = val - 1;
// j > i
for (j = i + 1; j < m; ++j) {
val = val + i;
}
}
This is not a loop you can traditionally unswitch because the conditional variable here is the loop variable.
This is a pretty simple for loop I have come across in a Java tutorial by Schildt. I have been studying it for some time now and am still unsure of how it returns the value 15. In particular I can't figure out the role played by the "sum" variable in the iteration protion of the statement. A good explanation of this would greatly help me in moving forward in my study of java. The author of the book simply throws this out there as an example of how to use a loop without a body with no explanation of the "sum" value and how it is iterated.
Here is the statement:
for(i = 1; i <= 5; sum += i++)
System.out.println("Sum is " + sum);
How do we explain the variable sum as having the final value of 15 in this statement?
Here's what will happen inside the loop.
i=1; sum = 1;
i=2; sum = 1+2 = 3;
i=3; sum = 3+3 = 6;
i=4; sum = 6+4 = 10;
i=5; sum = 10+5 = 15;
i increases 5 times due to the i++ statement, and is added to sum in each loop iteration, so
1 + 2 + 3 + 4 + 5 = 15
This instruction does two things : sum += i++
first:
sum = sum + i;
and later:
i = i + 1;
//Initial values
sum = 0;
i = 1;
//When the loop finish its last instruction in this case the print
sum = sum + 1
sum = 1;
i = i + 1;
i = 2;
============
sum = sum + 2
sum = 3;
i = i + 1;
i = 3;
============
sum = sum + 3
sum = 6;
i = i + 1;
i = 4;
============
sum = sum + 4
sum = 10;
i = i + 1;
i = 5;
============
sum = sum + 5
sum = 15;
i = i + 1;
i = 6;