Replacing elements in a matrix in C - c

I need to check whether the elements on the main diagonal of a matrix are even and divisible into sum of its indexes. I remembered such elements in an 1-D array:
for (i=0; i<n; ++i)
for (j=0; j<m; ++j)
{
if ((i == j) && ((arr[i][j] % 2) == 0))
{
arr2[count] = arr[i][j];
++count;
break;
}
}
Then I replace the elements which satisfy the condition with the sum of its indexes and place a special condition for [0][0] because of dividing on 0:
count = 0;
for (i=0; i<n; ++i)
for (j=0; j<m; ++j)
{
if ((i+j != 0) && (arr[i][j] == arr2[count]) && ((arr[i][j] % (i+j)) == 0))
{
arr[i][j] = i+j;
++count;
}
else if (((i+j) == 0) && (arr[i][j] == arr2[count])) arr[i][j] = 0;
}
The trouble is that when the first element is even, it is the only replaced number, and the condition doesn't work for the other elements:

Problem:
arr2 is not filled appropriately. As soon as you fill one element into it, you break out of that loop. Notice the usage of break in that loop. Moreover, you did not update the value of count in that else-if condition which causes your loop to run in vain searching for arr2[0] throughout.
Solution:
Remove that break statement.
Add ++count into that else-if condition.
Bonus:
You have written ugly code. You used an extra array which adds to the space complexity of your code and you have too many loops which increases the time complexity as well. You will understand these things later as you progress but for now, I'll give you a better solution:
// Deal with the (0, 0) case outside the loop
// And avoid an extra else-if inside the loop
if (arr[0][0] % 2 == 0)
arr[0][0] = 0;
// There are n diagonal elements in a matrix of order n
// Row and column indexes of a diagonal element are equal
// So you can eliminate the use of j and just rely on i
for (i = 1; i < n; ++i)
// Check if the diagonal element is even and divisible by the sum of the indices
if (arr[i][i] % 2 == 0 && arr[i][i] % (i + i) == 0)
// Replace the element if the condition is satisfied
arr[i][i] = i + i;
As you can see, this approach does not require any extra space and runs in a very good linear time. You may further optimize it by checking if a number is not odd using bitwise AND !(i & 1), and changing i + i into 2 * i which can be done quickly using the bitwise left shift operator (i << 1).
By the way, why do you want arr[0][0] to be replaced? Division by 0 is undefined.

Related

Random walk in a 10X10 array

Write a C program that generates a random walk across a 10x10 array. Initially, the array will contain only dot characters. The program must randomly “walk” from element to element, always going up, down, left, or right by one step. The elements visited by the program will be labeled with the letters A through Z, in the order visited.
It doesn't take the walk to an element that has already a letter assigned (blocked element).If all four directions are blocked, the program must terminate.
I wrote the code for the above question but sometimes the output is just blank, it is just showing a black screen.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
char visited = 'A';
char a[10][10];
// assigning value '.' to array elements
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
a[i][j] = '.';
// the initial is set for the player.
int playeri, playerj;
srand(time(0));
// assigning numbers between 0-9
playeri = rand() % 10; playerj = rand() % 10;
a[playeri][playerj] = visited++;
int move;
// now to move the player
while (visited <= 'Z') {
// to generate numbers between 1-4
move = rand() % 4 + 1;
// to move up
if (move == 1) {
if (a[playeri - 1][playerj] == '.' && playeri != 0) {
playeri = playeri - 1;
a[playeri][playerj] = visited++;
}
}
// to move down
else if (move == 2) {
if (a[playeri + 1][playerj] == '.' && playeri != 9) {
playeri = playeri + 1;
a[playeri][playerj] = visited++;
}
}
// to move right
else if (move == 3) {
if (a[playeri][playerj + 1] == '.' && playerj != 9) {
playerj = playerj + 1;
a[playeri][playerj] = visited++;
}
}
// to move left
else if (move == 4) {
if (a[playeri][playerj - 1] == '.' && playerj != 0) {
playerj = playerj - 1;
a[playeri][playerj] = visited++;
}
}
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
printf("%c", a[i][j]);
}
printf("\n");
}
}
My guess is that the program is stuck in an infinte loop, if so, how do I solve this problem?
Your program has undefined behavior if you access array a out of bounds. This can happen when the random direction is impossible because you reached the borders of the 10x10 array. To avoid this change the order of the conditions to check the index first, e.g.
if (playeri != 0 && a[playeri - 1][playerj] == '.') {
In some cases you probably end up in a position that has no adjacent positions with a dot, so there is no way to continue. As visited does not get incremented in this case, your loop will not terminate.
An additional check that there is at least one direction not blocked will fix the endless loop, but is not an optimal solution.
Your implementation that generates a random direction and then checks if this direction is possible may need several attempts when more fields get blocked.
Although it is very unlikely you might even get random numbers that denote blocked ways for a long time.
To implement the requirement to terminate the program when all directions are blocked and to improve the behavior when many directions are blocked, I suggest to change the algorithm.
Proposed algorithm:
check all 4 directions if it is possible to walk, put all possible directions into an array of at most 4 elements and count the possible directions as n. (Example: if up, down and left are possible, the array will contain up, down, left, (invalid). The count will be n = 3.)
if n == 0 (all blocked) terminate loop
get a random number from 0 to n - 1 (Example: 0..2)
select the direction from the array (Example: random number 1 will select down)
move in the selected direction (it has been checked before that it is possible)

Index Value goes to 5 million for nested for loop - C

I am programming a board game and I need to assign character values to a 2D array. To do this, I am using a nested for loop with the i as the row index and j as the column index. With a 4x4 dimension (n=4) The loop works fine until the second row. Using the debugger on codelite, I've noticed that the value of j does not increase from 0 to 1 like it should, but it increases to 5,560,570, disrupting the loop. I've also noticed that when using a dimension larger than 4, the program fails to display anything at all. Is this a memory error? I am stumped and have showed this to multiple other people as well.
int main(void){
int n;
char board[n][26];
printf("Enter the board dimension: ");
scanf("%d", &n);
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if((i == (n/2)-1 && j == (n/2)-1) || (i == (n/2) && j == (n/2))){
board[i][j] = 'W';
}
else if((i == (n/2) && j == (n/2)-1) || (i == (n/2)-1 && j == (n/2))){
board[i][j] = 'B';
}
else{
board[i][j] = 'U';
}
}
}
It appears that you are using n before you set it, in the declaration of board. Because this is undefined behavior, absolutely anything is permitted to happen; in this case, that is disrupting the value of other variables.
To fix this, you should probably wait until after initializing n in scanf to declare board, like so:
int main(void) {
int n;
printf("Enter the board dimension: ");
scanf("%d", &n);
char board[n][26];
...
}
As has been pointed out in the comments, this still will cause problems if n > 26, and can be wasteful for n != 26. Due to the way that arrays work in C, fixing that would probably require rethinking how the board is stored altogether.

Time complexity of a function with while loops and an if statement

int dup_chk(int a[], int length)
{
int i = length;
while (i > 0)
{
i--;
int j = i -1;
while (j >= 0)
{
if (a[i] == a[j])
{
return 1;
}
j--;
}
}
return 0;
}
So what I think I know is the following:
line 1 is just 1.
First while loop is N+1.
i--; is N times since its inside the first while loop.
j = i -1; is also N.
Second while loop is (N+1)N = N^2+N since its a while loop within a while loop
if statement: ???
j--; is N(N) = N^2
return 0; is 1
I'm really new to calculating the time complexity of algorithms so I'm not even sure if what I think I know is completely right.
But what is messing with me is the if statement, I do not know how to calculate that (and what if there is an else after it as well?)
EDIT: The grand total is equal to 3/2N^2 + 5/2N+3
I understand that this function is O(N^2) but don't quite get how the grand total was calculated.
Usually such accurate analysis of time complexity is not required. It suffices to know it in terms of Big-O. However, I did some calculations for my own curiosity.
If your concern is just a worst case analysis to obtain the time complexity, consider an array with only unique elements. In such a scenario:
The return 1 statement never executes. The inner while loop executes N(N-1)/2 times (summation i-1 from 1 to N), and three things happen - the while condition is checked (and evaluates to true), the if condition is checked (and evaluates to false) and the variable j is decremented. Therefore, the number of operations is 3N(N-1)/2.
The outer while loop executes N times, and there are three statements apart from the condition check - i is decremented, j is assigned, and the inner while condition fails N times. That is 4N more operations.
Outside all loops, there are three more statements. Initialisation of i, the while condition fails once, and then the return statement. Add 3 more to our tally.
3/2N2 - 3/2N + 4N + 3.
That's 3/2N2 + 5/2N + 3. There is your 'grand total'.
To repeat myself, this calculation is completely unnecessary for all practical purposes.
Maybe this can help you understand what goes wrong in your code. I have added some printout that make easier to understand what happens in your code. I think this should be sufficient to find your error
int dup_chk(int a[], int length)
{
int j = 0;
int i = length;
char stringa[30];
printf("Before first while loop j = %d and i = %d \n", j, i);
while (i > 0)
{
i--;
j = i - 1;
printf("\tIn first while loop j = %d and i = %d\n", j, i);
while (j >= 0)
{
printf("\t\tIn second while loop j = %d and i = %d\n", j, i);
if (a[i] == a[j])
{
printf("\t\tIn if statment j = %d and i = %d\n", j, i);
return 1;
}
j--;
printf("\t\tEnd of second while loop j = %d and i = %d\n", j, i);
}
}
printf("After first while loop j = %d and i = %d \n", j, i);
printf("Press any key to finish the program and close the window\n");
return 0;
}
I should also recomend to debug your code understand what goes on better.
The if check is executed as many times as the inner while loop iterates.
The return 1 is by definition only executed once max. It appears you assume there are no duplicates in the input (ie. worst case), in which case the return 1 statement never executes.
You'll eventually get a feel for what parts of the code you can ignore, so you won't need to calculate this "grand total", and just realize there are two nested loops that each traverse the array - ie. O(N^2).
int dup_chk(int a[], int length)
{
int i = length;
while (i > 0) // Outer loop
{
i--;
int j = i -1;
while (j >= 0) // Inner loop
{
if (a[i] == a[j])
{
return 1;
}
j--;
}
}
return 0;
}
The above program is exactly your code with two comments I took the liberty to add.
Let's consider the worst case scenario (because that's what everyone cares / is worried about). If you notice carefully, you will observe that for every value of i, the Inner loop executes i - 1 times. Thus if your Outer loop executes n times, the Inner loop will execute n * (n - 1) times in total (i.e. n - 1 times for each value of n).
n * (n - 1) yields n^2 - n in general algebra. Now, n^2 increases in leaps and bounds (as compared to n) as you go on increasing the value of n. Asymptotic notation let's us consider the factor which will have the greatest impact on the number of steps to be executed. Thus, we can ignore n and say that this program has a worst case running time of O(n^2).
That's the beauty and simplicity of the Big-O notation. - Quoting Jonathan Leffler from the comments above.
Thorough evaluation:
This program has a special feature: it terminates if a pair (a[I], a[J]) of equal values is found. Assume that we know I and J (we will see later what if there is no such pair).
The outer loop is executed for all I <= i < L, hence L-I times. Each time, the inner loop is executed for all 0 <= j < i, hence i times, except for the last pass (i = I): we have J <= j < I hence I-J iterations.
We assume that the "cost" of a loop is of the form a N + b, where a is the cost of a single iteration and b some constant overhead.
Now for the inner loop, which is run L-I times with decreasing numbers of iterations, using the "triangular numbers" formula, the cost is
a (L-1 + L-2 + ... I+1 + I-J) + b (L - I) = a ((L-1)L/2 - I(I+1)/2 + I-J) + b (L-I)
to which we add the cost of the outer loop to get
a ((L-1)L/2 - I(I+1)/2 + I-J) + b (L-I) + c
(where b is a different constant than above).
In general, this function is quadratic in L, but if a pair is found quickly (say I = L-3), it becomes linear; in the best case (I = L-1,J = L-2), it is even the constant a + b + c.
The worst case occurs when the pair is found last (I = 1, J = 0), which is virtually equivalent to no pair found. Then we have
a (L-1)L/2 + b (L - 1) + c
obviously O(L²).

finding subsets dicretely c

for (i = 0; i < (pow(2,n)-1); i++) {
x = binary_conversion(i);
for (j = (n-1); j > 0; j--) {
if (x == 0) {
M[i][j] = 0;
}
else {
M[i][j] = x % 10;
x = x / 10;
}
}
}
i want to print the subsets of a set, so for a set of n elements i get the value of 2^n. from 0 to 2^n, i'm converting the values to binary. and i am keeping the binary values in a matrice and as i go through the matrice, if the value is 1, i am printing the corresponding element of the original set.But while creating the matrice, it assigns the same binary value to two consecutive rows so at the end i can not even get half of the subsets. What do you think is wrong with the code?
Ah because you don't cover the LSB or the 0th element. for (j = (n-1); j >= 0; j--) You missed the =.
Also you have to know if j-th bit is set in i or not.
And instead of pow you can simply use (1<<n)[Equivalent to 2^n]
Your code is not readable. I will post the pseudocode.
for ( int i = 0; i<= (1<<numOfSetElmts)-1; i++)
{
//print Subset-i
for(int pos = 0; pos<=n-1;pos++)
if( i&(1<<pos) )
print Set[pos]
}
Why am I not using pow?
The pow function is implemented by an algorithm and uses floating point functions and values to compute the power value.
So power of floating point to the power n is not necessarily multiplying it repetitively n times. As a result you end up with some errors and execution is a bit slower too.
Bitwise is faster?
Yes it is. Even if modern implementation are making changes to the architecture as a whole but still you won't lose the performance by using bitwise. Most of them it will have better performance than addition operation, if not equal.
Your program have worst complexity. There are better solutions for this problem with minimum complexity. Anyway the problem of your code is put '<='
i <= pow(2,n)-1
Also you can use i < 1<<n Both work same but second one is better and faster. The same problem happens in the inner loop where you didn't put '=' sign. ie, j>=0 . Else the program was good.
The better solution for your problem may look like this.
void subsets(char A[], int N)
{
int i,j;
for( i = 0;i < (1 << N); ++i)
{
for( j = 0;j < N;++j)
if(i & (1 << j))
printf("%c ", A[j] );
printf("\n");
}
}
In this there is no external binary conversion or matrix needed.

Leetcode: Four Sum

Problem: Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0.
A solution set is:
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)
I know there's an O(n^3) solution to this problem, but I was wondering if there's a faster algorithm. I googled a lot and found that many people gave an O(n^2logn) solution, which fails to correctly deal with cases when there are duplicates of pair sums in S (like here
and here). I hope someone can give me a correct version of an O(n^2logn) algorithm if it really exists.
Thanks!
The brute-force algorithm takes time O(n^4): Use four nested loops to form all combinations of four items from the input, and keep any that sum to the target.
A simple improvement takes time O(n^3): Use three nested loops to form all combinations of three items from the input, and keep any that sum to the negative of the target.
The best algorithm I know is a meet-in-the-middle algorithm that operates in time O(n^2): Use two nested loops to form all combinations of two items from the input, storing the pairs and totals in some kind of dictionary (hash table, balanced tree) indexed by total. Then use two more nested loops to again form all combinations of two items from the input, and keep the two items from the nested loops, plus the two items from the dictionary, for any pair of items that sums to the negative of a total in the dictionary.
I have code at my blog.
IMHO, for O(n^2lgn) algorithm, the problem of duplicates can be solved when creating the aux[] array. (I'm using the name in the second link you provided). The basic idea is first sort the elements in the input, and then while processing the array, skip the duplicates.
vector<int> createAuxArray(vector<int> input) {
int len = input.size();
vector<int> aux;
sort(input.begin(), input.end());
for (int i = 0; i < len; ++i) {
if (i != 0 && input[i] == input[i - 1]) continue; // skip when encountered a duplicate
for (int j = i + 1; j < len; ++j) {
if (j != i + 1 && input[j] == input[j - 1]) continue; // same idea
aux.push_back(createAuxElement(input[i], input[j]);
}
}
return aux;
}
Complexity for this module is O(nlgn) + O(n^2) = O(n^2), which doesn't affect the overall performance. Once we have created aux array, we can plug it into the code mentioned in the post and the results will be correct.
Note that a BST or hashtable can be used to replace the sorting, but in general it doesn't decrease the complexity since you have to insert/query (O(lgN)) inside 2-nested loop.
This is a modified version of the geeksforgeeks solution which handles duplicates of pair sums as well. I noticed that some of the pairs were missing because the hash table was overwriting the old pairs when it found new pair that satisfies the sum. Thus, the fix is to avoid overwriting by storing them in a vector of pairs. Hope this helps!
vector<vector<int> > fourSum(vector<int> &a, int t) {
unordered_map<int, vector<pair<int,int> > > twoSum;
set<vector<int> > ans;
int n = a.size();
for (int i = 0; i < n; i++) for (int j = i + 1; j < n; j++) twoSum[a[i] + a[j]].push_back(make_pair(i, j));
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (twoSum.find(t - a[i] - a[j]) != twoSum.end()) {
for (auto comp : twoSum[t - a[i] - a[j]]) {
if (comp.first != i and comp.first != j and comp.second != i and comp.second != j) {
vector<int> row = {a[i], a[j], a[comp.first], a[comp.second]};
sort(row.begin(), row.end());
ans.insert(row);
}
}
}
}
}
vector<vector<int> > ret(ans.begin(), ans.end());
return ret;
}

Resources