N queens using backtracking - c

I have implemented a solution for the N queens problem by using backtracking.
I am checking whether the position of every queen is safe or not by checking its top left, top right and top and then placing it in the row, otherwise I backtrack.
It is giving a correct solution for some values of N, such as 4 and 8, but incorrect for others, such as 6.
I don't know what I am missing. Any help would be highly appreciated.
Here's the code:
int S;
static int cnt=0;
int safepos(int board[][S+1],int i,int j)
{
if(i==1)
return 1;
int a,b;
a=i-1;
b=j-1;
//checking for top-left side
while(a>0 && b>0 )
{
if(board[a--][b--]==1)
return 0;
}
a=i-1;
b=j+1;
//checking for top-right side
while(a>0 && b<=S )
{
if(board[a--][b++]==1)
return 0;
}
//checking for the same column
for(a=1;a<i;a++)
if(board[a][j]==1)
return 0;
return 1;
}
void Nqueens(int board[][S+1],int N,int n) //n is the number of the rows
{
if(n==N+1) //for those which reaches the last position we will have a solution
{
cnt++;
return;
}
int i;
for(i=1;i<=N;i++) //for every column
{
if( safepos(board,n,i) )
{
board[n][i]=1;
Nqueens(board,N,n+1); //checking for next row
}
board[n][i]=0;
}
}
int main()
{
int N=6;
S=N;
int board[N+1][N+1];
Nqueens(board,N,1);
printf("%d",cnt);
return 0;
}

Your implementation of the backtracking idea is correct, the problem comes from the fact that the values of the array 'board' have to be initialized to zero manually, by default the array comes with undefined values. If you do that, you should get the correct answer, I tested the code. For more information related to array initialization, see http://www.fredosaurus.com/notes-cpp/arrayptr/array-initialization.html

I know this has an accepted answered but wanted to share my implementation that uses a vector initialized to -1 and not zero as to not interfere with zero offset for row = 0
#include <iostream>
#include <vector>
const int GRID_SIZE = 8;
bool isValid ( int queenNum, int col, std::vector<int>& cols )
{
// check for other queen number that collide with this one
for ( int queenRow = 0; queenRow < queenNum; ++queenRow )
{
int queenCol = cols[queenRow];
if ( col == queenCol )
return false; // same col
if ((queenNum - queenRow) == abs( queenCol-col))
return false; // same diagonal
}
return true;
}
void solve( int queenNum, std::vector<int>& cols, std::vector<std::vector<int> >& results )
{
if ( queenNum == GRID_SIZE)
{
// we have a solution
results.push_back (cols);
}
for ( int i = 0; i < GRID_SIZE; ++ i)
{
if ( isValid(queenNum,i,cols) )
{
cols[queenNum] = i;
solve(queenNum + 1,cols, results);
}
}
}
void drawLine() {
std::string line;
for (int i=0;i<GRID_SIZE*2+1;i++)
line.append("-");
std::cout << line << std::endl;
}
void printBoard(std::vector<int>& cols)
{
drawLine();
for(int i = 0; i < GRID_SIZE; i++){
std::cout << "|";
for (int j = 0; j < GRID_SIZE; j++){
if (cols[i] == j) {
std::cout << "Q|";
} else {
std::cout << " |";
}
}
std::cout << std::endl;
drawLine();
}
std::cout << "" << std::endl;;
}
void printBoards(std::vector<std::vector<int> >& boards) {
for (int i = 0; i < (int)boards.size(); i++)
{
printBoard(boards[i]);
}
}
int main ()
{
std::vector<int> cols ( GRID_SIZE, -1);
std::vector<std::vector<int> > results;
solve(0, cols, results );
printBoards(results);
std::cout << results.size() << std::endl;
return 0;
}

Related

Generating Sudoku Puzzle

I'm trying to write a piece of code which generates for me a valid sudoku puzzle.
My algorithm:
initiate all fields with 0
respect the rules and set 20 random values from 1-9 to random fields
solve the puzzle with the back tracking algorithm
My problems:
Sometimes it generates a valid sudoku puzzle in under 1 second.
Sometimes it can't generate a valid sudoku and I get an error, which is ok because I can go back to step 1 in my algorithm.
Sometimes it can't generate a valid sudoku and I get an error but it takes about 2-3Minutes, which is not ok.
How can I solve my problems?
Especially problem 3.
Can I just count the seconds and if it takes more than 5 seconds just go back to step 1 of my algorithm?
Or does anyone have a better idea?
thanks in advance.
this is my code:
#include <stdio.h>
#include <stdlib.h>
#define N 9
#define UNASSIGNED 0
typedef enum {false, true} bool;
typedef struct {
char number;
bool editable;
} GRID;
void print_sudoku(GRID **g){
char row=0, col=0;
for(row=0; row<N; row++){
for(col=0; col<N; col++){
printf("%d ", g[row][col].number);
}
printf("\n");
}
}
GRID ** create_sudoku_grid(){
char i, row, col;
GRID **g = (GRID **) malloc(N * sizeof(GRID *));
for (i=0; i<N; i++) {
g[i] = (GRID *) malloc(N * sizeof(GRID));
}
for(row=0; row<N; row++){
for(col=0; col<N; col++){
g[row][col].number = UNASSIGNED;
g[row][col].editable = true;
}
}
return g;
}
bool find_unassigned_field(GRID **g, int *row, int *col){
for (*row = 0; *row < N; (*row)++) {
for (*col = 0; *col < N; (*col)++) {
if (g[*row][*col].number == UNASSIGNED){
return true;
}
}
}
return false;
}
bool validate_row(GRID **g, int row, int num) {
for (int col = 0; col < N; col++) {
if (g[row][col].number == num) {
return false;
}
}
return true;
}
bool validate_col(GRID **g, int col, int num) {
for (int row = 0; row < N; row++) {
if (g[row][col].number == num) {
return false;
}
}
return true;
}
bool validate_box(GRID **g, int row, int col, int num) {
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
if (g[r+row][c+col].number == num) {
return false;
}
}
}
return true;
}
bool validate_field(GRID **g, int row, int col, int num){
bool valrow, valcol, valbox, valunassigned;
valrow = validate_row(g, row, num);
valcol = validate_col(g, col, num);
valbox = validate_box(g, row - row%3 , col - col%3, num);
valunassigned = g[row][col].number==UNASSIGNED;
return (valrow && valcol && valbox && valunassigned);
}
bool generate_sudoku(GRID **g) {
int row, col;
// If there is no unassigned location, we are done
if (!find_unassigned_field(g, &row, &col)) {
return true; // success!
}
// consider digits 1 to 9
for (int num = 1; num <= 9; num++) {
// if looks promising
if (validate_field(g, row, col, num)) {
// make tentative assignment
g[row][col].number = num;
// return, if success, yay!
if (generate_sudoku(g)) {
return true;
}
// failure, unmake & try again
g[row][col].number = UNASSIGNED;
}
}
return false; // this triggers backtracking
}
void random_init_grid(GRID **g){
int row, col, num;
srand(time(0));
for(int cntr=0; cntr<20;){
row = rand() % N;
col = rand() % N;
num = rand() % N + 1;
if(g[row][col].number == UNASSIGNED){
if(validate_field(g, row, col, num)){
g[row][col].number = num;
cntr++;
}
}
}
}
int main(int argc, char *argv[]) {
GRID **g = create_sudoku_grid();
random_init_grid(g);
if(generate_sudoku(g)){
printf("OK\n\n");
} else {
printf("\nNOT OK\n\n");
}
print_sudoku(g);
}
Sudoko is a computationally hard problem possibly in the order of 10^100 using brute force and ignorance. It could take a lot longer than 2-3 minutes! Sometimes, because of number layout, it is easier than that.
In one approach, you could count your iterations, and give up if it exceeds them. Your key bit is the block where you recursively call generate_soduko() -- if you end up in here too many times you are in trouble.
To that end, I changed your program put a 1s alarm on its execution, counter the number of times in that block; and if the alarm expires, print the counter and exit; if it doesn't print the counter for reference at the end. On my machine, 1s == 500,000 iterations.
*** sud.c~ 2019-12-06 14:30:21.000000000 -0500
--- sud.c 2019-12-06 14:30:57.000000000 -0500
***************
*** 1,10 ****
#include <stdio.h>
#include <stdlib.h>
#define N 9
#define UNASSIGNED 0
-
typedef enum {false, true} bool;
typedef struct {
char number;
--- 1,21 ----
#include <stdio.h>
#include <stdlib.h>
+ #include <signal.h>
+ #include <unistd.h>
+ #include <time.h>
+
+ volatile long counter;
+ void alrm(int signo) {
+ char buf[64];
+ int n;
+ n = sprintf(buf, "failed after %ld iter\n", counter);
+ write(2, buf, n);
+ _exit(1);
+ }
#define N 9
#define UNASSIGNED 0
typedef enum {false, true} bool;
typedef struct {
char number;
***************
*** 106,111 ****
--- 117,123 ----
for (int num = 1; num <= 9; num++) {
// if looks promising
if (validate_field(g, row, col, num)) {
+ counter++;
// make tentative assignment
g[row][col].number = num;
***************
*** 139,145 ****
}
int main(int argc, char *argv[]) {
! GRID **g = create_sudoku_grid();
random_init_grid(g);
if(generate_sudoku(g)){
--- 151,161 ----
}
int main(int argc, char *argv[]) {
!
! GRID **g;
! signal(SIGALRM, alrm);
! alarm(1);
! g = create_sudoku_grid();
random_init_grid(g);
if(generate_sudoku(g)){
***************
*** 148,151 ****
--- 164,168 ----
printf("\nNOT OK\n\n");
}
print_sudoku(g);
+ printf("iter = %ld\n", counter);
}

Push_back odd numbers

So, the goal of the function is to add odd numbers to the array between 1 and a provided integer (inclusive). It seems like a simple task, however, I can't seem to get it to successfully add the integers to the actual array.
void populate(std::vector<int> ary, int a)
{
for (int i = 1; i <= a; i++)
{
if (i % 2 != 0)
{
ary.push_back(i);
}
}
}
The function itself isn't const, so shouldn't it be adding values to the array successfully?
EDIT: This is all done in a main, so here it is.
int main()
{
std::vector<int> loli(100);
populate(loli, 31);
for (int value : loli)
{
std::cout << value << " ";
system("pause");
}
}
EDIT 2: I've tried adding a return statement instead, however i still get the result zero.
std::vector<int> populate(std::vector<int> ary, int a)
{
for (int i = 1; i <= a; i++)
{
if (i % 2 != 0)
{
ary.push_back(i);
}
}
return ary;
}
int main()
{
std::vector<int> loli(100);
for (int value : populate(loli, 31))
{
std::cout << value << " ";
system("pause");
}
}
Your function should either return the final array after the for loop or you should pass the array as a pointer to the function.

Dynamic array class won't print

#include <iostream>
#include <cmath>
#include <iomanip>
#include <cstring>
#include <cstddef>
class ArrayList
{
public:
ArrayList();
void expand();
void store(std::string x);
void display_size();
friend std::ostream& operator<<(std::ostream& os, const ArrayList &arr);
void clean();
ArrayList(const ArrayList &arr);
~ArrayList();
void operator=(const ArrayList& arr);
private:
int size; //total size of your dynamic array
int max; //double the size of the array.
int free_space; //total size of unused space in your dynamic array
char *array; //a pointer used to create a dynamic array
};
ArrayList::ArrayList()
{
size = 2;
free_space = 1;
array = new char[2]();
array[0] = ' ';
array[1] = '\0';
max = size;
}
void ArrayList::expand()
{
max = size + size;
char *temp = new char[max];
for( int i = 0; i < max; i++ )
{
array[i] = temp[i];
}
free_space = free_space + size;
delete [] array;
array = temp;
size = max;
}
void ArrayList::store(std::string x)
{
int taken = max - free_space;
int y = x.size();
free_space = free_space - y;
for(int i = 0; i < y; i++)
{
if(y >= size)
{
while(y >= size)
{
expand();
}
}
else
{
array[i + taken] = x[i];
}
}
}
std::ostream& operator<<(std::ostream& os, const ArrayList &arr)
{
os << arr.array;
return os;
}
void ArrayList::display_size()
{
size = max;
std::cout << "Array Content: ";
std::cout << array;
std::cout << std::endl;
std::cout << "Remaining size: ";
std::cout << free_space;
std::cout << std::endl;
}
void ArrayList::clean()
{
int x = 0;
for(int i = 0; i < size; i++)
{
if(array[i] == ' ')
{
x++;
}
}
size = x;
}
ArrayList::ArrayList(const ArrayList &arr)
{
array = new char[size + 1];
strcpy(array, arr.array);
}
ArrayList::~ArrayList()
{
delete [] array;
}
void ArrayList::operator=(const ArrayList& arr)
{
int new_length = strlen(arr.array);
if(new_length > max)
{
delete [] array;
max = new_length;
array = new char[max + 1];
}
for(int i = 0; i < new_length; i++)
{
array[i] = arr.array[i];
}
array[new_length] = '\0';
}
int main()
{
ArrayList x;
std::string y;
char ans;
x.display_size();
std::cout << "Please enter your string: ";
std::cin >> y;
x.store(y);
x.display_size();// << std::endl;
do
{
std::cout << "Please enter your string: ";
std::cin >> y;
x.store(y);
x.display_size();
std::cout << "Do you want to enter another string? (y/n) ";
std::cin >> ans;
}while(ans != 'n');
return 0;
}
My question is regarding C++ dynamic arrays. I've created a class which creates a dynamic array.
I've posted my entire code it should be runnable.
The issue stems from the use of the store and expand functions.
store takes a string and puts each character into the array, if there isn't enough space it calls expand.
expand doubles the size of the array.
Array Content:
Remaining size: 1
Please enter your string: h
Array Content: h
Remaining size: 0
Please enter your string: ello
Array Content:
Remaining size: 2
Do you want to enter another string? (y/n) n
In theory the output above should have returned "hello" however it hasn't returned anything, despite returning the 'h' earlier. I'm completely out of ideas on how to solve this.
EDIT:
I've since changed the functions according to the advice given to me:
void ArrayList::expand()
{
max = size + size;
char *temp = new char[max];
for( int i = 0; i < max; i++ )
{
temp[i] = array[i];
}
free_space = free_space + size;
delete [] array;
array = temp;
size = max;
}
void ArrayList::store(std::string x)
{
int taken = max - free_space;
int y = x.size();
free_space = free_space - y;
for(int i = 0; i < y; i++)
{
if(free_space <= 0)
{
while(free_space <= 0)
{
expand();
}
}
else
{
array[i+taken] = x[i]; //I'm cetain this didn't do anything
}
}
}
I've solved the negative number issue detailed in the comments. The only issue now is printing the number.
This "for" loop in "expand" method:
for( int i = 0; i < max; i++ )
{
array[i] = temp[i];
}
should be replaced by:
for( int i = 0; i < size; i++ )
{
temp[i] = array[i];
}

Cant get a Diamond Shape in C right

I'm doing a c exercise to do a diamond shape with '#' using a funcion.
My code :
#include <stdio.h>
//Declare function
void losangle(int n);
//main
int main(void){
int n;
do {
printf("Altura do triangulo: ");
scanf("%d", &n );
} while( n % 2 == 0);
losangle(n);}
//function
void losangle(int n){
int i, hashtag, spaces, j, spaces1, hashtag1;
//triangle
for(i = 0; i < n; i++){
for(spaces = 0; spaces < (n-i); spaces++){
printf(" ");}
for(hashtag = 0; hashtag < (i+1);hashtag++){
printf("# ");}
printf("\n");}
//inverted triangle
for(j = 0; j < (n - 1); j++){
for(spaces1 = 0; spaces1 < (j+2); spaces1++){
printf(" ");}
//not working !!!
for(hashtag1 = (n-1); hashtag1 > 0; hashtag1--){
printf("# ");}
printf("\n");
}}
The output is this :
Losangle: 5
#
# #
# # #
# # # #
# # # # #
# # # #
# # # #
# # # #
# # # #
What is making the '#' not decrementing in the bottom part ? Is this line wrong (for(hashtag1 = (n-1); hashtag1 > 0; hashtag1--)) ?? Btw i also accept tips to improve the code efficiency.
Issue:
The inverted triangle for loop iterates from n-1 to 0 every time, regardless of j's value.
Solution:
Iterating between n-1 to j will cause the number of hash symbols to decrease every iteration.
Change this line:
for(hashtag1 = (n-1); hashtag1 > 0; hashtag1--){
to
for(hashtag1 = (n-1); hashtag1 > j; hashtag1--){
Milestone 1
What's the high level logic of the program?
void getInutAndDrawDiamond()
int getTriangleHeight();
void drawDiamond(int height);
int main()
{
getInutAndDrawDiamond();
return 0;
}
void getInutAndDrawDiamond()
{
int height = getTriangleHeight();
drawDiamond(height);
}
with dummy implementations of getTriangleHeight and drawDiamond.
int getTriangleHeight()
{
return 0;
}
void drawDiamond(int height)
{
}
Milestone 2
Add a proper implementation of getTriangleHeight.
int getTriangleHeight()
{
int height;
int c;
char const* prompt = "Enter the height of the triangle: ";
printf("%s", prompt);
while ( scanf("%d", &height) != 1 )
{
// Error reading the input.
// Ignore rest of the line
while ( (c = fgetc(stdin)) != '\n' && c != EOF );
// If EOF is reached, exit.
if ( c == EOF )
{
exit(EXIT_FAILURE);
}
// Try reading again.
printf("%s", prompt);
}
return height;
}
Milestone 3
Add the next level implementation of drawDiamond, using couple of helper functions that have dummy implementations.
void drawUpperHalfOfDiamond(int height);
void drawLowerHalfOfDiamond(int height);
void drawDiamond(int height)
{
drawUpperHalfOfDiamond(height);
drawLowerHalfOfDiamond(height);
}
void drawUpperHalfOfDiamond(int height)
{
}
void drawLowerHalfOfDiamond(int height)
{
}
Milestone 4
Add the next level implementation of drawUpperHalfOfDiamond and drawLowerHalfOfDiamond, using dummy implementations of couple of helper functions.
void drawUpperHalfRowOfDiamond(int row);
void drawLowerHalfRowOfDiamond(int row);
void drawUpperHalfOfDiamond(int height)
{
for (int row = 0; row < height; ++row )
{
drawUpperHalfRowOfDiamond(row);
}
}
void drawLowerHalfOfDiamond(int height)
{
for (int row = 0; row < height; ++row )
{
drawLowerHalfRowOfDiamond(row);
}
}
void drawUpperHalfRowOfDiamond(int row)
{
}
void drawLowerHalfRowOfDiamond(int row);
{
}
Milestone 5
Add the next level implementation of drawUpperHalfRowOfDiamond and drawLowerHalfRowOfDiamond, using dummy implementations of a few helper functions.
int getNumberOfColumsForUpperHalfRow(int row);
void drawUpperHalfCell(int row, int col);
int getNumberOfColumsForLowerHalfRow(int row);
void drawLowerHalfCell(int row, int col);
void drawUpperHalfRowOfDiamond(int row)
{
int cols = getNumberOfColumsForUpperHalfRow(row);
for (int col = 0; col < cols; ++col )
{
drawUpperHalfCell(row, col);
}
}
void drawLowerHalfRowOfDiamond(int row)
{
int cols = getNumberOfColumsForLowerHalfRow(row);
for (int col = 0; col < cols; ++col )
{
drawLowerHalfCell(row, col);
}
}
int getNumberOfColumsForUpperHalfRow(int row)
{
return 0;
}
void drawUpperHalfCell(int row, int col)
{
}
int getNumberOfColumsForLowerHalfRow(int row)
{
return 0;
}
void drawLowerHalfCell(int row, int col)
{
}
Milestone 5
Add proper implementations of the last four functions -- left as an exercise to the reader.
Complete program
#include <stdio.h>
#include <stdlib.h>
void getInutAndDrawDiamond();
int getTriangleHeight();
void drawDiamond(int height);
void drawUpperHalfOfDiamond(int height);
void drawLowerHalfOfDiamond(int height);
void drawUpperHalfRowOfDiamond(int row);
void drawLowerHalfRowOfDiamond(int row);
int getNumberOfColumsForUpperHalfRow(int row);
void drawUpperHalfCell(int row, int col);
int getNumberOfColumsForLowerHalfRow(int row);
void drawLowerHalfCell(int row, int col);
int main()
{
getInutAndDrawDiamond();
return 0;
}
void getInutAndDrawDiamond()
{
int height = getTriangleHeight();
drawDiamond(height);
}
int getTriangleHeight()
{
int height;
int c;
char const* prompt = "Enter the height of the triangle: ";
printf("%s", prompt);
while ( scanf("%d", &height) != 1 )
{
// Error reading the input.
// Ignore rest of the line
while ( (c = fgetc(stdin)) != '\n' && c != EOF );
// If EOF is reached, exit.
if ( c == EOF )
{
exit(EXIT_FAILURE);
}
// Try reading again.
printf("%s", prompt);
}
return height;
}
void drawDiamond(int height)
{
drawUpperHalfOfDiamond(height);
drawLowerHalfOfDiamond(height);
}
void drawUpperHalfOfDiamond(int height)
{
for (int row = 0; row < height; ++row )
{
drawUpperHalfRowOfDiamond(row);
}
}
void drawLowerHalfOfDiamond(int height)
{
for (int row = 0; row < height; ++row )
{
drawLowerHalfRowOfDiamond(row);
}
}
void drawUpperHalfRowOfDiamond(int row)
{
int cols = getNumberOfColumsForUpperHalfRow(row);
for (int col = 0; col < cols; ++col )
{
drawUpperHalfCell(row, col);
}
}
void drawLowerHalfRowOfDiamond(int row)
{
int cols = getNumberOfColumsForLowerHalfRow(row);
for (int col = 0; col < cols; ++col )
{
drawLowerHalfCell(row, col);
}
}
int getNumberOfColumsForUpperHalfRow(int row)
{
// TODO a proper implementation
return 0;
}
void drawUpperHalfCell(int row, int col)
{
// TODO a proper implementation
}
int getNumberOfColumsForLowerHalfRow(int row)
{
// TODO a proper implementation
return 0;
}
void drawLowerHalfCell(int row, int col)
{
// TODO a proper implementation
}
Concluding Remarks
After implementing the last four functions properly, the program is very well structured to be able to diagnose problems easily by changing what gets called from main.
Some crazy complicated answers have been posted.
Here it is in one loop, one printf, and one variable (other than the Width input).
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int w = 9;
int l;
for(l=0; l < w; ++l)
{
printf("%*.*s\n",
abs(w/2 - l)+abs((2*l+1)-(2*l+1>w)*2*w),
abs((2*l+1)-(2*l+1>w)*2*w),
"# # # # # # # # # # # # # # # # # # ");
}
return 0;
}
Link to IDEOne Code

C: interleaving with for loop?

I need to create a program which would ask from user to input a string and then function in program needs to separate it to 2 strings of same size (user always inputs even number of chars) and after that it has to "shuffle" them...
So it should basically do this:
user inputs: A1B1C1D1
code should make 2 same sized strings: A1B1 and C1D1 and after that it should "shuffle" them to look like this: A1C1B1D1.
So it needs to take first 2 elements of first string, then first 2 elements of second string and so on…
My problem is that when I input A1B1C1D1, after I run the program, I get AC1BD1 (it leaves out 2nd char from first array).
#include<stdio.h>
#include<string.h>
#define N 100
void shuffle(char *cards) {
int i, n, x=0, c1=0, c2=0, j=0;
char tmp1[N]={0}, tmp2[N]={0};
n=strlen(cards);
//divide to 2 arrays with same number of elements
for(i=0; i<n; i++){
if(i<(n/2)){
tmp1[i]=cards[i];}
else{
tmp2[x]=cards[i];
x++;
}
}
//storing 2 elements from first array, then 2 elements from second array and so on
for(i=0; i<n; i++){
if(j>3){
j=0;
}
if(j<=1){ // store 2 elements from 1st array
cards[i]=tmp1[c1];
c1++;
j++;
}
if(j>=2){ // store 2 elements from 2nd array
cards[i]=tmp2[c2];
c2++;
j++;
}
}
printf("1st half:%s\n2nd half:%s", tmp1, tmp2);
printf("\n\t%s",cards);
return;
}
int main() {
char cards[N];
scanf("%s", cards);
shuffle(cards);
return 0;
}
The problem is here
if(j<=1){ // store 2 elements from 1st array
cards[i]=tmp1[c1];
c1++;
j++;
}
if(j>=2){ // store 2 elements from 2nd array
cards[i]=tmp2[c2];
c2++;
j++;
}
Make the second if as an "else if" (just an "else" is also enough)
What happens is that after you increment j from 1 to 2, you go into the second if statement, and rewrite on the same index on cards.
If you don't mind an alternative suggestion for "shuffling your deck of cards" in a much simpler way:
void shuffle(char *cards)
{
char tmp[N]={0};
int n = strlen(cards);
for (int i=0; i<n/2; i++)
tmp[i*2+0] = cards[i];
for (int i=0; i<n/2; i++)
tmp[i*2+1] = cards[i+n/2];
for (int i=0; i<n; i++)
cards[i] = tmp[i];
}
You call it shuffle and cards.
Wouldnt it be better to make a card structure that has two elements?
I thinky your j in the for loop is behaving wrong.
I will double check this and edit this answer if it wasnt j.
EDIT:
Your cradcount was off by a bit and you wrote the wrong index.
Here is some working code:
j = 0;
i = 0;
while(i<n)
{
++j;
if(j == 1 || j == 2)
{ // store 2 elements from 1st array
cards[i++]=tmp1[c1++];
}
else if(j == 3 || j == 4)
{ // store 2 elements from 2nd array
cards[i++]=tmp2[c2++];
}
else
{
j = 0;
}
}
In general you can use the debugger to see whats happening with your index. I assume this is homework and you have to write "optimal code". In general it would be beneficial to use varaiblaenames with more meaning.
EDIT2:
There is a nice solution below that illustrates time optimized code.
I wanted to add some code that i think is easier to read and maintain.
#include<stdio.h>
#include<string.h>
#define DECK_MAX 100
typedef struct
{
char group;
int number;
}Tcard;
typedef struct
{
Tcard card[DECK_MAX];
int count;
}Tdeck;
int ReadDeck(Tdeck * deck, const char *cardstring);
int DeckAddCopy(Tdeck * deck, Tcard * card);
int PrintDeck(Tdeck * deck, const char *deckname);
int InterleaveDecksCopy(Tdeck * target, Tdeck * source[], int sourcecount);
int SplitDeckCopy(Tdeck * source, Tdeck * target[], int targetcount);
int main() {
int e = 0;
char cardstring[100];
Tdeck deck, stackA, stackB, interleaved;
Tdeck * stacks[] = {&stackA, &stackB};
printf("Please input a cardstring: ");
scanf("%s", cardstring);
e |= ReadDeck(&deck, cardstring);
e |= PrintDeck(&deck, "cardstring");
e |= SplitDeckCopy(&deck, stacks, sizeof(stacks) / sizeof(Tdeck*) );
e |= PrintDeck(&stackA, "1st half");
e |= PrintDeck(&stackB, "2nd half");
e |= InterleaveDecksCopy(&interleaved, stacks, sizeof(stacks) / sizeof(Tdeck*) );
e |= PrintDeck(&interleaved, "interleaved");
if( e != 0) printf("There was an error dureing execution.\n");
return e;
}
int ReadDeck(Tdeck * deck, const char *cardstring)
{
int e = 0;
int varCount, n, total = 0;
Tcard card;
memset(deck, 0, sizeof(Tdeck));
do{
n = 0;
varCount = sscanf(&cardstring[total], "%c%i%n", &card.group, &card.number, &n);
total += n;
if( varCount == 2 )
{
//check if card is valid?
e |= DeckAddCopy(deck, &card);
}
else
{
if(strlen(cardstring) != total)
{
//string was not read completely
e |= 1;
}
}
}while(varCount == 2);
return e;
}
int DeckAddCopy(Tdeck * deck, Tcard * card)
{
int e = 0;
if(deck->count >= DECK_MAX)
{
e |= 1;
}
else
{
memcpy(&deck->card[deck->count++], card, sizeof(Tcard));
}
return e;
}
int PrintDeck(Tdeck * deck, const char *deckname)
{
int c;
printf("%s contains %i cards%s", deckname, deck->count, (deck->count == 0)? ".\n":": ");
for(c = 0; c < deck->count; ++c)
{
printf("%c%i%s", deck->card[c].group, deck->card[c].number, ( c+1 < deck->count) ? ", ":".\n");
}
return 0;
}
int InterleaveDecksCopy(Tdeck * target, Tdeck * source[], int sourcecount)
{
int c, s, e = 0;
memset(target, 0, sizeof(Tdeck));
for(c = 0; c < DECK_MAX; ++c)
{
for(s = 0; s < sourcecount ; ++s)
{
if(c < source[s]->count)
{
e |= DeckAddCopy(target, &source[s]->card[c]);
}
}
}
return e;
}
int SplitDeckCopy(Tdeck * source, Tdeck * target[], int targetcount)
{
int c, t, e = 0;
for(t = 0; t < targetcount ; ++t)
{
memset(target[t], 0, sizeof(Tdeck));
}
c = 0;
for(t = 0; t < targetcount ; ++t)
{
int cMax = (source->count) - (((source->count)/targetcount) * targetcount - t - 1 );
for( ; c < (t+1)*(source->count)/targetcount ; ++c)
{
e |= DeckAddCopy(target[t], &source->card[c]);
}
}
return e;
}

Resources