check 2d array diagonally? - c

I'm trying to search a 3x3 2d array diagonally, like this:
I want to check if all boxes in the diagonal have the same value. Here is how I try to do it:
thisOne = board[0][2]; //set to 'X'
for(i = 0; i<3; i++) {
for(j = 3; j>0; j--){
if(board[i][j-1] != thisOne) {
thisOne= '\0';
}
}
}
//since all boxes were 'X', thisOne is still set to 'X'
if(thisOne != '\0') {
winner = thisOne;
printf("vinnare på nördöst\n");
}
So after running this code, winner should be 'X', if all boxes are X's. But the code does not do that, why is that?

You need to check only diagonal cells instead of checking all the cells.

You are not breaking/exiting the check loop when the first not matching char is retrieved.
Moreover your nested for does not what you guess: inner one loops into all columns of each row, but you want to che only the diagonal values...
You can easily a simple while
int i=0;
int j=2;
while ((i<3) && (j>=0) && (board[i][j] == thisOne))
{
i++;
j--;
}
// if i<3 the diagonal is not full of thisOne char
if ( i < 3)
{
}

As said by #BLUEPIXY, the problem is that the j loop is nested inside the i loop. So for every iteration in the i loop, the j loop runs 3 times on every column, instead of just working on the minor diagonal. There are several ways to fix this, although the most optimal way would be to use only one single loop and only one variable i.
for(i=0;i<3;i++) {
if(board[i][2-i]!=thisOne) {
thisOne='\0'
break;
}
}

To achieve your goal you'd simply need to decrement X iterator & Y iterator when going through your array.
Here is a simple example:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int arr[3][3];
int it_y;
int it_x;
it_y = 0;
it_x = 2;
arr[0][0] = 0;
arr[0][1] = 1;
arr[0][2] = 2;
arr[1][0] = 3;
arr[1][1] = 4;
arr[1][2] = 5;
arr[2][0] = 6;
arr[2][1] = 7;
arr[2][2] = 8;
while (it_x < 3 && it_x >= 0)
{
printf("[%d][%d]: '%d'\n", it_y, it_x, arr[it_y][it_x]);
--it_x;
++it_y;
}
return EXIT_SUCCESS;
}

You can do like
for(int row=0,col=2; row<3; row++,col--)
{
if(board[row][col] != thisOne)
{
thisOne= '\0';
}
}

You can only check diagonal elements like this
for(i = 0, j = 3-1; i < 3; i++, j--) {
if(board[i][j] != thisOne) {
thisOne = '\0';
}
}

Related

Have I written the Selection Sort Algoithm in C the right way?

A question in my book explained selection sort in three lines and then asked the reader to write CODE for it in C. I have written the code here and it is working fine, but I am a little confused whether I have written it in the right way or not. Please read the code, I have even added comments and correct me if needed.
#include <stdio.h>
#define VALUESIZE 10
int main(void)
{
int temp;
int value[VALUESIZE] = {3, 5, 46, 89, 72, 42, 312, 465812, 758, 1};
// Printing array just for the user to see.
for (int k=0; k<VALUESIZE; k++)
{
printf("[");
printf("%d", value[k]);
printf("] ");
}
printf("\n");
// Sorting algo begins
for (int i=0; i < VALUESIZE - 1; i++) // This will obviously loop through each element in our array except the last element as it will automatically be sorted after n-1 steps
{
for (int j= i+1; j <= VALUESIZE; j++) // This nested loop will go through each element which appears after ith element. For e.g. If i = 2, then j will loop through entire array starting from j = 3
{
if (value[i] > value[j]) // This basic if statement will compare our ith and following jth value
{
temp = value[i]; // If the program finds any value[j] greater than value[i], then the values will be swapped.
value[i] = value[j];
value[j] = temp;
}
}
}
// Now after sorting, print the new sorted array.
for (int l=0; l<VALUESIZE; l++)
{
printf("[");
printf("%d", value[l]);
printf("] ");
}
printf("\n");
}
Select sort needs to iterate through the array to compare the ith value. At the end of this pass it will swap the 2 values. This is a reason why its not a very good sort algorithm for medium or large arrays.
I have changed your code a bit below
Untested but should work:
// Sorting algo begins
for (int i = 0; i < arr_length - 1; i++)
{
int min = i;
for (int j = i + 1; j <= arr_length; j++)
{
if (value[j] < value[min])
{
min = j;
}
}
//now swap
int cache = value[min];
value[min] = value[i];
value[i] = cache;
}

How to compare jagged array to another array in C?

I've been trying to use a jagged array for a project of mine, meanwhile this is just a test furthermore I'll use it in my project. The question is the following How could I compare each element from each array, so in the code below I have three arrays, after them, I have one more which will be used to compare to the first ones,here what I have so far.
#include <stdio.h>
#include <stdlib.h>
int main(){
int row0[4] = {0,1,3,0};
int row1[4] = {5,6,9,10};
int row2[4] = {9,0,1,10};
int aux[4] = {9,6,9,10};
int *result[3] = {row0,row1,row2};
int size[3] = {4,4,4}, k =0;
for (int i = 0; i < 3; i++) {
int *ptr = result[i];
for (int j = 0; j < size[k]; j++) {
if(ptr[j] == aux[j])
{
printf("%d\n",ptr[j]);
}
ptr++;
}
printf("\n");
k++;
result[i]++;
}
return 0;
}
The result of it is 5, but I'd like to loop over all the values from the array that starts with 5, to find out if the all the other values are equal, in other words I want to know which array is equal to the "aux" array.
You have the (inner) loop:
int *ptr = result[i];
for (int j = 0; j < size[k]; j++)
{
if(ptr[j] == aux[j])
{
printf("%d\n",ptr[j]);
}
ptr++;
}
Since you increment both j and ptr, you're doing far too much incrementing. It's probably best to remove the ptr++; line.

Array element disappears

I'm trying to track a player's location with x marking their spot. When the player enters a string I increment the coordinates accordingly. However when the player is located one space from the perimeter, then attempts to move to the edge of the map, the player disappears.
Example:
.....
...x.
.....
.....
.....
Player located at 'x'
If player enters string "right" and I move player_loc, array simply returns:
.....
.....
.....
.....
.....
I attempted to add a sort of buffer by increasing the size of the array. No luck. I've been stuck on this for almost a week now. Any help would be appreciated. I apologize for messy code. I'm a total newbie at this and I'm really just futzing around in the dark with all this stuff. I've researched this across the forums here and haven't found a solution. If you know of something that I possibly (probably) missed feel free to point me in that direction.
#include <stdio.h>
#include <string.h>
char map[6][6];
char player_loc = 'x';
int row;
int col;
void init_map()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
map[i][j] = '.';
}
}
}
void print_map()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
printf("%c", map[i][j]);
}
printf("\n");
}
}
int get_player_loc()
{
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 5; k++) {
if(map[j][k] == player_loc)
{
row = k;
col = j;
}
}
}
return row;
return col;
}
void init_player_loc()
{
int check = 1;
for (int g = 0; g < 5; g++) {
for (int h = 0; h < 5; h++) {
if (map[g][h] == 'x') {
check = 0;
}
}
}
if(check == 1) {
map[0][0] = player_loc;
} else {
get_player_loc();
}
}
void move_left()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j-1] = player_loc;
map[i][j] = '.';
}
}
}
}
void move_right()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
}
}
}
}
int main(int argc, char* argv[])
{
char input[15];
printf("You enter a room...you can go left, right, or straight. Which way do you go?\n");
int done = 0;
init_map();
map[3][3] = player_loc;
//init_player_loc();
print_map();
while (!done) {
scanf("%s", input);
if (strcmp("left", input) == 0) {
move_left();
printf("You go left...\n");
print_map();
get_player_loc();
printf("%d %d\n", row, col);
done = 1;
}
else if (strcmp("right", input) == 0) {
move_right();
printf("You go right...\n");
print_map();
get_player_loc();
printf("%d %d\n", row, col);
done = 1;
}
else if (strcmp("straight", input) == 0) {
printf("You go straight...");
done = 1;
}
else {
printf("Sorry, can't do that.\n");
}
}
}
You must break the loop if you find the player location, e.g
void move_right()
{
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
return;
}
}
}
}
In your code you move right the player, and the next loop will find the player in the new location and do the right move again, forever.
Moreover in your code you are not taking care of boundaries of your 2d matrix: j+1 is valid only if j<5.
Then a better code should be
void move_right()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
return;
}
}
}
}
The problem is that your move_right function picks up the player and moves them completely off of the map. Let's say your player is at [0, 2] and step through the code.
for (int j = 0; j < 5; j++) {
if (map[i][j] == player_loc) {
map[i][j+1] = player_loc;
map[i][j] = '.';
}
}
[0, 0] No player here, move along
[0, 1] No player here, move along
[0, 2] Found a player! Move them right to [0, 3]
[0, 3] Found a player! Move them right to [0, 4]
[0, 4] Found a player! Move them right to [0, 5]
At 5, the loop ends. Because of the buffer you added, your array is 6x6, so the player is stashed in the wings without crashing the program. There are a few things you should do:
Once you've found and moved the player, break or return so they'll only move once.
Make your array 5x5 (or print all 6x6) so you can see everything.
Do some bounds checking so the player isn't allowed to move right from j = 5.
Watch out for this same bug in move_up, where it would happen as you increment i.
Your loops allow for checking the position twice, once at i,j, and again at i,(j+1) (or some other variant). This probably isn't what you intend. After you find the player you should make the updates and then break out of the loops.
Also, the code as is allows for indexing passed the bounds of the array, in theory. Also not what is desired. You may consider bounds checking. I don't know what is supposed to happen when the player moves right and there is a wall to the right. Does he not move? Wrap around? LR corner could cause seg fault as it is now.
You appear to have row and column indeces transposed in the get_player_loc function, as well as having two return statements (the compiler should warn you about unreachable code), neither of which is required or used by the calling code.
At the start, initialise the row and col variables. (Values taken from your main.)
int row = 3;
int col = 3;
Change the get_player_loc function so that it just updates the globals row and col. It sets row and col to 0 if the player is not found, as per the original.
void get_player_loc(void)
{
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 5; k++) {
if(map[j][k] == player_loc)
{
// The meaning of row and col is set by how they are used
// to index the array in the move and print functions. Keep
// the same order and meaning here.
row = j;
col = k;
return;
}
}
}
// Set row and col to 0 if the location is not found.
row = 0;
col = 0;
map[0][0] = player_loc;
}
You'll still have problems when they reach an edge, due to the index into the array going out of bounds in the move functions, but that's a different problem.

Nested for/while loops and arrays, filtering out numbers from an array

int main(void)
{
int i,j=0,k; //initialization
char equation[100]; //input is a string (I think?)
int data[3]; //want only 3 numbers to be harvested
printf("Enter an equation: ");
fgets(equation, 100, stdin); //not so sure about fgets()
for (i = 0; i < equation[100]+1; i++) { //main loop which combs through
//"equation" array and attempts
//to find int values and store
while (j <= 2) { //them in "data" array
if (isdigit(equation[i])) {
data[j] = equation[i]
j++;
}
}
if (j == 2) break;
}
for (k = 0; k <= 2; k++) { //this is just to print the results
printf("%d\n", data[k]);
}
return 0;
}
Hello! This is my program for my introductory class in C, I am trying to comb through an array and pluck out the numbers and assign them to another array, which I can then access and manipulate.
However, whenever I run this I get 0 0 0 as my three elements in my "data" array.
I am not sure whether I made an error with my logic or with the array syntax, as I am new to arrays.
Thanks in advance!!! :)
There are a few problems in your code:
for (i = 0; i < equation[100]+1; i++) { should be something like
size_t equ_len = strlen(equation);
for (i = 0; i < equ_len; i++) {
Whatever the input is, the value of equation[100] is uncertain, because char equation[100];, equation only has 100 element, and the last of them is equation[99].
equation[i] = data[j]; should be
data[j] = equation[i];
I suppose you want to store digit in equation to data.
break; should be deleted.
this break; statement will jump out of the while loop, the result is you will store the last digit in equation to data[0] (suppose you have switched data and equation, as pointed out in #2).
If you want the first three digits in equation, you should do something like
equ_len = strlen(equation);
j = 0;
for (i = 0; i < equ_len; i++) {
if (j <= 2 && isdigit(equation[i])) {
data[j] = equation[i];
j++;
}
if (j > 2) break;
}
printf("%d\n", data[k]); should be printf("%c\n", data[k]);
%d will give the ASCII code of data[k], for example, if the value of data[k] is character '1', %d will print 50 (the ASCII code of '1') instead of 1.
Here is my final code, based on the OP code:
#include <ctype.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
int i,j,k;
char equation[100];
int data[3];
int equ_len;
printf("Enter an equation: ");
fgets(equation, 100, stdin);
equ_len = strlen(equation);
j = 0;
for (i = 0; i < equ_len; i++) {
if (j <= 2 && isdigit(equation[i])) {
data[j] = equation[i];
j++;
}
if (j > 2) break;
}
for (k = 0; k <= 2; k++) {
printf("%c\n", data[k]);
}
return 0;
}
Tested with:
$ ./a.out
Enter an equation: 1 + 2 + 3
1
2
3

Find the duplicate elements in a two-dimensional array

I need to find the duplicate elements in a two dimensional array.
route_ptr->route[0][1] = 24;
route_ptr->route[0][2] = 18;
route_ptr->route[1][1] = 25;
route_ptr->route[2][1] = 18;
route_ptr->route[3][1] = 26;
route_ptr->route[3][2] = 19;
route_ptr->route[4][1] = 25;
route_ptr->route[4][2] = 84;
Those are my data; the duplicate entries of route[2][1] (duplicate of route[0][2]) and route[4][1] (duplicate of route[1][1]) has to be found.
The solution is the duplicate 'i' value of route[i][j] which is 2 & 4 from this example.
please guide me.
#include <stdio.h>
struct route{
int route[6][6];
int no_routes_found;
int count_each_route[6];
};
int main() {
struct route *route_ptr, route_store;
route_ptr=&route_store;
int i,j,k;
// the data
route_ptr->route[0][1] = 24;
route_ptr->route[0][2] = 18;
route_ptr->route[1][1] = 25;
route_ptr->route[2][1] = 18;
route_ptr->route[3][1] = 26;
route_ptr->route[3][2] = 19;
route_ptr->route[4][1] = 25;
route_ptr->route[4][2] = 84;
route_ptr->count_each_route[0]=3;
route_ptr->count_each_route[1]=2;
route_ptr->count_each_route[2]=2;
route_ptr->count_each_route[3]=3;
route_ptr->count_each_route[4]=3;
route_ptr->no_routes_found=5;
//// process
for (i = 0; i <(route_ptr->no_routes_found) ; i++)
{
for (j = 1; j < route_ptr->count_each_route[i]; j++)
{
printf("\nroute[%d][%d] = ", i, j);
printf("%d",route_ptr->route[i][j]);
}
}
}
The solution expected is:
route[0][1] is compared by route [0][2] i.e [24 !=18]
route[0][1] and route [0][2] is compared by route[1][1] i.e [24 && 18 !=25]
route[0][1] and route[0][2] and route[1][1] is compared by route[2][1] i.e [ 24&&18&&25 is compared by 18, there is a matching element,
save the newcomer 'i' value which matches to the existence and drop it for next checking]
break the 'i' loop
route[0][1], route[0][2], route[1][1] is now compared route[3][1]
route[0][1], route[0][2], route[1][1] ,[3][1] is now compared route[3][2]
route[0][1], route[0][2], route[1][1] ,[3][1] ,[3][2] is now compared to route [4][1] i.e [ now there is a match to route[1][1], so save the newcomer 'i' value and break the 'i' loop
So i values [2 and 4] are duplicate, and that is my expected result of my code.
Got something against index zero, zero?
I also don't see the point of the pointer shenanigans.
It's a general safety thing to initialize all your data. You know, to zero or something.
The algorithm you suggest in your solution is rather hard to be faithful to, but this will find your duplicates. You have to walk through the entire array, in both dimensions, twice.
This will also match all the zeroes in your data, so you could add an exception to ignore routes values of zero.
//Cycling through the array the first time.
for (i = 0; i < 6 ; i++)
{
for (j = 0; j < 6; j++)
{
//Cycling through the array the second time
for (x = 0; x < 6 ; x++)
{
for (y = 0; y < 6; y++)
{
if(i==x && j==y)
continue;
if(routestore.route[i][j] == routestore.route[x][y])
printf("You have a match [%d][%d] = [%d][%d]", i, j, x,y);
}
}
}
}
Ok, so if you only want to see matches once, ie [0][2] == [2][1] but not [2][1] == [0][2], then you can do something like what I have below. This one made me scratch my head. Usually, when it's a simple list of items, you initialize the inner loop to the value of the outer loop, plus one. But you can't quite do that when it's a 2D array. So I gave up and made a super-lame hack-job. I'm a big fan of brute forcing things when possible. I'd normally tell you not to use pointers like this.
Now... this will still have multiple hits if you have three similar values. If that irks you then you need to start building a list and comparing hits against that as you walk through the data.
#include <stdio.h>
#include <string.h>
struct route{
int route[6][6];
int no_routes_found;
int count_each_route[6];
};
int lameAddOneAlternative(int *i, int *j)
{
if((*j)<6)
{
(*j)++;
return 1;
}
else if (*i<6)
{
(*i)++;
(*j) = 0;
return 1;
}
return 0;
}
int main(int argc, char **argv)
{
struct route routeStore;
int i,j,x,y;
memset(routeStore.route,0,sizeof(int)*36);
// the data
routeStore.route[0][1] = 24;
routeStore.route[0][2] = 18;
routeStore.route[1][1] = 25;
routeStore.route[2][1] = 18;
routeStore.route[3][1] = 26;
routeStore.route[3][2] = 19;
routeStore.route[4][1] = 25;
routeStore.route[4][2] = 84;
//Cycling through the array the first time.
for (i = 0; i < 6 ; i++)
{
for (j = 0; j < 6; j++)
{
x=i;
y=j;
//Cycling through the array the second time
while(lameAddOneAlternative(&x,&y))
{
if(routeStore.route[i][j] == 0 )
continue;
if(routeStore.route[i][j] == routeStore.route[x][y])
printf("You have a match [%d][%d], [%d][%d] == %d\n", i, j, x,y, routeStore.route[i][j] );
}
}
}
}
for (i = 0; i <(route_ptr->no_routes_found) ; i++)
{
for (j = 1; j < route_ptr-> count_each_route[i]; j++)
{
for (x = 0; x < (route_ptr->no_routes_found) ; x++)
{
for (y = 0; y < route_ptr-> count_each_route[x]; y++)
{
if(i==x && j==y)
continue;
if(route_ptr->route[i][j] == route_ptr->route[x][y])
printf("You have a match [%d][%d] = [%d][%d]\n", i, j, x,y);
}
}
}

Resources