Dynamic array class won't print - c

#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];
}

Related

Dynamically exclude some numbers from randomly generated sequence

I want to produce a random sequence of numbers between a range, for example 100 to 200.
After a while, depending on some events, I want to produce a new sequence between the same range (100 to 200), but this time I want to exclude some numbers. For example I don't want [150,165,170].
And the next time, these excluded numbers may or may not be included in the sequence.
One possible approach could be an array of numbers like this:
int rndm[] {100,101,102,103,...};
and use the index of the array to generate a random number at a time:
random(rndm[0-99]);
But I need to use as few instruction/data structures as possible in order to achieve performance.
I am using C for this code and I use random() or randomSeed(seed) and I want to know what the most efficient approach to handle this issue is, in terms of data structures should be used for the speed and memory.
This solution is efficient in the case that there are not many exclusions during the lifetime, once the exclusion function is quadratic.
There is a struct called RandomArray that holds a pointer to and array with size N. N is the desired size of the sequence. The time and space complexity is linear O(N) for the create function.
When an event happens it shall call the function excludeValue, with a time complexity of O(N) and space complexity of 1.
If it is desired to exclude a bunch of values, the function excludeValues (pay attention to s at the end) shall be called. In this case the complexity is O(N x K) and the space complexity is 1. K is the amount of values that shall be excluded.
#include <stdio.h>
#include <stdlib.h>
struct RandomArray {
int *pData;
size_t dataLen;
int excludedIdx;
};
struct RandomArray *excludeValue(struct RandomArray *pAr, int val) {
size_t i;
for (i = 0; i < pAr->excludedIdx; ++i) {
if (pAr->pData[i] == val) {
pAr->excludedIdx--;
int tmp = pAr->pData[i];
pAr->pData[i] = pAr->pData[pAr->excludedIdx];
pAr->pData[pAr->excludedIdx] = tmp;
// Do test again the position
--i;
}
} return pAr;
}
struct RandomArray *excludeValues(struct RandomArray *pAr, int *pVals, size_t len) {
size_t i;
for (i = 0; i < len; ++i)
excludeValue(pAr, pVals[i]);
}
struct RandomArray *destroyRandomArray(struct RandomArray *pAr) {
if (pAr) {
if (pAr->pData)
free(pAr->pData);
pAr->dataLen = 0;
}
return pAr;
}
struct RandomArray *createRandomArray(
struct RandomArray *pAr,
size_t dataLen,
int lowLimit, int highLimit) {
int i;
int range = (highLimit - lowLimit);
pAr->pData = (int*)malloc(sizeof(int) * dataLen);
pAr->dataLen = dataLen;
srand(time(NULL));
for (i = 0; i < dataLen; ++i) {
pAr->pData[i] = rand() % (range + 1) + lowLimit;
}
// Clear excluded indexs
pAr->excludedIdx = pAr->dataLen; return pAr;
}
void printRandomArray(struct RandomArray *pAr) {
size_t i;
printf("Random Array (len = %d): ", pAr->dataLen);
for (i =0; i < pAr->dataLen; ++i) {
printf(" %d", pAr->pData[i]);
}
printf("\n");
}
void printValidRandomArray(struct RandomArray *pAr) {
size_t i;
printf("Valid Random Array (len = %d): ", pAr->excludedIdx);
for (i =0; i < pAr->excludedIdx; ++i) {
printf(" %d", pAr->pData[i]);
}
printf("\n");
}
void printExcludedRandomArray(struct RandomArray *pAr) {
size_t i;
printf("Excluded Random Array (len = %d): ", pAr->dataLen - pAr->excludedIdx);
for (i = pAr->excludedIdx; i < pAr->dataLen; ++i) {
printf(" %d", pAr->pData[i]);
}
printf("\n");
}
void printAllRandomArray(struct RandomArray *pAr) {
printRandomArray(pAr);
printValidRandomArray(pAr);
printExcludedRandomArray(pAr);
}
int main() {
int lowLimit = 100;
int highLimit = 105;
int arrayLen = 10;
struct RandomArray myAr;
createRandomArray(&myAr, arrayLen, lowLimit, highLimit);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 100);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 101);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 102);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 103);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 104);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 105);
printAllRandomArray(&myAr);
destroyRandomArray(&myAr);
createRandomArray(&myAr, arrayLen, lowLimit, highLimit);
printf("\n\n\n");
printAllRandomArray(&myAr);
printf("\n");
int vals[] = { 102, 105, 104 };
excludeValues(&myAr, vals, sizeof(vals) / sizeof(vals[0]));
printAllRandomArray(&myAr);
destroyRandomArray(&myAr);
}
This was asked here on the Arduino forum but I saw it here too. My answer is in Arduino's flavor of C++ since it was posted there...
Of course, performance varies as the set of excluded numbers grows relative to the set of numbers to be used to create your "new sequence."
void setup() {
Serial.begin(115200);
randomSeed(analogRead(A0));
}
void loop() {
// create an arbitray sized array to be filled with unique values to exclude from desired array
const int arraySize = 5;
int exclusions[arraySize];
for (int i = 0; i < arraySize; i++) {
// fill the array with unique values...
int val;
do {
val = random(100, 200);
} while([&]() {
for (auto j : exclusions) {
if (val == j) {
return true;
}
}
return false;
}());
exclusions[i] = val;
}
Serial.print(F("Exclusion Array: "));
for (int i = 0; i < arraySize; i++) {
Serial.print(exclusions[i]);
if (i < arraySize - 1)
Serial.print(F(", "));
}
Serial.println();
// create a new array of arbitrary length of unique random numbers in >>>the same<<< range as above (but not necessary)
Serial.print(F("Starting...\n"));
uint32_t start = millis();
const int listSize = 32;
int list[listSize];
for (int i = 0; i < listSize; i++) {
// fill the array with unique values that will exclude exclusions[]
int val;
do {
val = random(100, 200);
} while([&]() {
for (auto j : list) {
if (val == j) {
return true;
}
for (auto k : exclusions) {
if (val == k) {
return true;
}
}
}
return false;
}());
list[i] = val;
}
uint32_t end = millis();
Serial.println(end - start);
// OPTIONAL -> lets sort the final arry to make spotting the duplicates easier:
for (int i = 0; i < listSize; i++) {
for (int j = i + 1; j < listSize; j++) {
if (list[j] < list[i]) {
int temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
// output the final array
Serial.print(F("Final Array: "));
for (int i = 0; i < listSize; i++) {
Serial.print(list[i]);
if (i < listSize - 1)
Serial.print(F(", "));
}
Serial.print(F("\n\n\n"));
delay(1000);
}

Lexicographic Order in Multidimensional Array C++

I'm having trouble with one final task that my program should do.
Having my output character in a lexicographic order.
For example, if I input bbbaaa it should have an output of
Frequencies:
a 3
b 3
Not
Frequencies:
b 3
a 3
Can anyone help me solve this problem?
Here is my code:
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctype.h>
using namespace std;
void sort(char letters[], int integers[], int size);
void swap_letters(char& first, char& second, int& int1, int& int2);
int index_of_largest(const int integers[], int start_index, int number_used);
int main(){
const int MAX_CHARS = 200;
char letters[MAX_CHARS] = {'\0'};
int integers[MAX_CHARS] = {'\0'};
int index, size = 0;
char character;
cout << "Enter text:" << endl;
cin.get(character);
character = tolower(character);
while (character!= '.' && size < MAX_CHARS){
if(isalpha(character)){
index = 0;
while (index < size){
if(letters[index] == character)
break;
else
index++;
}
if (index < size){
integers[index] = integers[index] + 1;
}
else{
letters[index] = character;
integers[index] = 1;
size++;
}
}
cin.get(character);
character = tolower(character);
}
letters[index] = tolower(letters[index]);
sort(letters, integers, size);
cout << "Frequencies:"<< endl;
for(int i = 0; i < size; i++){
cout << letters[i] << " " << integers[i] << endl;
}
return 0;
}
void sort(char letters[], int integers[], int size){
for (int i = 0; i < size -1; i++){
int j = index_of_largest(integers, i, size);
swap_letters(letters[i], letters[j], integers[i], integers[j]);
}
}
void swap_letters(char& first, char& second, int& int1, int& int2){
char temp_char = first;
first = second;
second = temp_char;
int temp_int = int1;
int1 = int2;
int2 = temp_int;
}
int index_of_largest(const int integers[], int start_index, int number_used){
int max_int = integers[start_index];
int max_int_index = start_index;
for (int index = start_index + 1; index < number_used; index++){
if (integers[index] > max_int){
max_int = integers[index];
max_int_index = index;
}
}
return max_int_index;
}
The problem is in function index_of_largest() where you detect the index of largest checking only integers and ignoring letters.
All goes well when all letters are with different frequencies but doesn't work when a couple two or letter are with the same frequency. In this case you should take in count letters too.
I suppose you can correct the function in this way
int index_of_largest(const int integers[], const char letters[], int start_index, int number_used){
int max_int = integers[start_index];
int max_int_index = start_index;
for (int index = start_index + 1; index < number_used; index++){
if ( (integers[index] > max_int)
|| ( (integers[index] == max_int)
&& (letters[index] < letters[max_int_index]) )){
max_int = integers[index];
max_int_index = index;
}
}
return max_int_index;
}
But I suggest you to follow the Jack's suggestion: use STL container/algorithm when you can / when is possible
p.s.: sorry for my bad English.

Realloc an array of double

The exercise, that I have to complete says:
That array_remove function must remove from the array arr the value, that is in the position pos, and scale of a position successive values of pos, and eventually change the array size for no gaps.
If this value is not included in the array (if pos is greater than pn (array size)), then you should not do anything.
My problem is:
Probably very wrong to use the malloc function, because when it is performed, it shows the following error:
MAIN.C:
#include "array.h"
int main(void)
{
double arr[] = { 1.0,2.0,3.0,4.0,5.0 };
size_t pn = 5;/*array length*/
size_t pos = 2;/*position of the number to be deleted*/
array_remove(arr, &pn, pos);
}
ARRAY.C:
#include "array.h"
void array_remove(double *arr, size_t *pn, size_t pos)
{
int x = *pn;
int y = pos;
if (x > y)
{
for (int i = y; i < x; i++)
{
arr[i] = arr[i + 1];
}
realloc(&arr, sizeof(double) * 4);
}
}
According to the C docs:
realloc Reallocates the given area of memory that must be previously allocated
by malloc(), calloc() or realloc() and not yet freed with free,
otherwise, the results are undefined.
You have an out of bound problem as well at the following lines when i=x-1 you try to access at arr[i+1] = arr[x=pn]:
for (int i = y; i < ; i++) {
arr[i] = arr[i + 1];
Check the following code out *(live: https://ideone.com/mbSzjL
#include<stdlib.h>
void array_remove(double **arr, int *pn, int pos) {
int x = *pn;
int y = pos;
if (x > y) {
//check if after deletion size is zero!
if (x > y) {
for (int i = y; i < x-1; i++) {
(*arr)[i] = (*arr)[i + 1];
}
*arr=realloc(*arr, sizeof(double) * x-1);
*pn=*pn-1;
}
}
}
int main(void) {
int pn = 20;/*array length*/
int pos = 5;/*position of the number to be deleted*/
double *arr = malloc(sizeof(double)*pn);
printf("%p\n",arr);
for(int i=0;i<pn;i++){
arr[i] = i;
}
for(int i=0;i<pn;i++){
printf("%.f ",arr[i]);
}
printf("\n");
printf("%i\n",pn);
array_remove(&arr, &pn, pos);
printf("%p\n",arr);
for(int i=0;i<pn;i++){
printf("%.f ",arr[i]);
}
printf("\n");
printf("%i",pn);
free(arr);
}
Don't forget to realloc using the right size (not using an hardcoded 4) and check for the edge case in which size is zero after deletion!
In addition,
free the memory at the end and to update the size variable.
http://en.cppreference.com/w/c/memory/realloc
arr array is stack allocated. You cannot realloc something that wasn't mallocated.
You probably want something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
bool array_remove(double **arr, size_t *pn, size_t pos)
{
int x = *pn - 1;
int y = pos;
int i;
double *temp;
if (x > y) {
for (i = y; i < x; i++) {
(*arr)[i] = (*arr)[i + 1];
}
temp = realloc(*arr, sizeof(double) * x);
}
if (arr != NULL)
{
*arr = temp;
*pn -=1;
return true;
}
else
{
return false;
}
}
int main(void)
{
size_t pn = 5; // array length
size_t pos = 2; // position of the number to be deleted
int i;
double *arr = malloc(pn*sizeof(double));
if (arr != NULL)
{
for (i=0; i<pn; i++)
{
arr[i] = (double)(i+1);
}
if (array_remove(&arr, &pn, pos) == false)
{
printf("Failed to remove element %zu\n", pos);
}
for (i=0; i<pn; i++)
printf ("arr[%d]: %f\n", i, arr[i]);
free(arr);
}
else
{
printf("Failed to alloc array\n");
}
return 0;
}
As you can see I changed the loop of array_remove. In your code you are addressing the array out of bound on the last loop, because of i=4 and then:
arr[i] = arr[i + 1]; is arr[4] = arr[5]
Indexes of a 5 elements array start from 0 to 4.
actually you have a different problem here:
int x = *pn; //x=5
int y = pos; //y=2
if (x > y) {
for (int i = y; i < x; i++) {
arr[i] = arr[i + 1];
}
On the last iteration, you do
arr[4] = arr[5]
This is out of range addressig and that's probably your problem, or at least your first one.
Also, even though it's not technically wrong it's conceptually wrong:
array_remove(arr, &pn, pos);
Never pass a value by pointer unless you plan on modifying it. Not the case here, so you can pass it by value.

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;
}

N queens using backtracking

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;
}

Resources