I have a problem with this piece of code in C.
#include <stdio.h>
#include <stdint.h>
typedef uint64_t bboard;
// Accessing a square of the bitboard
int
get (bboard b, int square)
{
return (b & (1ULL << square));
}
void
print_board (bboard b)
{
int i, j, square;
for (i = 7; i >= 0; i--) // rank => top to bottom
{
for (j = 0; j < 8; j++) // file => left to right
printf ("%d ", get (b, j+8*i) ? 1 : 0);
printf ("\n");
}
}
int
main ()
{
bboard b = 0xffffffffffffffff;
print_board (b);
}
// result that I have
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 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
Ok, why the bitboard is not set with all bit at 1?
For any question please add a comment. Ty :D
get returns an int, but (b & (1ULL << square)) is a uint64_t. When (b & (1ULL << square)) is greater than INT_MAX, the result is undefined; in this case it truncates and returns 0.
If get returns a bboard instead, this works as expected (verified here: http://codepad.org/zEZiJKeR).
Related
I found here an implementation for Hoshen-Kopelman Algorithm, But it checks neighbors only up and left, meaning that a diagonal connection is not considered a connection.
How can I improve this code so that even a diagonal connection will be considered a connection?
In the following example I expect 1 object and not 7 objects:
4 5
1 0 1 0 1
0 1 0 1 0
1 0 1 0 0
0 0 1 0 0
--input--
1 0 1 0 1
0 1 0 1 0
1 0 1 0 0
0 0 1 0 0
--output--
1 0 2 0 3
0 4 0 5 0
6 0 7 0 0
0 0 7 0 0
HK reports 7 clusters found
This is the implementation (full code can be found here):
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* Implementation of Union-Find Algorithm */
/* The 'labels' array has the meaning that labels[x] is an alias for the label x; by
following this chain until x == labels[x], you can find the canonical name of an
equivalence class. The labels start at one; labels[0] is a special value indicating
the highest label already used. */
int* labels;
int n_labels = 0; /* length of the labels array */
/* uf_find returns the canonical label for the equivalence class containing x */
int uf_find(int x)
{
int y = x;
while (labels[y] != y)
y = labels[y];
while (labels[x] != x)
{
int z = labels[x];
labels[x] = y;
x = z;
}
return y;
}
/* uf_union joins two equivalence classes and returns the canonical label of the resulting class. */
int uf_union(int x, int y)
{
return labels[uf_find(x)] = uf_find(y);
}
/* uf_make_set creates a new equivalence class and returns its label */
int uf_make_set(void)
{
labels[0] ++;
assert(labels[0] < n_labels);
labels[labels[0]] = labels[0];
return labels[0];
}
/* uf_intitialize sets up the data structures needed by the union-find implementation. */
void uf_initialize(int max_labels)
{
n_labels = max_labels;
labels = calloc(sizeof(int), n_labels);
labels[0] = 0;
}
/* uf_done frees the memory used by the union-find data structures */
void uf_done(void)
{
n_labels = 0;
free(labels);
labels = 0;
}
/* End Union-Find implementation */
#define max(a,b) (a>b?a:b)
#define min(a,b) (a>b?b:a)
/* print_matrix prints out a matrix that is set up in the "pointer to pointers" scheme
(aka, an array of arrays); this is incompatible with C's usual representation of 2D
arrays, but allows for 2D arrays with dimensions determined at run-time */
void print_matrix(int** matrix, int m, int n)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
printf("%3d ", matrix[i][j]);
printf("\n");
}
}
/* Label the clusters in "matrix". Return the total number of clusters found. */
int hoshen_kopelman(int** matrix, int m, int n)
{
uf_initialize(m * n / 2);
/* scan the matrix */
for (int y = 0; y < m; y++)
{
for (int x = 0; x < n; x++)
{
if (matrix[y][x])
{ // if occupied ...
int up = (y == 0 ? 0 : matrix[y - 1][x]); // look up
int left = (x == 0 ? 0 : matrix[y][x - 1]); // look left
switch (!!up + !!left)
{
case 0:
matrix[y][x] = uf_make_set(); // a new cluster
break;
case 1: // part of an existing cluster
matrix[y][x] = max(up, left); // whichever is nonzero is labelled
break;
case 2: // this site binds two clusters
matrix[y][x] = uf_union(up, left);
break;
}
}
}
}
/* apply the relabeling to the matrix */
/* This is a little bit sneaky.. we create a mapping from the canonical labels
determined by union/find into a new set of canonical labels, which are
guaranteed to be sequential. */
int* new_labels = calloc(sizeof(int), n_labels); // allocate array, initialized to zero
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (matrix[i][j])
{
int x = uf_find(matrix[i][j]);
if (new_labels[x] == 0)
{
new_labels[0]++;
new_labels[x] = new_labels[0];
}
matrix[i][j] = new_labels[x];
}
int total_clusters = new_labels[0];
free(new_labels);
uf_done();
return total_clusters;
}
/* This procedure checks to see that any occupied neighbors of an occupied site
have the same label. */
void check_labelling(int** matrix, int m, int n)
{
int N, S, E, W;
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (matrix[i][j])
{
N = (i == 0 ? 0 : matrix[i - 1][j]);
S = (i == m - 1 ? 0 : matrix[i + 1][j]);
E = (j == n - 1 ? 0 : matrix[i][j + 1]);
W = (j == 0 ? 0 : matrix[i][j - 1]);
assert(N == 0 || matrix[i][j] == N);
assert(S == 0 || matrix[i][j] == S);
assert(E == 0 || matrix[i][j] == E);
assert(W == 0 || matrix[i][j] == W);
}
}
/* The sample program reads in a matrix from standard input, runs the HK algorithm on
it, and prints out the results. The form of the input is two integers giving the
dimensions of the matrix, followed by the matrix elements (with data separated by
whitespace).
a sample input file is the following:
8 8
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1
1 0 0 0 0 1 0 1
1 0 0 1 0 1 0 1
1 0 0 1 0 1 0 1
1 0 0 1 1 1 0 1
1 1 1 1 0 0 0 1
0 0 0 1 1 1 0 1
this sample input gives the following output:
--input--
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1
1 0 0 0 0 1 0 1
1 0 0 1 0 1 0 1
1 0 0 1 0 1 0 1
1 0 0 1 1 1 0 1
1 1 1 1 0 0 0 1
0 0 0 1 1 1 0 1
--output--
1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 1
2 0 0 0 0 2 0 1
2 0 0 2 0 2 0 1
2 0 0 2 0 2 0 1
2 0 0 2 2 2 0 1
2 2 2 2 0 0 0 1
0 0 0 2 2 2 0 1
HK reports 2 clusters found
*/
int main(int argc, char** argv)
{
int m, n;
int** matrix;
/* Read in the matrix from standard input
The whitespace-deliminated matrix input is preceeded
by the number of rows and number of columns */
while (2 == scanf_s("%d %d", &m, &n))
{ // m = rows, n = columns
matrix = (int**)calloc(m, sizeof(int*));
for (int i = 0; i < m; i++)
{
matrix[i] = (int*)calloc(n, sizeof(int));
for (int j = 0; j < n; j++)
scanf_s("%d", &(matrix[i][j]));
}
printf_s(" --input-- \n");
print_matrix(matrix, m, n);
printf(" --output-- \n");
/* Process the matrix */
int clusters = hoshen_kopelman(matrix, m, n);
/* Output the result */
print_matrix(matrix, m, n);
check_labelling(matrix, m, n);
printf("HK reports %d clusters found\n", clusters);
for (int i = 0; i < m; i++)
free(matrix[i]);
free(matrix);
}
return 0;
}
I tried to change the function hoshen_kopelman as described below, but I still get 2 objects instead of 1:
int hoshen_kopelman(int** matrix, int m, int n)
{
uf_initialize(m * n / 2);
/* scan the matrix */
for (int y = 0; y < m; y++)
{
for (int x = 0; x < n; x++)
{
if (matrix[y][x])
{ // if occupied ...
int up = (y == 0 ? 0 : matrix[y - 1][x]); // look up
int left = (x == 0 ? 0 : matrix[y][x - 1]); // look left
// ----------- THE NEW CODE -------------
if (x > 0)
{
if (up == 0 && y > 0) // left+up
up = matrix[y - 1][x - 1];
if (left == 0 && y < m - 1) // left+down
left = matrix[y + 1][x - 1];
}
// ---------- END NEW CODE --------------
switch (!!up + !!left)
{
case 0:
matrix[y][x] = uf_make_set(); // a new cluster
break;
case 1: // part of an existing cluster
matrix[y][x] = max(up, left); // whichever is nonzero is labelled
break;
case 2: // this site binds two clusters
matrix[y][x] = uf_union(up, left);
break;
}
}
}
}
/* apply the relabeling to the matrix */
/* This is a little bit sneaky.. we create a mapping from the canonical labels
determined by union/find into a new set of canonical labels, which are
guaranteed to be sequential. */
int* new_labels = calloc(sizeof(int), n_labels); // allocate array, initialized to zero
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
if (matrix[i][j])
{
int x = uf_find(matrix[i][j]);
if (new_labels[x] == 0)
{
new_labels[0]++;
new_labels[x] = new_labels[0];
}
matrix[i][j] = new_labels[x];
}
int total_clusters = new_labels[0];
free(new_labels);
uf_done();
return total_clusters;
}
The following output is now obtained (I am expecting 1 and got 2):
4 5
1 0 1 0 1
0 1 0 1 0
1 0 1 0 0
0 0 1 0 0
--input--
1 0 1 0 1
0 1 0 1 0
1 0 1 0 0
0 0 1 0 0
--output--
1 0 1 0 1
0 1 0 1 0
2 0 1 0 0
0 0 1 0 0
HK reports 2 clusters found
What is the correct way to correct the code to check all 8 neighbors?
I led you astray saying to check down-left. The algorithm relies on the current node it is examining being after all the neighbors it checks. So you need to check left, up, up-left, and up-right. You can use this in place of your new code:
if (y > 0)
{
if (left == 0 && x > 0) // left+up
left = matrix[y - 1][x - 1];
if (up == 0 && x < n-1) // right+up
up = matrix[y - 1][x + 1];
}
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));
}
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 :-)
I have a short variable (16 bits) and an index (unsigned char).
I need a macro that returns the indexth in my variable data.
This is what I got:
#define GETBIT(data, index) data & 1 << index
And how I use it:
unsigned char i;
short * twobytes = (short *) calloc(1, sizeof(short));
twobytes = ((char * )buffer + *currentIndex);
while (codeLength != 0)
{
i = GETBIT(code, codeLength--);
*twobytes = SETBIT(*twobytes, *currentBitIndex, i);
(*currentBitIndex)++;
if (*currentBitIndex == 8) {
(*currentIndex)++;
(*currentBitIndex) %= 8;
}
}
For some reason i always equals to 0 in my test cases, where it sometimes should equal 1.
What am I doing wrong and how should I fix it?
Thanks.
Nevermind, thanks, instead of codeLength-- I should've done --codeLength.
Example:
$ cat qq.c
#include <stdio.h>
#define GETBIT(data, index) ((data & (1 << index)) == 0 ? 0 : 1)
int main() {
const int x = 14;
int i;
for (i = 0; i < 32; i++) {
printf("%d ", GETBIT(x, i));
}
printf("\n");
return 0;
}
Run:
$ gcc -Wall qq.c && ./a.out
0 1 1 1 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 0 0 0
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++.