C read big matrix from input file - c

Im trying to read a 40000x40000 boolean (binary) matrix from a input file and store it in a variable. After I store it in the variable, I want to write it to a file. However, with the code I wrote it takes more than a hour. Can someone help me out? I think im doing something wrong.
Code
void get_grid_values_file(bool *grid, int n, int m, char *input_filename){
FILE *in_file;
in_file = fopen(input_filename, "r");
char buffer[1];
bool search = true;
int k=0;
while(search){
fseek(in_file, k, SEEK_SET);
fread(buffer, 1, 1, in_file);
if(*buffer == '\n')
search = false;
k++;
}
int i,j;
for(i=0; i<n; i++){
for(j=0; j<m; j++){
fseek(in_file, k, SEEK_SET);
fread(buffer, 1, 1, in_file);
*((grid+i*m) + j) = atof(buffer);
k+=2;
}
}
fclose(in_file);
}
void set_grid_values_file(bool *grid, int n, int m, char *output_filename){
FILE *out_file;
out_file = fopen(output_filename, "w");
char buffer[1] = " ";
//Set n,m and spaces
int length_n= (int) (log10 (abs (n))) + 1;
char char_n[length_n];
sprintf(char_n, "%d", n);
fseek(out_file, 0, SEEK_SET);
fwrite (char_n, length_n, 1, out_file);
fseek(out_file, length_n, SEEK_SET);
fwrite (" ", 1, 1, out_file);
int length_m= (int) (log10 (abs (m))) + 1;
char char_m[length_m];
sprintf(char_m, "%d", m);
fseek(out_file, length_n+1, SEEK_SET);
fwrite (char_m, length_m, 1, out_file);
fseek(out_file, length_n+1+length_m, SEEK_SET);
fwrite ("\n", sizeof(char), 1, out_file);
//Set grid
int i,j;
int k =length_n + length_m + 2;
for(i=0; i<n; i++){
for(j=0; j<m; j++){
fseek(out_file, k, SEEK_SET);
buffer[0] = (*((grid+i*m) + j) == true ? '1' : '0');
fwrite (buffer, 1, 1, out_file);
k++;
fseek(out_file, k, SEEK_SET);
fwrite (" ", 1, 1, out_file);
k++;
}
fseek(out_file, k, SEEK_SET);
fwrite ("\n", sizeof(char), 1, out_file);
k++;
}
}
int main(int argc, char *argv[])
{
char *input_filename = "gen0_40kx40k.in";
char *output_filename = "gol_output.out";
int n = 40000;
int m = 40000;
bool *grid = (bool *)malloc(n*m*sizeof(bool));
//Read
get_grid_values_file((bool *)grid, n, m, input_filename);
//Write
set_grid_values_file((bool *)grid, n, m, output_filename);
return 0;
}
Input format, the first line contains the dem of the 2d matrix:
20 20
1 0 1 0 0 1 0 0 1 0 1 0 1 0 1 1 0 1 0 0
1 1 0 0 0 0 0 1 0 1 1 1 1 0 0 1 0 0 1 1
0 1 1 0 1 0 1 1 0 0 0 1 1 0 0 1 1 0 0 1
1 0 1 1 0 1 0 0 1 0 1 1 1 0 1 0 1 1 1 1
1 1 0 0 0 0 0 1 0 0 0 0 0 1 1 1 0 1 1 1
1 1 1 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 0 1
1 1 1 0 0 0 1 1 1 0 0 1 1 1 1 1 0 0 1 1
0 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1 0 0 1
1 0 0 0 0 1 1 0 1 1 1 1 0 1 1 1 0 0 0 0
1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 1 0 1 1 0
0 1 1 0 0 0 1 1 0 1 1 0 0 1 0 1 1 1 1 1
0 0 0 1 1 1 1 1 0 0 1 0 1 1 0 0 1 1 1 0
1 0 0 1 0 0 0 1 1 1 0 1 1 0 0 0 1 1 0 0
0 1 0 1 0 1 1 0 0 0 0 1 1 0 1 1 0 1 0 1
1 0 0 0 0 0 1 1 0 1 1 0 0 0 1 1 1 1 1 1
1 1 1 0 1 0 1 1 1 1 0 0 1 0 1 1 0 0 1 0
1 0 0 1 0 0 0 1 1 1 1 0 0 0 1 1 0 0 0 1
0 0 0 1 0 1 1 1 1 0 1 0 0 0 1 1 0 0 0 1
1 1 1 0 1 0 1 1 1 0 1 1 0 1 0 1 0 1 0 1
1 1 1 0 1 0 1 1 0 1 0 0 1 0 0 0 0 1 0 1

Read larger chunks from the input file - not every char as a separate call. Eg a complete row of your matrix at once.
Why do you use in the inner loop of set_grid_values_file two fwrite calls. Better to combine them:
char buffer[2] = " ";
for(i=0; i<n; i++){
int base = grid+i*m;
for(j=0; j<m; j++){
fseek(out_file, k, SEEK_SET);
buffer[0] = (*(base + j) ? '1' : '0');
fwrite (buffer, 1, 2, out_file);
k+=2;
}

I would suggest removing the calls to fseek.
while(search){
// Make sure the read is successful. Otherwise, break out of the loop.
if ( fread(buffer, 1, 1, in_file) != 1 )
{
break;
}
if(*buffer == '\n')
search = false;
k++;
}
int i,j;
// Rewind the file
fseek(in_file, 0, SEEK_SET);
for(i=0; i<n; i++){
for(j=0; j<m; j++){
// Make sure the read is successful. Otherwise, break out of the loop.
if ( fread(buffer, 1, 1, in_file) != 1 )
{
break;
}
*((grid+i*m) + j) = atof(buffer);
k+=2;
}
}
Also atof(buffer) is a problem when buffer has only one element in it. Use at least a two element array.
char buffer[2] = {0};

This is about the simplest(and possibly the fastest) method.
stdio is buffered, getc() is most probably a macro
function calls are costly (they trash the instruction pipeline and cache) ; you use 1seek+1fread per boolean bit read.
you dont need to seek the file; just read it sequentially and put the values at the correct{row,col} positions.
setting and testing an indicator variable (your search) is a waste of time (often taught in Pascal and Java classes...) ;instead: just jump out of the loop (or continue)
I am assuming an ASCII file with spaces between the values, but without the{nrow,ncol} at the top (the{n,m}values are supplied as function arguments)
void get_grid_values_file(bool *grid, int n, int m, char *input_filename)
{
unsigned col,row;
FILE * fp;
fp= fopen (input_filename, "r" );
if(!fp)return;
for(row=col=0; ; ) {
int ch;
ch=getc(fp);
if (ch == EOF)break;
if (ch < '0' || ch > '1') continue;
grid[row*m+col++] = (ch == '0') ? False :True;
if (col == m) {col=0; row++; }
if (row == n) break;
}
fclose(fp);
return;
}

Related

2D array - I want to find which columns have 1s in them in each row

My input looks like this :
15 5
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0
0 1 0 1 0
0 0 1 0 0
0 0 0 0 1
0 0 0 0 0
0 0 0 0 0
0 1 0 0 0
1 0 0 0 1
0 0 1 0 0
0 0 0 1 0
The first row contains the number of rows and columns of my array. And basically I want to find out where these 1s are in the array.
So in the first 3 rows i want to get 3, in the 7th 1, and in the 8th, i want to get 2 3 etc..
My code looks like this so far
#include <stdio.h>
int main() {
int row, column;
FILE* input;
FILE* output;
input = fopen("input.txt", "r");
if (input == 0) {
printf("ERROR couldn't open input.txt");
return 1;
}
if (! fscanf(input, "%d %d", &row, &column)) {
printf("ERROR not recognised value");
fclose(input);
return 2;
}
output = fopen("output.txt", "w");
int meteor[row][column];
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
fscanf(input, "%d", &meteor[i][j]);
}
}
int sum;
int loc[row];
for (int i = 0; i < row; i++) {
sum = 0;
for (int j = 0; j < column; j++) {
sum += meteor[i][j];
if (meteor[i][j] == 1) {
loc[i] = (j + 1);
}
}
printf("%d %d\n", loc[i], sum);
}
fclose(input);
fclose(output);
return 0;
}
My output is this :
3 1
3 1
3 1
0 0
-1 0
1 1
4 2
3 1
5 1
0 0
4214921 0
2 1
5 2
3 1
4 1
The first column shows some of the locations, the second shows how many 1s are in the row, but it all fails when there are only 0s in the row or there is more than one 1. And also I would like to store these values.
You need to initialize loc[].. If you look carefully at your code, you only populate it on the condition of if (meteor[i][j] == 1)... but you print it for every index of i. which would print uninitialized memory (i.e. unknown).
To answer the second part of your question, if you want to store the "sum". Simply make loc[] a 2d array just like meteor, but with 2 columns (row and sum). i.e. int loc[row][2].. making sure to initialize both columns of course :)

Bit mask with 0's in C

I need to build a method in C that will return an int, take 3 ints as parameters. The first and second int are the starting and ending bit position. The third int is a 0 or 1 to determine the type of mask.
For example,
getMask(2, 6, 1);
//Set bits 2 to 6 to 1, set all others to zero
should set the bits 2 through 6 to a 1 and all other bits to zero.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0
So getMask(2, 6, 1) should return the integer 124.
And getMask(11, 31, 0) (set bits 11 to 31 to 0) should return 2047.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1
This is what I have currently:
#include <stdio.h>
int getM(int start, int end, int choice) {
if (choice == 1){
return ~(~0 << (end - start + 1)) << (start);
}
else if (choice == 0){
return ~(~1 << (end - start + 1)) << (start);
}
else{
return 0;
}
}
It works when I the choice is 1, but for 0 I am completely lost.
I currently get -2048 for getMask(11, 31, 0).
I know I can use ands and ors, but I cannot figure out how to use them the way I am doing this.
#AnttiHaapala is correct: choice==0 is just the bitwise negation of choice==1 for the same start and end. Therefore (as an MCVE):
#include <stdio.h>
int getM(int start, int end, int choice) {
if (choice == 1){
return ~(~0 << (end - start + 1)) << (start);
}
else if (choice == 0){
return ~getM(start, end, 1); /* Just use what you have, but ~ it */
}
else{
return 0;
}
}
int main() {
printf("2 6 1 %d\n", getM(2,6,1));
printf("11 31 0 %d\n", getM(11,31,0));
}

Clusters of a matrix(array)

So. I am working in C and I need some help. I have a matrix(array) (I do not now how to translate it right :D ) that has only 0 and 1 in it. For example, one could look like this:
1 1 0 0 0 0
1 1 0 1 0 0
1 0 0 0 0 1
0 0 1 1 0 1
0 0 1 0 1 1
Now. I need to extract from it the clusters that contain 1. Can you write me some ideas on how to approach this? I tried with a structure and a **pointer to it, with the structure containing 2 elements : x and y, x for x coordinate in the original matrix and y for the y coordinate in the matrix. Then, for each cluster, it would look like :
cluster[0][0].x = 0;
cluster[0][0].y = 0;
cluster[0][1].x = 1;
cluster[0][1].y = 0;
cluster[0][2].x = 0;
cluster[0][2].y = 1;
.. and so on. But I have some problems with the iteration( I have a 1000*1000 matrix) and I decided to ask you if you have any other ideas. Thanks.
EDIT: These are the clusters in this example:
1:
1 1 0 0 0 0
1 1 0 0 0 0
1 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
2:
0 0 0 0 0 0
0 0 0 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
3:
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 1 0 0
0 0 1 0 0 0
4:
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1
0 0 0 0 0 1
0 0 0 0 1 1
EDIT2:
So. From that matrix of 1 and 0 and I nee to extract all groups of adjacent "1"'s. Adjacent means neighbouring on either up down left or right from it's position. As for the first cluster would be the one made up from those 5 "1"'s from the beginning of the matrix. Another cluster would be that that contains only one "1" on line 2 column 4. And I need somehow to store the x and y coordinate of each cluster somewhere, as I need to use them later on.
For string the data, just an array
char map[1000][1000]
that'll use 1 megabyte of memory, which is not a lot these days.
An algorithm as I see it is
find a 1 in the matrix,
do a flood-fill on it (eg changing 1 to 2 or to 0)
then continue searhcing for a 1 in the matrix.
return the number of fills needed to convert all the 1s.
Flood fill is a well known algorithm, you should be able to find a suitable example, or possibly use a graphics library.
A simple implemention
Use the backtracking to get all clusters, let's start from (0,0) as an example, we first check if (0,0) is 1, if so, check its neighbors one by one. If one of the neighbors is 1, move there and check in the same way. this process doesn't stop until the position's four direction neighbors are all 0 or visited.
To record the position we visited, we need a flag map which has the same size as origin array.
Besides, to draw each cluster, during the backtracking, we record each postion at the same time, I choose a set of list to save all positions in a cluster.
here is all code, including test case you post
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#define MAX_COL 6
#define MAX_ROW 5
#define MAX_SIZE (MAX_COL * MAX_ROW)
int a[5][6] = {
1, 1, 0, 0, 0, 0,
1, 1, 0, 1, 0, 0,
1, 0, 0, 0, 0, 1,
0, 0, 1, 1, 0, 1,
0, 0, 1, 0, 1, 1,
};
int dir_x[4] = {0, 1, 0, -1};
int dir_y[4] = {1, 0, -1, 0};
struct point {
int x;
int y;
};
struct node {
struct point pos;
struct node *next;
};
struct node* cluster_set[MAX_SIZE];
int cluster_set_index = 0;
int is_inside(int height, int width, int i, int j)
{
if (0 <= j && j < width && i >= 0 && i < height)
return 1;
return 0;
}
int cluster_check(int (*matrix)[MAX_COL], int height, int width, int row, int col, int (*flag_matrix)[MAX_COL], struct node* head)
{
int i, tmp_x, tmp_y;
flag_matrix[row][col] = 1;
for (i = 0; i < 4; i++)
{
tmp_x = row + dir_x[i];
tmp_y = col + dir_y[i];
if (is_inside(height, width, tmp_x, tmp_y) && matrix[tmp_x][tmp_y] && !flag_matrix[tmp_x][tmp_y]) {
flag_matrix[tmp_x][tmp_y] = 1;
struct node *new_node = (struct node*)malloc(sizeof(struct node));
assert(new_node != NULL);
new_node -> pos.x = tmp_x;
new_node -> pos.y = tmp_y;
new_node -> next = NULL;
head -> next = new_node;
cluster_check(matrix, height, width, tmp_x, tmp_y, flag_matrix, new_node);
}
}
}
int cluster_count(int (*matrix)[MAX_COL], int height, int width)
{
int count = 0, i, j;
int flag_matrix[MAX_ROW][MAX_COL] = {0};
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
{
if (matrix[i][j] && !flag_matrix[i][j]) {
count++;
struct node *new_node = (struct node*)malloc(sizeof(struct node));
assert(new_node != NULL);
new_node -> pos.x = i;
new_node -> pos.y = j;
new_node -> next = NULL;
cluster_set[cluster_set_index++] = new_node;
cluster_check(matrix, height, width, i, j, flag_matrix, new_node);
}
}
return count;
}
void print_cluster(int (*map)[MAX_COL], int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
printf("%2d ", map[i][j]);
printf("\n");
}
printf("\n");
}
int main()
{
printf("total clusters: %d\n", cluster_count(a, 5, 6));
int i, cluster_map[MAX_ROW][MAX_COL] = {0};
struct node *tmp;
for (i = 0; i < cluster_set_index; i++)
{
tmp = cluster_set[i];
while (tmp != NULL) {
printf("(%d, %d)", tmp->pos.x, tmp->pos.y);
cluster_map[tmp->pos.x][tmp->pos.y] = 1;
tmp = tmp -> next;
}
printf("\n");
print_cluster(cluster_map, MAX_ROW, MAX_COL);
memset(cluster_map, 0x00, sizeof(int)*MAX_ROW*MAX_COL);
}
}
and here is the running results, just ignore the infomation you don't need
total clusters: 4
(0, 0)(0, 1)(1, 1)(1, 0)(2, 0)
1 1 0 0 0 0
1 1 0 0 0 0
1 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
(1, 3)
0 0 0 0 0 0
0 0 0 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
(2, 5)(3, 5)(4, 5)(4, 4)
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1
0 0 0 0 0 1
0 0 0 0 1 1
(3, 2)(4, 2)
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
0 0 1 0 0 0

Using C, While initializing an array of structs, it seems like the first column, and the last column are overlooping

When main runs, I've been getting this output. The first columns being somehow confused with the last one, even though it's specifically initialized.
0 0 0 0 0 0 4 3 13 3 3 0 0 0 0 0 0
0 0 0 0 0 4 0 0 5 0 0 2 0 0 0 0 0
0 0 0 0 4 0 0 0 5 0 0 0 2 0 0 0 0
0 0 0 18 0 0 0 0 5 0 0 0 0 17 0 0 0
0 0 4 0 2 0 7 12 19 12 3 0 8 0 2 0 0
0 4 0 0 0 0 0 0 5 0 0 0 0 0 0 2 0
0 0 0 0 5 0 0 0 5 0 0 0 5 0 0 0 2
2 0 0 0 11 0 0 0 5 0 0 0 11 0 0 0 1
1 7 7 7 20 7 7 7 14 7 7 7 20 7 7 7 1
1 0 0 0 11 0 0 0 5 0 0 0 11 0 0 0 1
1 0 0 0 1 0 0 0 5 0 0 0 1 0 0 0 0
0 6 0 0 0 0 0 0 5 0 0 0 0 0 0 8 0
0 0 6 0 4 0 7 12 19 12 3 0 6 0 8 0 0
0 0 0 15 0 0 0 0 5 0 0 0 0 16 0 0 0
0 0 0 0 6 0 0 0 5 0 0 0 8 0 0 0 0
0 0 0 0 0 6 0 0 5 0 0 8 0 0 0 0 0
0 0 0 0 0 0 7 7 7 7 8 0 0 0 0 0 0
motion.h
struct square{
int directions;
int isRobotHere;
int isMultipleDirections;
int printable;
};
typedef struct square Square;
struct robot{
int robotx;
int roboty;
int robotz;
int destinationx;
int destinationy;
int destinationz;
};
typedef struct robot Robot;
enum direction{North, NorthWest, West, SouthWest, South, SouthEast, East, NorthEast};
Square firstfloor[16][16];
Square secondfloor[16][16];
void printbothfloors();
void initializeArrays();
initializeArrays.c
#include <stdio.h>
#include "motion.h"
void initializeArrays(){
firstfloor[6][0].directions=5;
firstfloor[7][0].directions=5;
firstfloor[8][0].directions=14;
firstfloor[9][0].directions=5;
firstfloor[10][0].directions=6;
firstfloor[11][1].directions=6;
firstfloor[12][2].directions=6;
firstfloor[13][3].directions=15;
firstfloor[14][4].directions=6;
firstfloor[15][5].directions=6;
firstfloor[16][6].directions=7;
firstfloor[16][7].directions=7;
firstfloor[16][8].directions=7;
firstfloor[16][9].directions=7;
firstfloor[16][10].directions=8;
firstfloor[15][11].directions=8;
firstfloor[14][12].directions=8;
firstfloor[13][13].directions=16;
firstfloor[12][14].directions=8;
firstfloor[11][15].directions=8;
firstfloor[10][16].directions=1;
firstfloor[9][16].directions=1;
firstfloor[8][16].directions=1;
firstfloor[7][16].directions=1;
firstfloor[6][16].directions=2;
firstfloor[5][15].directions=2;
firstfloor[4][14].directions=2;
firstfloor[3][13].directions=17;
firstfloor[2][12].directions=2;
firstfloor[1][11].directions=2;
firstfloor[0][10].directions=3;
firstfloor[0][9].directions=3;
firstfloor[0][8].directions=13;
firstfloor[0][7].directions=3;
firstfloor[0][6].directions=4;
firstfloor[1][5].directions=4;
firstfloor[2][4].directions=4;
firstfloor[3][3].directions=18;
firstfloor[4][2].directions=4;
firstfloor[5][1].directions=4;
firstfloor[1][8].directions=5;
firstfloor[2][8].directions=5;
firstfloor[3][8].directions=5;
firstfloor[4][8].directions=19;
firstfloor[5][8].directions=5;
firstfloor[6][8].directions=5;
firstfloor[7][8].directions=5;
firstfloor[8][8].directions=14;
firstfloor[9][8].directions=5;
firstfloor[10][8].directions=5;
firstfloor[11][8].directions=5;
firstfloor[12][8].directions=19;
firstfloor[13][8].directions=5;
firstfloor[14][8].directions=5;
firstfloor[15][8].directions=5;
firstfloor[8][1].directions=7;
firstfloor[8][2].directions=7;
firstfloor[8][3].directions=7;
firstfloor[8][4].directions=20;
firstfloor[8][5].directions=7;
firstfloor[8][6].directions=7;
firstfloor[8][7].directions=7;
firstfloor[8][9].directions=7;
firstfloor[8][10].directions=7;
firstfloor[8][11].directions=7;
firstfloor[8][12].directions=20;
firstfloor[8][13].directions=7;
firstfloor[8][14].directions=7;
firstfloor[8][15].directions=7;
firstfloor[7][4].directions=11;
firstfloor[9][4].directions=11;
firstfloor[4][7].directions=12;
firstfloor[4][9].directions=12;
firstfloor[12][7].directions=12;
firstfloor[12][9].directions=12;
firstfloor[7][12].directions=11;
firstfloor[9][12].directions=11;
firstfloor[4][4].directions=2;
firstfloor[4][6].directions=7;
firstfloor[4][10].directions=3;
firstfloor[4][12].directions=8;
firstfloor[6][4].directions=5;
firstfloor[6][12].directions=5;
firstfloor[10][4].directions=1;
firstfloor[10][12].directions=1;
firstfloor[12][4].directions=4;
firstfloor[12][6].directions=7;
firstfloor[12][10].directions=3;
firstfloor[12][12].directions=6;
firstfloor[11][0].directions=0;
firstfloor[5][16].directions=0;
}
printbothfloors.c
#include <stdio.h>
#include <stdlib.h>
#include "motion.h"
void printbothfloors(){
// printf("printfloor is running");
int upper, lower, i, j;
printf("%4d %4d %4d %4d %4d", firstfloor[6][0].directions, firstfloor[7][0].directions, firstfloor[8][0].directions, firstfloor[9][0].directions, firstfloor[10][0].directions);
printf("%4d %4d %4d %4d %4d", firstfloor[6][16].directions, firstfloor[7][16].directions, firstfloor[8][16].directions, firstfloor[9][16].directions, firstfloor[10][16].directions);
printf("FIRST FLOOR");
printf("\n-");
/* The next for loop prints out the upper edge */
for (upper = 0; upper < 18; upper++){
printf("----");
}
printf("\n");
/*The next for loop prints out the floor, every element is 4 digits wide */
for (i = 0; i <= 16; i++){
printf("|");
for(j = 0; j <= 16; j++){
printf("%4d", firstfloor[i][j].directions);
}
printf(" |\n");
}
/* The next for loop prints out the lower edge */
for (lower = 0; lower < 18; lower++){
printf("----");
}
printf("-\n");
/*
printf("SECOND FLOOR");
// printf("printfloor is running");
printf("\n-----");
// The next for loop prints out the upper edge
for (upper = 0; upper < 17; upper++){
printf("----");
}
printf("\n");
//The next for loop prints out the floor, every element is 4 digits wide
for (i = 0; i <= 16; i++){
printf("|");
for(j = 0; j <= 16; j++){
printf("%4d", secondfloor[i][j].directions);
}
printf(" |\n");
}
// The next for loop prints out the lower edge
for (lower = 0; lower < 17; lower++){
printf("----");
}
printf("-----\n");
*/
}
prog2.c
#include <stdio.h>
#include <stdlib.h>
#include "motion.h"
//#include "printbothfloors.h"
int main(){
int row = 0;
int column = 0;
initializeArrays();
// printbothfloors();
/*
for (row=0; row < 17; row++){
for (column=0; column < 17; column++){
// firstfloor[row][column].directions=0;
// secondfloor[row][column].directions=5;
//firstfloor[i][j].isRobotHere=0;
//secondfloor[i][j].isRobotHere=0;
//firstfloor[i][j].isMultipleDirections=0;
//secondfloor[i][j].isMultipleDirections=0;
}
}
firstfloor[6][0].directions=5;
firstfloor[7][0].directions=5;
firstfloor[8][0].directions=14;
firstfloor[9][0].directions=5;
firstfloor[10][0].directions=6;
firstfloor[11][1].directions=6;
firstfloor[12][2].directions=6;
firstfloor[13][3].directions=15;
firstfloor[14][4].directions=6;
firstfloor[15][5].directions=6;
firstfloor[16][6].directions=7;
firstfloor[16][7].directions=7;
firstfloor[16][8].directions=7;
firstfloor[16][9].directions=7;
firstfloor[16][10].directions=8;
firstfloor[15][11].directions=8;
firstfloor[14][12].directions=8;
firstfloor[13][13].directions=16;
firstfloor[12][14].directions=8;
firstfloor[11][15].directions=8;
firstfloor[10][16].directions=1;
firstfloor[9][16].directions=1;
firstfloor[8][16].directions=1;
firstfloor[7][16].directions=1;
firstfloor[6][16].directions=2;
firstfloor[5][15].directions=2;
firstfloor[4][14].directions=2;
firstfloor[3][13].directions=17;
firstfloor[2][12].directions=2;
firstfloor[1][11].directions=2;
firstfloor[0][10].directions=3;
firstfloor[0][9].directions=3;
firstfloor[0][8].directions=13;
firstfloor[0][7].directions=3;
firstfloor[0][6].directions=4;
firstfloor[1][5].directions=4;
firstfloor[2][4].directions=4;
firstfloor[3][3].directions=18;
firstfloor[4][2].directions=4;
firstfloor[5][1].directions=4;
firstfloor[1][8].directions=5;
firstfloor[2][8].directions=5;
firstfloor[3][8].directions=5;
firstfloor[4][8].directions=19;
firstfloor[5][8].directions=5;
firstfloor[6][8].directions=5;
firstfloor[7][8].directions=5;
firstfloor[8][8].directions=14;
firstfloor[9][8].directions=5;
firstfloor[10][8].directions=5;
firstfloor[11][8].directions=5;
firstfloor[12][8].directions=19;
firstfloor[13][8].directions=5;
firstfloor[14][8].directions=5;
firstfloor[15][8].directions=5;
firstfloor[8][1].directions=7;
firstfloor[8][2].directions=7;
firstfloor[8][3].directions=7;
firstfloor[8][4].directions=20;
firstfloor[8][5].directions=7;
firstfloor[8][6].directions=7;
firstfloor[8][7].directions=7;
firstfloor[8][9].directions=7;
firstfloor[8][10].directions=7;
firstfloor[8][11].directions=7;
firstfloor[8][12].directions=20;
firstfloor[8][13].directions=7;
firstfloor[8][14].directions=7;
firstfloor[8][15].directions=7;
firstfloor[7][4].directions=11;
firstfloor[9][4].directions=11;
firstfloor[4][7].directions=12;
firstfloor[4][9].directions=12;
firstfloor[12][7].directions=12;
firstfloor[12][9].directions=12;
firstfloor[7][12].directions=11;
firstfloor[9][12].directions=11;
firstfloor[4][4].directions=2;
firstfloor[4][6].directions=7;
firstfloor[4][10].directions=3;
firstfloor[4][12].directions=8;
firstfloor[6][4].directions=5;
firstfloor[6][12].directions=5;
firstfloor[10][4].directions=1;
firstfloor[10][12].directions=1;
firstfloor[12][4].directions=4;
firstfloor[12][6].directions=7;
firstfloor[12][10].directions=3;
firstfloor[12][12].directions=6;
firstfloor[11][0].directions=0;
firstfloor[5][16].directions=0;
*/
// for (i = 0; i < 17; i++){
// firstfloor
// printbothfloors();
// pbf_entrypoints();
/*
row = 0;
column = 0;
while (i < 17){
firstfloor[i][8] = 1;
secondfloor[i][8] = 1;
firstfloor[8][i] = 1;
secondfloor[8][i] = 1;
i++;
}
*/
printf("Function got here");
printbothfloors();
return 0;
}
Valid indices for Type arr[N] are between 0 and N-1.
This goes for any Type and for any number of dimensions.
Indexes in C start at 0, so if you declare an array to have 16 elements, valid indexes start from 0 and end at 15.
16 boxes, numbered 0 to 15:
---------------------------------------------------------------------------------
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
---------------------------------------------------------------------------------
Accessing an element outside of this range (e.g. by using the index -1 or 16) invokes undefined behaviour.
Both the first answers are correct, I'll add some examples from your code.
firstfloor[6][16].directions
firstfloor[x][y], has been initialized as firstfloor[16][16] meaning the values x and y can can from 0 to 15. The numbering system is 0 based, a hang-over from Java's C language ancestry. 0-15 covers 16 elements.
/*The next for loop prints out the floor, every element is 4 digits wide */
for (i = 0; i <= 16; i++){
printf("|");
for(j = 0; j <= 16; j++){
printf("%4d", firstfloor[i][j].directions);
}
printf(" |\n");
}
The two for loops, start correctly at i = 0 and should only continue while i < 16 or if you prefer i <= 15.
At the moment I'm personally jumping between Java, C and Python, so someone might correct me in this, but calling firstfloor[6][16] if it does not generate an array out-of-bounds error, will give you the same result as firstfloor[7][0]. This might explain why you are observing the first columns being confused with the last.
Good luck :-)

Generate Binary Sequence

I want to generate permutations of string of 5 0s followed by the permutations of 4 0s and a single 1, followed by the permutations of 3 0s with 2 1s etc? My code is as follows:
#include<stdio.h>
int main(){
int i,j,k,l,s[5];
for(i=0;i<5;i++)
s[i]=0;
for(k=0;k<5;k++)
printf("%d ",s[k]);
printf("\n");
printf("---------------------------------------------\n");
for(i=0;i<5;i++){
for(j=0;j<5;j++)
if(i==j)
s[j]=1;
else
s[j]=0;
for(k=0;k<5;k++)
printf("%d ",s[k]);
printf("\n");
}
printf("---------------------------------------------\n");
for(i=0;i<5;i++){
for(k=0;k<5;k++)
s[k]=0;
s[i]=1;
for(j=i+1;j<5;j++){
s[j]=1;
for(k=0;k<5;k++)
printf("%d ",s[k]);
printf("\n");
for(k=j;k<5;k++)
s[k]=0;
}
}
printf("---------------------------------------------\n");
for(i=0;i<5;i++){
for(j=i+1;j<5;j++){
for(k=0;k<5;k++)
s[k]=0;
s[i]=1;
s[j]=1;
for(l=j+1;l<5;l++){
s[l]=1;
for(k=0;k<5;k++)
printf("%d ",s[k]);
printf("\n");
for(k=l;k<5;k++)
s[k]=0;
}
}
}
}
So output is
0 0 0 0 0
---------------------------------------------
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
---------------------------------------------
1 1 0 0 0
1 0 1 0 0
1 0 0 1 0
1 0 0 0 1
0 1 1 0 0
0 1 0 1 0
0 1 0 0 1
0 0 1 1 0
0 0 1 0 1
0 0 0 1 1
---------------------------------------------
1 1 1 0 0
1 1 0 1 0
1 1 0 0 1
1 0 1 1 0
1 0 1 0 1
1 0 0 1 1
0 1 1 1 0
0 1 1 0 1
0 1 0 1 1
0 0 1 1 1
Output is ok. However in my code I use
different for loops for different cases.
Is it possible to use better approach so
that length of the code is reduced?
One approach follows. This solution needs O(n) space and each output string requires O(n) time.
#include <stdio.h>
#include <stdlib.h>
char *buf;
// Print combinations of m 1's in a field of n 0/1's starting at s.
void print_combinations(char *s, int n, int m)
{
// If there is nothing left to append, we are done. Print the buffer.
if (m == 0 && n == 0) {
*s = '\0';
printf("%s\n", buf);
return;
}
// Cut if there are more 1's than positions left or negative numbers.
if (m > n || m < 0 || n < 0) return;
// Append a 0 and recur to print the rest.
*s = '0';
print_combinations(s + 1, n - 1, m);
// Now do the same with 1.
*s = '1';
print_combinations(s + 1, n - 1, m - 1);
}
int main(void)
{
int n = 5;
buf = malloc(n + 1);
for (int m = 0; m <= n; m++) {
print_combinations(buf, n, m);
printf("-----\n");
}
return 0;
}
You could use a recursive function like so - you don't have to print the result when finished, you could add it to a list etc.
The function works by starting with an empty string. At each step you add one more character - in this case you add either a 0 or a 1.
If a 1 is added we account for this by decrementing the ones value on the next call to the function. (In a more general case you could pass a list of all the elements to be permuted - then the process would be to pick from this list, add it to your permutation and remove it from the list. You repeat that until the list is empty and you have permuted all of the elements in the list.)
When the string reaches the desired length we have finished and so we return.
#include <stdio.h>
void recurse(char *str, int length, int maxLength, int ones)
{
if (length == maxLength)
{
// we are finished
printf("%s\n", str);
return;
}
if (ones > 0)
{
// put a 1 into the new string
str[length] = '1';
recurse(str, length + 1, maxLength, ones - 1);
}
if (ones < maxLength - length)
{
// there are still spaces for 0s
// put a 0 into the string
str[length] = '0';
recurse(str, length + 1, maxLength, ones);
}
}
int main()
{
const int maxLength = 5;
char buffer[maxLength + 1];
buffer[maxLength] = 0;
int ones;
for (ones = 0; ones <= maxLength; ones++)
{
printf("Ones: %i\n", ones);
recurse(buffer, 0, maxLength, ones);
printf("\n");
}
return 0;
}
The output looks like this:
Ones: 0
00000
Ones: 1
10000
01000
00100
00010
00001
Ones: 2
11000
10100
10010
10001
01100
01010
01001
00110
00101
00011
Ones: 3
11100
11010
11001
10110
10101
10011
01110
01101
01011
00111
Ones: 4
11110
11101
11011
10111
01111
Ones: 5
11111
Finally, unless you really want to/need to learn/use C, I would recommend using C++ because you get really nice features like std::vector and std::set and so many other things which will make your life so much easier. I would have written this completely different in C++.

Resources