I have the following matrix:
1 4 5
5 7 6
5 8 8
I want to find the minimum value of line 1 and subtract from all values of the same line. The same thing for line 2 and 3. The minimum value of line 1 is 1, line 2 is 5 and line 3 is 5. So I subtract 1 from all values of line 1, subtract 5 from all values in line 2 and subtract 5 from all values in line 3.
0 3 4
0 2 1
0 3 3
My matrix is called "a":
min = a[0][0] \\\ min = minimum value
for (k = 0; k < 3; k++) {
for (l = 1; l < 3; l++) {
if (a[k][l] < min)
min = a[k][l - 1];
}
for (l = 0; l < 3; l++) {
a[k][l] = a[k][l] - min;
}
min = a[k+1][0];
}
For k = 0, the value a[k+1][0] = 5 is changing to 4. Why is that?
EDIT: I declared the array as:
a[0][0] = 1;
a[0][1] = 4;
a[0][2] = 5;
a[1][0] = 5;
a[1][1] = 7;
a[1][2] = 6;
a[2][0] = 5;
a[2][1] = 8;
a[2][2] = 8;
Following Kresimir I changed the code to:
for (k = 0; k < 3; k++) {
min = 10000;
for (l = 0; l < 3; l++) {
if (a[k][l] < min)
min = a[k][l];
}
for (l = 0; l < 3; l++) {
a[k][l] = a[k][l] - min;
}
}
To print the matrix:
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
printf("a[%d][%d] = %d\n", i, j, a[i][j]);
}
}
But the output is:
a[0][0] = 0
a[0][1] = 3
a[0][2] = 0
a[1][0] = 0
a[1][1] = 3
a[1][2] = 0
a[2][0] = 0
a[2][1] = 0
a[2][2] = 3
When k = 0, the first line is changed correctly and the rest is kept the same as they should, when k = 1, all lines are changed wrong to the above.
When approaching any bit of coding, it generally helps to break your coding tasks down into a series of individual steps -- that then provide a road-map to follow as you begin actual coding. You can type the steps out in a separate editor window, (or what I find just as helpful is an 8 1/2 x 11 sheet of paper and pencil).
Think through what your code must do and write it down, e.g.
loop over all rows in the matrix (a/k/a the 2D array of int);
loop over all column values to find the minimum in each row; and finally
loop over all column values (again) subtracting the minimum from each value.
You don't have to get it perfect the first time, now look again at the steps you have written and determine if there are any constraints you must impose.
(Here, yes, you must determine the minimum by examining each value in a row before you can begin subtracting the minimum from each value -- this necessitates at least two loops over the column values. Further, you must also reset or re-initialize your min variable so that it holds the minimum for the current row -- not the minimum from the last row that just happened to be less than this one. Use the re-initialization requirement to make a logical choice for the scope within which each variable should be declared)
Now with your steps refined with any constraints you must impose, you can logically lay out your code (keeping in mind that you must always protect against reading or writing beyond your array bounds, etc.) With the benefit of a good outline, you know you will need one outer loop that loops over all rows, and then two inner loops that (a) find the minimum, and (b) subtract that from all values in that row. You could do something similar to:
#include <stdio.h>
#include <limits.h> /* for INT_MAX, INT_MIN */
#define ASZ 3 /* if you need a constant, define one (or more), a size */
int main (void) {
int a[][ASZ] = {{ 1, 4, 5 }, { 5, 7, 6 }, { 5, 8, 8 }};
puts ("Original matrix:"); /* output original matrix */
for (int row = 0; row < ASZ; row++) {
for (int col = 0; col < ASZ; col++)
printf (" %2d", a[row][col]);
putchar ('\n');
}
puts ("\nModified matrix:"); /* subtract row-min from each element */
for (int row = 0; row < ASZ; row++) { /* loop over rows */
int min = INT_MAX; /* declare min = INT_MAX */
for (int col = 0; col < ASZ; col++) /* loop over column vals */
if (a[row][col] < min) /* find row-min value */
min = a[row][col];
for (int col = 0; col < ASZ; col++) { /* loop over column vals */
a[row][col] -= min; /* subtract row-min value */
printf (" %2d", a[row][col]); /* output new value */
}
putchar ('\n');
}
}
Example Use/Output
$ ./bin/mtrx_subtract_rowmin
Original matrix:
1 4 5
5 7 6
5 8 8
Modified matrix:
0 3 4
0 2 1
0 3 3
There is no magic to it, it just takes approaching each problem in a systematic way. Doing it often enough, it gets easier each time. Pay attention to where each variable was declared (or constant defined) and understand why. Let me know if you have any further questions.
If you want to find the minimum for each line, you need to initialise it for each line, not only once.
for (k = 0; k < 3; k++) {
min = a[k][0];
...
You were only searching for the minimum so far.
Whenever I'm looking for a minimum, I set min to positive infinity (nothing can be larger than that - you don't have to do it, but it makes for a nicer code, in my opinion).
Alternatively, you can use min = Math.min(...a[k]); instead of that entire first for loop (will not work on IE, though).
Also, keep in mind that indices go from 0 to 2. Also, check the order of k and l (depending on how you implement the rows and columns of the matrix).
let k, l, min;
let a=[[1, 4, 5],
[5, 7, 6],
[5, 8, 8]];
for (k = 0; k < 3; k++) {
min = +Infinity;
for (l = 0; l < 3; l++) {
if (a[k][l] < min)
min = a[k][l];
}
for (l = 0; l < 3; l++) {
a[k][l] = a[k][l] - min;
}
}
console.log(a);
Related
This is the question text:
Given an array arr[] denoting heights of N towers and a positive integer K, you have to modify the height of each tower either by increasing or decreasing them by K only once. After modifying, height should be a non-negative integer.
Find out what could be the possible minimum difference of the height of shortest and longest towers after you have modified each tower.
The question can be found here: https://practice.geeksforgeeks.org/problems/minimize-the-heights3351/1#
My doubt was in the correctness of the algorithm I came up with. Here's the code:
int getMinDiff(int arr[], int n, int k) {
// code here
int mean = 0;
for(int i = 0; i < n; i++)
{
mean += arr[i];
}
mean /= n;
int minH = INT_MAX, maxH = INT_MIN;
for(int i = 0; i < n; i++)
{
if(arr[i] < mean)
{
if(arr[i] + k <= mean)
{
arr[i] += k;
}
else
{
int a = arr[i] + k - mean;
int b = mean - arr[i];
if(a < b)
{
arr[i] += k;
}
}
}
else if(arr[i] > mean)
{
if(arr[i] >= k)
{
if(arr[i] - k >= mean)
{
arr[i] -= k;
}
else
{
int a = arr[i] - mean;
int b = mean - (arr[i] - k);
if(b < a)
{
arr[i] -= k;
}
}
}
}
}
for(int i = 0; i < n; i++)
{
if(arr[i] < minH)
{
minH = arr[i];
}
if(arr[i] > maxH)
{
maxH = arr[i];
}
}
return maxH - minH;
}
The code first finds the mean height of towers, then to minimize the difference, tries to bring height of each tower as close to the mean as possible. Then it calculates the difference between highest and lowest towers' heights.
This code, for the following test case:
K = 5
arr = 2 6 3 4 7 2 10 3 2 1
Produces the output
4
The given answer is
7
But, according to me, we can adjust the array as:
2 6 3 4 2 2 5 3 2 6
Then the minimum and maximum heights are 2 and 6, so the answer should be 4. So, is there something wrong in the way I am approaching this problem?
I know this question has been asked before, but my query is about the specific solution algorithm.
Mean gets skewed by the number of elements having a certain value. But in this problem, the result is independent of how many elements match a particular value; we could have one element equal 20 or 1000 elements equal 20 and it won't affect the result.
2 6 3 4 7 2 10 3 2 1
k = 5
Ordered:
x (optimal)
+5: 6 7 8 9 11 12 15
1 2 3 4 6 7 10
-5: -4 -3 -2 -1 1 2 5
x (optimal)
I did the following:
for (int i = 0; i < tamLinhas; i++) {
for (int j = 0; j < tamColunas; j++) {
if (i >= 0) {
vetormedia[j] = (informacoes[i][j] + informacoes[i][j]) / tamVetor;
}
}
}
I'm trying to record in an array the result of the sum of the matrix's rows but I need to ignore the first line of the Matrix.
In a nutshell, the values of the first line cannot be included in the sum. I just cannot get it done right. I've been trying for hours...
To bypass the first line of the matrix informacoes just start the iteration at the index 1 rather than 0:
for (int i = 1; i < tamLinhas; i++) {
Note your test if (i >= 0) is useless even in your initial case because i cannot be negative
That line is very strange :
vetormedia[j] = (informacoes[i][j] + informacoes[i][j]) / tamVetor;
because you do not sum the rows and you save that value in the same place for all the lines.
To just sum the rows of each line separately and save the result in vetormedia :
for (int i = 1; i < tamLinhas; i++) {
int sum = 0
for (int j = 0; j < tamColunas; j++) {
sum += informacoes[i][j];
}
vetormedia[i] = sum;
}
Supposing tamLinhas values 3 and tamColunas values 4 and informacoes is the following matrix :
1 2 3 4
4 5 6 7
8 9 0 1
after the previous loop vetormedia will be :
x 22 18
where "x" design any value because the first line of the matrix is bypassed
Do you want that ?
Is it possible in C to have a fast for/while loop that loops through the odd numbers and 2? Without using arrays.
So I'd like it to loop through {1, 2, 3, 5, 7, 9, ..}
Of course. Here is a pretty straight forward way.
for(int i=1; i<N; i++) {
if(i>3) i++;
// Code
}
A bit more hackish variant:
for(int i=1; i<N; i+=1+(i>2)) {
// Code
}
But I think in this case that the most readable variant would be something like:
// Code for 1 and 2
// Then code for 3,5,7 ...
for(int i=3; i<N; i+=2) {
// Code
}
Another option
for(int i=1;;++i) // you didn't specify a limit
{
switch(i)
{
default:
if(!(i&1))continue;
case 1:
case 2:
DoSomething(i):
}
}
Another alternative which does use an array but only a small one that is a constant size of two elements no matter how many numbers in the sequence would be:
{
int i;
int iray[] = {1, 2};
int n = 15;
for (i = 1; i < n; i += iray[i > 2]) {
printf (" i = %d \n", i);
// code
}
}
which produces:
i = 1
i = 2
i = 3
i = 5
i = 7
i = 9
i = 11
i = 13
Extending this alternative to other sequences
And this alternative can be extended to other sequences where there is a change of a similar nature. For instance if the desired sequence was
1, 2, 3, 5, 8, 11, ..
Which involves several changes in the sequence. Beginning at 1 an increment of 1 is used followed by a first increment change beginning at 3 where an increment of 2 is used followed by a second change in the sequence beginning at 5 where an increment of 3 is used, you can make the following modification.
{
int i;
int iray[] = {1, 2, 3}; // increment changes
int n = 15;
// calculate the increment based on the current value of i
for (i = 1; i < n; i += iray[(i > 2) + (i > 3)]) {
printf (" i = %d \n", i);
// code
}
return 0;
}
which would produce:
i = 1
i = 2
i = 3
i = 5
i = 8
i = 11
i = 14
#include <stdio.h>
int main()
{
for(unsigned x = 0; x < 10; x++)
printf("%u%s element - %u\n",x + 1, !x ? "st" : x == 1 ? "nd" : x == 2 ? "rd" : "th", !x + x * 2 - (x >= 2));
return 0;
}
no jumps calculating in the !x + x * 2 - (x >= 2) so no pipeline flushes.
I tried to sort arr by excluding those who were already selected as the largest numbers but it didn't work.
The result is this:
As I intended, at first cycle, the store is {9, 0, 0, 0, 0 ... } and when arr[i] becomes 9, the rest of process should be skipped. I have to sort it without additional functions and it's too difficult to me. What is the problem?
int i = 0;
int j = 0;
int num = 0;
int sign = 0;
int arr[10] = { 1,5,3,4,8,7,5,9,8,0 };
int max = arr[0];
int store[10] = { 0 };
int k = 0;
for (j = 0; j < 10; j++) {
printf("store: ");
for (int n = 0; n < 10; on++)
printf("%d ", store[n]);
printf("\n");
for (i = 0; i < 10; i++) {
sign = 0;
k = 0;
while (k < 10) {
if (arr[i] == store[k]) {
sign = 1;
break;
}
k++;
}
if (sign == 1) {
continue;
}
if (arr[i] > max) {
max = arr[i];
}
}
store[j] = max;
}
You have several errors here:
The array store has a size of 10, but in the jth pass through the outer loop, only j values have been filled in; the rest is still zero. So whenever you iterate over store, you should use j as upper limit.
You are looking for the max in each iteration. Therefore, it is not enough to initialise max once outside the outer loop. You do that, and it will stay 9 ever after. You should reset max for every j.
Finally, your idea to go through the array to see whether you have already processed a certain value does not work. Your array has duplicates, two 8's and two 5's. You will only place one eight and one five with your strategy and re-use the last value of max for the last two elements. (Plus, that idea lead to O(n³) code, which is very wasteful.
You can work around that by keeping an extra array where you store whether (1) or not (0) you have already processed a value at a certain index or by setting processed entries in the array to a very low value.
What you want to implement is selection sort: Find the maximum value in the whole list and move it to the front. Then find the maximum in the whole list except the first item and move it to the second slot and so on:
* 1 5 3 4 8 7 5 9 8 0
9 * 5 3 4 8 7 5 1 8 0
9 8 * 3 4 5 7 5 1 8 0
9 8 8 * 4 5 7 5 1 3 0
9 8 8 7 * 5 4 5 1 3 0
9 8 8 7 5 * 4 5 1 3 0
9 8 8 7 5 5 * 4 1 3 0
9 8 8 7 5 5 4 * 1 3 0
9 8 8 7 5 5 4 3 * 1 0
9 8 8 7 5 5 4 3 1 * 0
9 8 8 7 5 5 4 3 1 0 *
Here, all items to the left of the asterisk have been sorted and everything to the right of the asterisk is still unsorted. When the * (at position j) has moved to the right, the whole array is sorted.
This sort is in-place: It destroys the original order of the array. That is useful, because the position of an element tells us whether it has been processed or not. In the third iteration, the algorithm can distinguish between the 8 that has been sorted and the 8 that hasn't been sorted yet. (This sort is often described as sorting a hand of cards: Look fo the lowest, put it to the left and so on. If you must sort into a second array, copy the original array and sort the copy in place.)
Here's the code that sorts your array and prints out the diagram above:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int arr[10] = {1, 5, 3, 4, 8, 7, 5, 9, 8, 0};
int i = 0;
int j = 0;
for (j = 0; j < 10; j++) {
int imax = j;
int swap = arr[j];
// print array
for (i = 0; i < 10; i++) {
if (i == j) printf("* ");
printf("%d ", arr[i]);
}
printf("\n");
// find index of maximum item
for (i = j + 1; i < 10; i++) {
if (arr[i] > arr[imax]) {
imax = i;
}
}
// swap first unsorted item and maximum item
arr[j] = arr[imax];
arr[imax] = swap;
}
// print fully sorted array
for (i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("*\n");
return 0;
}
Use i and j.
N is 10 and the data consists of shuffled numbers 0 to N-1.
j goes from 0 to N-1. At each step, you want to fill it with
the maximum of the unprocessed input.
So i goes from j+1 to N-1, in the inner loop. If arr[j] < arr[i],
swap arr[i] and arr[j].
It speeds up considerably as you get towards the end.
So I have been trying to do a variant of the subset sum problem, which I want to do using dynamic programming. So what I am aiming for is for example, to have an input of
m = 25 // Target value
n = 7 // Size of input set
and the input set to be for example {1, 3, 4, 6, 7, 10, 25}. So the wanted output would be something like
{1, 3, 4, 7, 10} and {25}.
Here is the code
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Get input sequence
int n = 7; // Size of input set
int m = 25; // Target value
int *S; // Input set
int **C; // Cost table
int i,j,potentialSum,leftover;
S=(int*) malloc((n+1)*sizeof(int));
C=malloc((m+1)*sizeof(int*));
for (int rows = 0; rows<=m; rows++) {
C[rows] = malloc((m+1)*sizeof(int));
}
if (!S || !C)
{
printf(" FAILED %d\n",__LINE__);
exit(0);
}
S[0] = 0;
S[1] = 1;
S[2] = 3;
S[3] = 4;
S[4] = 6;
S[5] = 7;
S[6] = 10;
S[7] = 25;
// Initialize table for DP
C[0][0]=0; // DP base case
// For each potential sum, determine the smallest index such
// that its input value is in a subset to achieve that sum.
for (potentialSum=1; potentialSum<=m; potentialSum ++)
{
for (j=1;j<=n;j++)
{
leftover=potentialSum-S[j]; // To be achieved with other values
if (leftover<0) // Too much thrown away
continue;
if (C[leftover][0] == (-1)) // No way to achieve leftover
continue;
if (C[leftover][0]<j) // Indices are included in
break; // ascending order.
}
C[potentialSum][0]=(j<=n) ? j : (-1);
}
// Output the input set
printf(" i S\n");
printf("-------\n");
for (i=0;i<=n;i++)
printf("%3d %3d\n",i,S[i]);
// Output the DP table
printf("\n\n i C\n");
printf("-------\n");
for (i=0;i<=m;i++)
printf("%3d %3d\n",i,C[i][0]);
if (C[m][m]==(-1))
printf("No solution\n");
else
{
printf("\n\nSolution\n\n");
printf("(Position) i S\n");
printf("------------------\n");
for (i=m;i>0;i-=S[C[i][0]])
printf(" %3d %3d\n",C[i][0],S[C[i][0]]);
}
}
This will output the following
i S
-------
0 0
1 1
2 3
3 4
4 6
5 7
6 10
7 25
i C
-------
0 0
1 1
2 -1
3 2
4 2
5 3
6 4
7 3
8 3
9 4
10 4
11 4
12 5
13 4
14 4
15 5
16 5
17 5
18 5
19 6
20 5
21 5
22 6
23 6
24 6
25 6
Solution
(Position) i S
------------------
6 10
5 7
3 4
2 3
1 1
Program ended with exit code: 0
My problem is that I can only output one solution, and that is the solution that needs the smaller values and goes up to 25, so when 25 is used it isn't in the solution. The C array in the code is a 2-D array, since I thought I could maybe do another backtrace while computing the first one? I couldn't figure out how to do so, so I left C[i][0] fixed to the first column, just to demonstrate a single solution. Any tips in the right direction would be greatly appreciated. I found a solution using Python, but the problem is solved recursively, which I don't think helps me, but that code is here.
Thanks for all the help in advance.
I did not fully understand your code. But here is a C code which finds all the subsets that sum to target.
#include <stdio.h>
int a[] = { 0, 1, 3, 4, 6, 7, 10, 25 }; //-- notice that the input array is zero indexed
int n = 7;
int target = 25;
int dp[8][26];
int solutions[1 << 7][8]; //-- notice that the number of subsets could be exponential in the length of the input array a.
int sz[1 << 7]; //-- sz[i] is the length of subset solutions[i]
int cnt = 0; //-- number of subsets
void copy(int srcIdx, int dstIdx){
int i;
for (i = 0; i < sz[srcIdx]; i++)
solutions[dstIdx][i] = solutions[srcIdx][i];
sz[dstIdx] = sz[srcIdx];
}
//-- i, and j are indices of dp array
//-- idx is the index of the current subset in the solution array
void buildSolutions(int i, int j, int idx){
if (i == 0 || j == 0) return; // no more elements to add to the current subset
if (dp[i - 1][j] && dp[i - 1][j - a[i]]){ // we have two branches
cnt++; // increase the number of total subsets
copy(idx, cnt); // copy the current subset to the new subset. The new subset does not include a[i]
buildSolutions(i - 1, j, cnt); //find the remaining elements of the new subset
solutions[idx][sz[idx]] = a[i]; // include a[i] in the current subset
sz[idx]++; // increase the size of the current subset
buildSolutions(i - 1, j - a[i], idx); // calculate the remaining of the current subset
}
else if (dp[i - 1][j - a[i]]){ // we only have one branch
solutions[idx][sz[idx]] = a[i]; // add a[i] to the current subset
sz[idx]++;
buildSolutions(i - 1, j - a[i], idx); // calculate the remaining of the current subset
}
else buildSolutions(i - 1, j, idx); // a[i] is not part of the current subset
}
int main(){
int i, j;
// initialize dp array to 0
for (i = 0; i <= n; i++)
for (j = 0; j <= target; j++) dp[i][j] = 0;
//-- filling the dp array
for (i = 0; i <= n; i++)
dp[i][0] = 1;
for (i = 1; i <= n; i++){
for (j = 1; j <= target; j++){
if (j < a[i])
dp[i][j] = dp[i - 1][j];
else
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - a[i]];
}
}
//-- building all the solutions
for (i = 0; i < sizeof(sz); i++) sz[i] = 0; //-- initializing the sz array to 0
buildSolutions(n, target, 0);
//-- printing all the subsets
for (i = 0; i <= cnt; i++){
for (j = 0; j < sz[i]; j++){
printf("%d ", solutions[i][j]);
}
printf("\n");
}
}
If you have any questions about the code, do not hesitate to ask.