Most effective way to find combinations in C - c

#include <stdio.h>
#include <stdlib.h>
int chessboard[8][8];
int indicator, x, i, j, b, checksum, testerint, temp, row, column;
int rescounter, resstarter;
void togglecolumn(int columnumber) {
//
for (j = 0; j < 8; j++) {
//
chessboard[j][columnumber] = toggleint(chessboard[j][columnumber]);
}
}
void togglerow(int rownumber) {
//
for (j = 0; j < 8; j++) {
//
chessboard[rownumber][j] = toggleint(chessboard[rownumber][j]);
}
}
void fulltoggle(int i, int j) {
//
togglerow(i);
togglecolumn(j);
chessboard[i][j] = toggleint(chessboard[i][j]);
}
int toggleint(int a) {
//
if (a == 0) {
b = 1;
}
if (a == 1) {
b = 0;
}
return b;
}
void fillchessboard() {
x = 1;
//
for (i = 0; i < 8; i++) {
x = toggleint(x);
for (j = 0; j < 8; j++) {
//
chessboard[i][j] = x;
x = toggleint(x);
}
}
}
void showchessboard() {
//
printf("------------------- \n \n");
for (i = 0; i < 8; i++) {
//
for (j = 0; j < 8; j++) {
//
if (j == 7) {
//if end of the row
printf("%d \n", chessboard[i][j]);
} else {
//
printf("%d ", chessboard[i][j]);
}
}
}
printf("\n \n");
printf("------------------- \n \n");
}
int checkboard() {
checksum = 0;
for (i = 0; i < 8; i++) {
//
for (j = 0; j < 8; j++) {
//
if (chessboard[i][j] == 1) {
//
return 1;
}
}
}
return 0;
}
void rowcolindicator(int i) {
//
if (i % 8 == 0) {
column = 7;
row = i / 8 - 1;
} else {
row = i / 8;
column = i % 8 - 1;
}
}
// for proper operation i should be chosen 0
int recurfuntion(int i, int stepcounter) {
if (stepcounter != 0) {
stepcounter--;
temp = i;
for (i = temp + 1; i < 65; i++) {
//do row and column for
rowcolindicator(i);
fulltoggle(row, column);
recurfuntion(i, stepcounter);
}
if (i == 65) {
i = temp++;
rowcolindicator(temp);
fulltoggle(row, column);
stepcounter++;
}
} else {
//
temp = i;
for (i = temp + 1; i < 65; i++) {
//do row and column for i code and return iteration number if board turns all right
rowcolindicator(i);
fulltoggle(row, column);
if (checkboard() == 0) {
//
showchessboard();
return 1;
} else {
//
fulltoggle(row, column);
}
}
if (i == 65) {
i = temp++;
rowcolindicator(temp);
fulltoggle(row, column);
stepcounter++;
//showchessboard();
}
}
}
int main(int argc, char *argv[]) {
fillchessboard();
showchessboard();
indicator = checkboard();
printf("indicator is %d \n", indicator);
for (rescounter = 0; rescounter < 1000; rescounter++) {
fillchessboard();
printf("iiteration number: %d \n", rescounter);
if (recurfuntion(0, rescounter) == 1) {
printf("iteration number is %d so is the answer :) \n", rescounter);
}
}
system("PAUSE");
return 0;
}
I am trying solve this problem: "You have an 8x8 table on a computer screen with all squares colored to white. In each step you will select any square and as a result all the squares on the same row and column -including the selected square itself- will switch their colors (white becomes black, and black becomes white).
What is the minimum number of steps required for obtaining a standard colored chessboard?"
To do that, I percieved the chessboard into 64 pieces(8x8) and calculating all the combinations of this 64s cluster from 1 to 64. (I know the answer is between 1 and 64).
My method is to begin from the end(chessboard) through to all white. So I fill the board with ones(black) and zeros(white) and construct the chessboard in function fillchessboard() successfully. And I can perfectly toggle row and the column the initial square I choose is on.
Checking method if all board is white is checkboard(). This function returns indicator as 0 if all board is white, 1 if not. I start from little combinations to bigger combinations and check the board in each step. So when the indicator returns as 0 for the first time, it will be the smallest iteration number to make the board all white and be the answer of the question.
So far, my code works and in 10 hours it is able to step up to 10th iteration. However it will take more and more time so 11th iteration will take about 10 hours and 12th iteration will take 20 hours and so on... My question is, is there any method to these instructions more fast and effective? I can not wait for a week to solve this. I d appreciate any help. Thanks!

First let's do some naming:
c_{i,j} is the cell at intersection of row i and column j.
cross_{i,j} is the set: { c_{r,c} / r=i or c=j }. It is the cross of all cells from row i union column j. It contains an odd number of cells.
odd(cross_{i,j}) is a function which returns 0 if there is an even number of black cells in cross_{i,j} and 1 if there is an odd number of black cells.
Let's consider the effect of selecting cell c_{i,j}:
It will switch an odd number of cells in cross_{i,j} and so it will switch the value of odd(cross_{i,j}).
For all other "crosses" the number of cells impacted will be even and so the value of odd(cross_{k,l}) for any (k,l) \neq (i,j) will not change.
The reason for point 2 is that there are only 3 cases for the intersection of cross_{k,l} with cross_{i,j}:
It is a whole row, with an even number of cells.
It is a whole column with an even number of cells.
It is one cell for row k and one cell for column l.
So for every possibility an even number of cells change colors, and so the value of odd(cross_{k,l}) doesn't change.
So the only way to switch the value of odd(cross_{i,j}) is to select c_{i,j}.
At the end of the game there are 32 crosses which have switched value. So the minimal number of steps for any solution is 32.
Now, the previous reasoning also show that selecting the 32 cells of interest will produce the final checkerboard state.
So this is a minimal solution.
I'm sorry but there is no programming here :)

This isn't a solution, but some pointers that should help reduce the complexity (but not the difficulty) of the problem.
The chess board has 2^64 different states.
There are some properties of a chess board that will help you reduce the number of interesting states.
Each move flips 15 tiles (an odd number). Since you start and end with an even number of white tiles you know that the total number of moves is even.
Also, the order you perform the moves in is irrelevant. And selecting the same square twice reverses the previous flip. So we only need to figure out which of the 64 tiles to select.
So we can use 64 bits to represent the solution and each bit represents either a selected tile or an unselected tile. We could use a 64-bit long to store a possible solution.
Also, if you use a 64-bit long to store the state of the board, each step is an XOR with a number that flips the right 15 tiles (a number that has those 15 bits set).
A chessboard is symmetrical. It doesn't matter if you turn it or mirror it. The state would be the same. This further reduces the complexity, because it proves that if X is a solution then the complement of X is also a solution. So if no solution has been found with 32 pieces selected, then no solution exists.
My intuition (or rather the symmetry) suggests that the solution, if one exists) should be a multiple of 8 and be either 8, 16, or 32 with 16 being the most probable. I have no proof for this, however. I should be fairly easy to prove that no solution exists in 8 moves (and you have proved this by using brute force - provided your program is correct).

Related

C 100 Prisoners riddle, something wrong with my code

(If you already know what the riddle is about just read the last 2 lines)
I saw a video about a riddle which is called "The 100 prisoners riddle" it essentially tells you that a bunch of prisoners (only one person at a time) get into a room, this room has boxes that are ordered correctly from 1 to a 100 but the numbers inside the boxes are random and each prisoner getting into the room is numbered from 1 to a 100 too, so each prisoner has to pick the box that has his number, each prisoner has a set of tries (50 tries) if he opened 50 boxes and he didn't find his number he loses! for example prisoner number 1 gets in the room and he has to find the box that has his number .. it might be box number 7 or 19 or 27 who knows! so it's just a game of luck .. or is it? the game has strategies and ways to mathematically solve the puzzle but that's not my problem here, I just wanna program the game in C and solve the puzzle for myself, the code has a lot of holes in it so look closely into it and find what's the problem, THANK YOU ALL :)!
#include <stdio.h>
#include <stdlib.h>
int main() {
int i, j = 0, k = 0, counter = 0;
int boxes[10];
int boxEntered;
for (i = 0; i <= 10; i++) \\ numbering the array
boxes[i] = i;
for (i = 0; i <= 10; i++) {
int temp = boxes[i];
int randomIndex = (rand() % 10); \\ shuffling the boxes to put random numbers
boxes[i] = boxes[randomIndex];
boxes[randomIndex] = temp;
}
for (i = 0; i <= 10; i++) {
printf("%d : (%d)\n", boxes[i], i); \\ print the boxes randomized and their index ordered
}
printf("You only have 5 tries!\n");
while (k != 5) {
while (j < 10) {
printf("Pick a box number between 0 and 10 (You are number %d)\n",counter);
scanf("%d",&boxEntered);
if (boxes[boxEntered] == boxes[counter]) {
printf("\nYou succeded, PROCEED TO NEXT PRISONER\n");
j++; \\ go to the next iteration
k = 0; \\ set tries back to 0
counter++;
} else
printf("Try again\nThe box you entered had number %d\n",boxes[boxEntered]);
k++;
if (k == 5) { \\ if player prisoner fails 5 times you break the loop
break;
}
}
}
if (counter == 10) { \\ if last prisoner was reached successfully then game is won
printf("You are freed!");
} else {
printf("You are going back heheheheheh!\n")
}
return 0;
}
As you can see in this picture the output doesn't make any sense at all and i have no idea what is wrong here..
From your code's logic, you should replace
boxes[boxEntered] == boxes[counter]
with
boxes[boxEntered] == counter
This is because counter here seems to represent a prisoner. Taking boxes[counter] will give you a box, which isn't what you want; you're trying to see if the box matches the current prisoner.
Another important note is the following code will go out of bounds for your array, causing undefined behaviour:
for (i = 0; i <= 10; i++) boxes[i] = i;
boxes is declared as having size 10, and therefore taking boxes[10] goes out of bounds; the maximum is boxes[9].
To fix this, you can index your arrays starting from 1. To do this in C, instead of declaring boxes[10], use boxes[11]. This will ensure you can access boxes[10].
You can then change your loops to start from 1, so something like:
for (i = 1; i <= 10; i++) boxes[i] = i;
Be sure to make this change for every array and for loop in your code.

How do I record the frequency of numbers inputted by a user using functions in C

Hey there i'm currently developing a lotto type game and one of my requirements is to record the frequency of the numbers inputted by the user and then display them if the users wishes to see them. The program also must be modular hence the functions.
My problem is that i can't seem to figure out how to keep track of the numbers I tried numerous things and this is the closest I've gotten...
void num_free(int *picked_nums)
{
static int elements[MAX] = { 0 };
int i;
for (i = 0; i < MAX; i++)
if (*(picked_nums + i) == i)
{
elements[i]++;
}
for (i = 0; i < MAX; i++)
{
if (elements[i] != 0)
{
printf("\nThe amount of times you chose %d is %d", i, elements[i]);
}
}
printf("\nEnter any key to return to main menu");
getchar();
}
The output of this every time i run it no matter the input is
"The amount of times you chose 11 is 1"
I'm really clueless as to what to do next so any and all help would be appreciated. Thanks in advance!
EDIT: The user can play multiple rounds and thats how the frequency of the numbers can add up.
I think the main problem in your code is here:
if (*(picked_nums + i) == i)
{
elements[i]++;
}
you actually check if the i-th number the user chose equals to i. That means that increment is done only in that case - which is not what you want (if I got you right).
I think you should give up the if statement, and, assuming that the user chooses only non-negative numbers (and that the elements array is properly zeroed at the beginning), do this:
elements[picked_nums[i]]++;
Namely, you increment the array cell matching the chosen number (and the i is only the index you use to iterate the picked_num array).
The problem is how you count and store the numbers:
if (*(picked_nums + i) == i)
{
elements[i]++;
}
Your i is moving and at the same time the element chosen from picked_nums is moving. This loop will not count or store properly.
The provided solution assumes that picked numbers are stored in the numbers array. I assumed that numbers are in 1 to 64 range. You can adjust program to your needs. Test provided:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void num_free(int picked_nums[], int size )
{
static int elements[65] = { 0 }; // numbers can be from 1 to 64 range
int i;
for (int j = 0; j < size; j++)
{
int n = picked_nums[j];
for (i = 1; i < 65; i++) // numbers can be from 1 to 64 range
{
if ( n == i)
{
elements[i] = elements[i]+1;
}
}
}
for (i = 0; i < 65; i++)
{
if (elements[i] != 0)
{
printf("\nThe amount of times you chose %d is %d", i, elements[i]);
}
}
// printf("\nEnter any key to return to main menu");
// getchar();
}
// array of entered numbers:
int numbers[] = { 2, 2, 2, 40, 7, 7, 8, 9, 40 };
int main(void) {
num_free(numbers, 9); // call with sizeof numbers
return 0;
}
Test:
The amount of times you chose 2 is 3
The amount of times you chose 7 is 2
The amount of times you chose 8 is 1
The amount of times you chose 9 is 1
The amount of times you chose 40 is 2

Check, if row of matrix is full of 1s in O(1) time

I have an assignment, where I need to write in C a function, which checks, if there is a row in a given matrix that is full of '1's. The matrix values can be only '1's or '0's (boolean matrix).
For example: (size 3)
1 1 0
1 1 1
0 0 1
returns 1 (true)
1 1 0
1 0 1
1 0 0
returns 0 (false)
Now, it's really simple with no restrictions, but then I am asked to do this with time complexity of O(1) and I have no idea, where to start.
If it helps: We were asked to write 2 functions before this one:
init(n, A) fill n-size matrix A with '1's in O(n^2)
flip(A, i ,j) turns value at [i,j] from '0' to '1' or '1' to '0' in O(1)
The catch is to have previously done the "accounting work" and now to just fetch the result in constant time.
There are different strategies that might be applied here. After you have initialized the matrix with 1s in O(n^2) time, now with each flip, you could either keep track of:
the 1s
the flips (or equivalently 0s)
If you choose to track 1s, then you need additional O(n) of memory to each matrix to store them. And when you flip a 1, you subtract 1 from your ones-on-a-row array. When you flip a 0, then you add 1 to your ones-on-a-row* array.
If you track flips, you do it by row, and you need again O(n) of additional memory. Similarly, you have a helper array, where you store the number of flips for each row. If you flip and the new is 0 - add one, if you flip & the new is 1 - subtract one.
Then, at your O(1)-function, you just check against the row's stored value at the respective array position.
O(1) (constant time) is not possible, except when the size of the matrix is fixed.
Then you can simply use some if operations for every row:
// Matrix has fixed size 2x2
if (matrix[0][0] && matrix[0][1]) return 1;
if (matrix[1][0] && matrix[1][1]) return 1;
return 0;
(What do you need the flip function for?)
Otherwise: Just iterate through the matrix:
Init:
void init(unsigned n, unsigned matrix[n][n]) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
matrix[i][j] = 1;
}
}
}
Option 1:
unsigned check(unsigned n, unsigned matrix[n][n]) {
for (int i = 0; i < n; i++) {
unsigned found = 1;
for (int j = 0; j < n; j++) {
if (!matrix[i][j]) {
found = 0;
break;
}
}
if (found) {
return 1;
}
}
return 0;
}
Option 2:
unsigned check(unsigned n, unsigned matrix[n][n]) {
for (int i = 0; i < n; i++) {
unsigned sum = 0;
for (int j = 0; j < n; j++) {
sum += matrix[i][j];
}
if (sum == 3) {
return 1;
}
}
return 0;
}
As the "Big O" notation wants give an order of time (complexity), it will only look at order 1, n, squares, logs etc.
Going through a n x n matrix takes n2 steps (time), so is O(n2). init will be doing something like that.
O(1) should accomplish a task in one step. Flipping can do that as it goes to the element to flip in one step (indexing the array).
Note: the algorithms (functions) to accomplish init and flip are very simple, but I don't want to do your homework for you, just get you going.

Sudoku Grid Generator

I have just started making my Sudoku game and I have made this function grid for creating a 6x6 Sudoku grid. I have used the rand() function for different numbers in each cell (currently it will only check rows for repetition of numbers). rand() is also used for random numbers of empty cells in each grid.
The problem is that sometimes the grid is perfect 6x6 and without any number repeating (in rows only), however, sometimes in some cells there are garbage values generated and sometimes the number of columns is increased. I don't understand what is causing the problem?
The Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void grid(void) {
int cell[6][6], row, col, s, i, j;
char in = 'A';
srand(time(NULL));
for (row = 0; row <= 5; row++) {
printf("\t\t\t[ |");
for (col = 0; col <= 5; col++) {
s = rand() % 6 + 1;
if (s % 2 == 0)
{
cell[row][col] = rand() % 6 + 1;
for (j = 0; j<col; j++) {
if (cell[row][j] == cell[row][col]) {
col--;
continue;
}
}
}
else { printf(" | ", in++); continue; }
printf(" %d | ", cell[row][col]);
}
printf("]\n\n");
}
}
int main()
{
grid();
}
They are too many syntax errors in the code you post, and the format is quite horrible. Try editing it so we can help you !
col--;
Maybe this is your problem, because if you col--; in your for (col = 0; col < 6; col++) loop, you will do more than 6 iterations.
I know this question is old, but a commenter here did say to wait at least 1 hour...
To answer your question directly:
You get garbage values because you do not set values for cell when !(s % 2 == 0).
You get more than 6 entries per row because your c-- statement causes the col loop to execute more than 6 times (and you printf each time).
If you want to maintain the general structure of your logic, then do this in two passes - fill cell completely and then print the whole thing. However, there are other problems. You probably want to remove the s % 2 == 0 check completely, and the first continue could be a break (or a goto if you really want to make people angry).

Graph Coloring in C: Unable to identify the logical error

I am trying to implement the graph coloring algorithm in C, this implementation is based on how we assign the colors by iterating through the adjacency matrix. I am unable to get it after assigning a color to the second vertex.
Here is the code of my program:
int n, a[10][10], i, j, k, c[10], max = 0, col, ct = 0, rt = 0, m, count = 2;
void main() {
printf("enter n\n");
scanf("%d", &n);
printf("enter the Adjacency Matrix for %d rows and %d columns\n", n, n);
for (i = 0; i < n; i++) {
c[i] = 0;
for (j = 0; j < n; j++)
scanf("%d", &a[i][j]);
}
c[0] = 1;
c[1] = 2;
for (i = 1; i < n; i++) {
for (j = 0; j < n; j++)
if (a[i][j] > 0) {
m = 0;
for (col = 0; col < n; col++) {
if (a[i][col] > 0)
rt++;
if (a[col][i] > 0)
ct++;
}
m = rt;
if (ct > rt)
m = ct;
if (m < 2) {
if (a[0][i] > 0)
c[i] = 2;
else
c[i] = 1;
} else {
c[i] = count;
if (m > max) {
max = m;
count++;
}
}
rt = 0;
ct = 0;
}
if (c[i] < 1)
if (c[i - 1] > 1)
c[i] = 1;
else
c[i] = 2;
}
printf("The proper coloring is\n");
for (i = 0; i < n; i++)
printf("c%d=%d ", i + 1, c[i]);
printf("\n");
}
Example Input:
Consider a complete graph:
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Expected output:
c1=1 c2=2 c3=3 c4=4
Observed output:
c1=1 c2=2 c3=3 c4=3
The error seems to be in logic, as you may have inferred by the looks of the question title. The conditional statement where you are checking if m is greater than max and then updating max and count accordingly seem to be incorrect.
I could not exactly figure out what the intended logic was, but I can tell why it is incorrect.
In your usage, you keep the maximum number of neighbors you encountered in max, and update it when you find a vertex which has more neighbors. With it, you also update count, which I think holds the color of currently highest value. Now, unless you encounter a vertex with more neighbors at each step(while traversing each row), you don't update max, and therefore you don't update count. Consequently, unless you encounter such a vertex, you keep assigning the same currently highest count to all vertices you encountered.
You should explain some more about the algorithm you implemented. However, just by looking at your code I think you should at least increment count somewhere different.
A good idea might by just keeping an array equal to the number of vertices. Then for each vertex (inside outermost loop) you can reset the array and by traversing all of the neighbors of ith vertex you can set the colors used in them, and pick the smallest unused color.
It is probably not the most efficient way to do it, but you already have an O(n3) algorithm, so I think it wouldn't hurt going this way.
Below is your code, updated to reflect the changes I mentioned.
int n,a[10][10],i,j,k,c[10],max=0,col,ct=0,rt=0,m,count=2;
int used[11]; /* indices used are from 1 to n, inclusive */
void main()
{
printf("enter n\n");
scanf("%d",&n);
printf("enter the Adjacency Matrix for %d rows and %d columns\n",n,n);
for(i=0; i < n ; i++)
{
c[i]=0;
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
}
c[0]=1;
c[1]=2;
for(i = 1 ;i < n;i++)
{
for(j = 1 ;j <= n ;j++)
used[j] = 0;
for(j = 0 ;j < i ;j++)
{
if(a[i][j] > 0)
used[c[j]] = 1;
}
for(j = 1 ;j <= n ;j++)
if(!used[j])
{
c[i] = j;
break;
}
}
printf("The proper coloring is\n");
for(i = 0;i < n ;i++)
printf("c%d=%d ",i+1,c[i]);
printf("\n");
}
What does a straightforward algorithm to colour the verices look like?
Consider all vertices in a loop and assign a colour. Vertices that have been visited already have a colour; vertices that will still be visited are still uncoloured.
Determine which colours are used by adjacent vertices that have already been coloured.
With this information, pick the lowest possible colour.
What does your algorithm look like:
Assign colour 1 to vertex 1 and colour 2 to vertex 2. (Note that vertex 2 can use the same colour as vertex 1 if the two aren't connected.)
Loop over all remaining vertices; then loop over all vertices cnnected to that.
Count the number of incoming and outgoing links to the second vertex in yet another loop. (Note that merely counting the links doesn't give you information on which colours are still available. You could have many vertices coloured with colours 3 and 4, for example, but you base your new colour on the number of links. In this example, colour 1 would be a good choice.)
Your criterion for chosing a new colour is whether the number of links is greater or equal to 2. You then assign the count, but before incrementing it. That gives you the second 3 in your example, where there should be a 4.
So you loop once too many and have a poor criterion for choosing a colour. Instead of counting the lonks, you should keep a list of used colours in adjacent nodes and base your new colour on that list.
Other stylistic issues with your code:
All your variables should be local to main; there's no reason to make them global, especially since you don't use functions.
Please be more systematic with your variable declarations. To have them all slapped together in one large definition, which even claoesces arrays and scalars, make them hard to understand.
Please use braces around all code blocks, even if they are not strictly necessary. It makes reading the code easier. Small if s without an else in the inner block such as if (ct > rt) m = ct; don't need braces, but consider using them everywhere else.

Resources