Strange occurence in genetic algorithm implementation - c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 8
#define POP 8
int answers[SIZE] = {5,3,1,7,4,6,0,2};
int getRand(int mod){
if (mod==0) return 0;
else return random()%mod;
}
void printArray(int array[]){
int i;
for(i=0; i<SIZE-1; i++) printf("(%i,%i),",i,array[i]);
printf("(%i,%i)",SIZE-1,array[SIZE-1]);
printf("\n");
}
int getWeight(int array[]){
int weight = 28;
int queen;
for(queen=0;queen<SIZE;queen++){ //for each queen
int nextqueen;
for(nextqueen=queen+1;nextqueen<SIZE;nextqueen++){ //for each of the other queens (nextqueen = queen to avoid counting pairs twice)
if(array[queen] == array[nextqueen] || abs(queen-nextqueen)==abs(array[queen]-array[nextqueen])){ //if conflict
weight--;
}
}
}
return weight;
}
void geneticAlgorithm(){
int population[POP][SIZE];
int children[POP][SIZE];
int weightProb[] = {};
int wpl = 0; //weightProb[] length
float mutProb = 0.05;
int done = 0;
int i;
for(i=0;i<POP;i++) for(int j=0;j<SIZE;j++) population[i][j] = getRand(SIZE);
while(done == 0){
for(i=0;i<POP;i++){
if(getWeight(children[i]) == 28){
printf("solution: ");
printArray(children[i]);
done = 1;
}
}
for(i=0;i<wpl;i++) weightProb[i] = (int)NULL; //clear weightprob
wpl=0;
//weighted probability distribution
for(i=0;i<POP;i++){
int w = getWeight(population[i]);
for(int j=0;j<w;j++){
weightProb[wpl] = i; //fill array with member number w times
wpl++;
}
}
//reproduce
for(i=0;i<POP;i+=2){
int par1 = weightProb[getRand(wpl)];
int par2 = weightProb[getRand(wpl)];
int split = getRand(SIZE);
//crossover
for(int j=0;j<split;j++){
children[i][j] = population[par1][j];
children[i+1][j] = population[par2][j];
}
for(int j=split;j<SIZE;j++){
children[i][j] = population[par2][j];
children[i+1][j] = population[par1][j];
}
//mutation
if(getRand(1000000)<=mutProb*1000000){
int child=getRand(2);
if(child == 0) children[i][getRand(SIZE)] = getRand(SIZE);
else children[i+1][getRand(SIZE)] = getRand(SIZE);
}
}
for(i=0;i<POP;i++) for(int j=0;j<SIZE;j++) population[i][j] = children[i][j];
wpl = 0;
}
}
int main(int argc, const char * argv[]){
srandom((unsigned int)time(NULL)); //seed random
geneticAlgorithm();
return 0;
}
when filling weightProb[], the population randomly changes.
i've debugged using print statements and it stops when wpl++ is commented out, but that is required
(wpl is the length of the weightProb array).
how is this happening?

This declaration:
int weightProb[] = {};
declares an empty array. This means each time you write to an element you write out of bounds of the array, and bad things will happen.

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

Difference in behavior between clang and gcc?

I'm writing a C function to simulate a cache given an address trace. The function works as expected when compiled on my mac using gcc (really clang). gcc --version on my mac returns this:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.42)
When I compile the same program on linux using gcc, the returns are way off, and eC & hC in my program (cache eviction counter and hit counter) are in the hundreds of thousands, when they should be below 10. When typing gcc --version on the linux machine, it returns this:
gcc (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3
Here is the program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <getopt.h>
#include "cachelab.h"
typedef struct{
int v;
int t;
int LRU;
} block;
typedef struct{
block *blocks;
} set;
typedef struct{
set *sets;
} cache;
void simulate(int s, int E, int b, char* file, int* hC, int* mC, int* eC)
{
int numSets = (1 << s);
char operation;
int address;
int size;
int curTag;
int curSet;
int maxLRU = 0;
int curLRU = 0;
int check = 0;
cache c;
set *sets = malloc(sizeof(set) * numSets);
c.sets = sets;
int i = 0;
while(i < numSets)
{
c.sets[i].blocks = malloc(sizeof(block) * E);
for (int j = 0; j < E; j++)
{
c.sets[i].blocks[j].v = 0;
c.sets[i].blocks[j].t = INT_MIN;
c.sets[i].blocks[j].LRU = 0;
}
i++;
}
FILE *f = fopen(file, "r");
while(fscanf(f," %c %x,%d", &operation, &address, &size) != EOF)
{
check = 0;
curTag = ((unsigned int) address) >> (s+b);
curSet = (address >> b) & ((1 << s) - 1);
for (int i = 0; i < E; i++)
{
c.sets[curSet].blocks[i].LRU++;
if(c.sets[curSet].blocks[i].LRU >= maxLRU)
{
maxLRU = c.sets[curSet].blocks[i].LRU;
curLRU = i;
}
if(curTag == c.sets[curSet].blocks[i].t)
{
*hC = *hC + 1;
if (operation == 'M')
{
*hC = *hC + 1;
}
c.sets[curSet].blocks[i].LRU = 0;
check = 1;
}
}
if(check == 0)
{
for(int i = 0; i < E; i++)
{
if(c.sets[curSet].blocks[i].v == 0)
{
*mC = *mC + 1;
if (operation == 'M')
{
*hC = *hC + 1;
}
c.sets[curSet].blocks[i].v = 1;
c.sets[curSet].blocks[i].LRU = 0;
c.sets[curSet].blocks[i].t = curTag;
check = 1;
break;
}
}
}
if(check == 0)
{
*eC = *eC + 1;
*mC = *mC + 1;
if (operation == 'M')
{
*hC = *hC + 1;
}
c.sets[curSet].blocks[curLRU].t = curTag;
c.sets[curSet].blocks[curLRU].v = 1;
c.sets[curSet].blocks[curLRU].LRU = 0;
}
}
}
int main(int argc, char** argv)
{
int hitCount, missCount, evictionCount;
int s, E, b;
char *file;
char opt;
while((opt = getopt(argc,argv,"v:h:s:E:b:t:")) != -1)
{
switch(opt){
case 'v':
break;
case 'h':
break;
case 's':
s = atoi(optarg);
break;
case 'E':
E = atoi(optarg);
break;
case 'b':
b = atoi(optarg);
break;
case 't':
file = optarg;
break;
default:
exit(1);
}
}
simulate(s, E, b, file, &hitCount, &missCount, &evictionCount);
printSummary(hitCount, missCount, evictionCount);
return 0;
}
EDIT:
I understand that this is due to a difference between clang and gcc. Does anyone have any information about how I can go about fixing this discrepancy?
Here is cachelab.c:
/*
* cachelab.c - Cache Lab helper functions
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "cachelab.h"
#include <time.h>
trans_func_t func_list[MAX_TRANS_FUNCS];
int func_counter = 0;
/*
* printSummary - Summarize the cache simulation statistics. Student cache simulators
* must call this function in order to be properly autograded.
*/
void printSummary(int hits, int misses, int evictions)
{
printf("hits:%d misses:%d evictions:%d\n", hits, misses, evictions);
FILE* output_fp = fopen(".csim_results", "w");
assert(output_fp);
fprintf(output_fp, "%d %d %d\n", hits, misses, evictions);
fclose(output_fp);
}
/*
* initMatrix - Initialize the given matrix
*/
void initMatrix(int M, int N, int A[N][M], int B[M][N])
{
int i, j;
srand(time(NULL));
for (i = 0; i < N; i++){
for (j = 0; j < M; j++){
// A[i][j] = i+j; /* The matrix created this way is symmetric */
A[i][j]=rand();
B[j][i]=rand();
}
}
}
void randMatrix(int M, int N, int A[N][M]) {
int i, j;
srand(time(NULL));
for (i = 0; i < N; i++){
for (j = 0; j < M; j++){
// A[i][j] = i+j; /* The matrix created this way is symmetric */
A[i][j]=rand();
}
}
}
/*
* correctTrans - baseline transpose function used to evaluate correctness
*/
void correctTrans(int M, int N, int A[N][M], int B[M][N])
{
int i, j, tmp;
for (i = 0; i < N; i++){
for (j = 0; j < M; j++){
tmp = A[i][j];
B[j][i] = tmp;
}
}
}
/*
* registerTransFunction - Add the given trans function into your list
* of functions to be tested
*/
void registerTransFunction(void (*trans)(int M, int N, int[N][M], int[M][N]),
char* desc)
{
func_list[func_counter].func_ptr = trans;
func_list[func_counter].description = desc;
func_list[func_counter].correct = 0;
func_list[func_counter].num_hits = 0;
func_list[func_counter].num_misses = 0;
func_list[func_counter].num_evictions =0;
func_counter++;
}
You forgot to initialize the counters and flags so they start at undefined values. The following lines:
int hitCount, missCount, evictionCount;
int s, E, b;
should be:
int hitCount = 0, missCount = 0, evictionCount = 0;
int s = 0, E = 0, b = 0;
It just happens that the initial values happen to be lower on the mac so you're not getting correct results on the mac either (at least not guaranteed since the initial value is undefined).

C - Genetic Algorithm for N Queens

I'm trying to figure our how to use the Genetic Algorithm to solve N queens.
Here is the program:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 8
#define POP 8
int answers[SIZE] = {5,3,1,7,4,6,0,2};
int getRand(int mod){
if (mod==0) return 0;
else return random()%mod;
}
void printArray(int array[]){
int i;
for(i=0; i<SIZE-1; i++) printf("(%i,%i),",i,array[i]);
printf("(%i,%i)",SIZE-1,array[SIZE-1]);
printf("\n");
}
int getWeight(int array[]){
int weight = 28;
int queen;
for(queen=0;queen<SIZE;queen++){ //for each queen
int nextqueen;
for(nextqueen=queen+1;nextqueen<SIZE;nextqueen++){ //for each of the other queens (nextqueen = queen to avoid counting pairs twice)
if(array[queen] == array[nextqueen] || abs(queen-nextqueen)==abs(array[queen]-array[nextqueen])){ //if conflict
weight--;
}
}
}
return weight;
}
void geneticAlgorithm(){
int population[POP][SIZE];
int children[POP][SIZE];
int weightProb[224] = {};
int wpl = 0; //weightProb[] length
float mutProb = 0.2; //higher prob yields faster times. works decently anyways. bug: prob = 0
int done = 0;
int i;
for(i=0;i<POP;i++) for(int j=0;j<SIZE;j++) population[i][j] = getRand(SIZE);
while(done == 0){
for(i=0;i<POP;i++){
if(getWeight(children[i]) == 28){
printf("solution: ");
printArray(children[i]);
done = 1;
}
}
for(i=0;i<wpl;i++) weightProb[i] = (int)NULL; //clear weightprob
wpl=0;
//weighted probability distribution
for(i=0;i<POP;i++){
int w = getWeight(population[i]);
for(int j=0;j<w;j++){
weightProb[wpl] = i; //fill array with member number w times
wpl++;
}
}
//reproduce
for(i=0;i<POP;i+=2){
int par1 = weightProb[getRand(wpl)];
int par2 = weightProb[getRand(wpl)];
int split = getRand(SIZE);
//crossover
for(int j=0;j<split;j++){
children[i][j] = population[par1][j];
children[i+1][j] = population[par2][j];
}
for(int j=split;j<SIZE;j++){
children[i][j] = population[par2][j];
children[i+1][j] = population[par1][j];
}
//mutation
if(getRand(1000000)<=mutProb*1000000){
int child=getRand(2);
if(child == 0) children[i][getRand(SIZE)] = getRand(SIZE);
else children[i+1][getRand(SIZE)] = getRand(SIZE);
}
}
for(i=0;i<POP;i++) for(int j=0;j<SIZE;j++) population[i][j] = children[i][j];
wpl = 0;
}
}
int main(int argc, const char * argv[]){
srandom((unsigned int)time(NULL)); //seed random
geneticAlgorithm();
return 0;
}
The program runs and compiles properly but doesn't produce the results I'm after. I'm wanting to display the x,y co-ordinates of each queen and simply print them out on output. However instead I'm getting random garbage on output and I cant figure out why.
Current output example:
(0,0) (1,3248234234) (2,0) (3,-3248236736) (4,57435727) (5,234743567) (6, 23498348) (7,23487234)
Desired output example (a solution to the N queen problem):
(3,4) (7,2) (0,3) (4,6) (6,5) (1,7) (5,1) (2,0)
Not sure if this is the cause of your specific issue, but it is a problem:
for(i=0;i<POP;i++) for(int j=0;j<SIZE;j++) population[i][j] = getRand(SIZE);
while(done == 0){
for(i=0;i<POP;i++){
if(getWeight(children[i]) == 28){
printf("solution: ");
printArray(children[i]);
done = 1;
}
}
The above is the initialisation of the population and the beginning of the loop. On the first time through, the children array contains uninitialised data.
Given the rest of the algorithm, you need to be checking the weight of the elements of population (and printing an element from population) if it is a winner, not children.

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.

Calculate the best possible combination of items within a cost and weight limit

I'm trying to help my sister with a college assignment in Computer programming(I'm in the Irish equivalent of High School). I've programmed in Python and Java before but seldom C. The project has to be done in C.
Essentially, you are given a number of items. Each item has a weight, value and cost. The idea is to calculate the best possible value for the items while staying within a weight limit and budget.
I've written a code, but it doesn't work. Each time it is run the output is a random array of numbers and the weight and cost values are zero...
I think the problem is to do with the realloc function, but I don't know how to use that probably. I essentially want to make an array that I can change the length of. I don't think realloc is designed for this... Any advice or solutions would be a great help...
#include <stdio.h>
#include <stdlib.h>
int check(int finalList[], int value, int current,int limit, int weight, int tempw, int budget, int cost, int tempc, int Clist[], int x);
int main()
{
int nlist[5] = {1,2,3,4,5};
int values[5] = {4,5,7,2,9};
int weights[5] = {1,4,8,2,9};
int costs[5]= {3,6,2,1,8};
int n = 5;
int x,i,j,k,l,m,p=0;
int value=0, cost= 0, weight = 0,tempv=0, tempw = 0, tempc = 0;
int budget = 45;
int limit = 12;
int finalList[n];
for(x=0;x<n;x++)
{
for(i=0;i<n;i++)
{
int list[x+1];
list[0] = nlist[i];
tempv = values[i];
tempw = weights[i];
tempc = costs[i];
for(j=0;j<x;j++)
{
for(k=0;k<n;k++)
{
list[0]=nlist[i];
tempv = values[i];
tempw = weights[i];
tempc = costs[i];
m = p;
for(l=0;l<x;l++)
{
if(m==i)
{
m++;
p++;
}
list[l] = nlist[m];
tempv = tempv + values[m];
tempw = tempw + weights[m];
tempc = tempc + costs[m];
check(finalList, value,tempv, limit, weight, tempw, budget, cost, tempc, list,x);
}
p++;
}
}
check(finalList, value,tempv,limit, weight, tempw, budget, cost, tempc, list,x);
}
}
printf("\nMost efficient item list:" );
for(i=0;i<n;i++)
{
printf("%d", finalList[i]);
}
printf("\nWeight: %d", weight);
printf("\nCost: %d", cost);
}
int check(int finalList[], int value, int current,int limit, int weight, int tempw, int budget, int cost, int tempc, int Clist[], int x)
{
if(tempw<=limit)
{
if(tempc<=budget)
{
if (current>value)
{
finalList = realloc(finalList, 1*(x+1));
finalList= Clist;
value = current;
weight = tempw;
cost = tempc;
}
}
}
return finalList,value,weight,cost;
}
First, I'll try to show you how object oriented principles with appropriate data structures and small functions can help make code more readable and errors easier to spot.
#include <stdio.h>
#include <stdlib.h>
const int MAX_COST = 45;
const int MAX_WEIGHT = 12;
const int VALUES[5] = {4, 5, 7, 2, 9};
const int WEIGHTS[5] = {1, 4, 8, 2, 9};
const int COSTS[5] = {3, 6, 2, 1, 8};
typedef struct
{
// total over all items in the subset
int value;
int weight;
int cost;
// subset of items
int indices[5];
int num_indices;
} candidate;
void candidate_init (candidate *c)
{
c->value = 0;
c->weight = 0;
c->cost = 0;
c->num_indices = 0;
}
void candidate_print (const candidate *c)
{
printf ("items: ");
for (int i = 0; i < c->num_indices; i++) {
printf ("%d, ", c->indices[i]);
}
putchar ('\n');
printf ("value: %d\n", c->value);
printf ("weight: %d\n", c->weight);
printf ("cost: %d\n", c->cost);
};
void candidate_add_item (candidate *c, int i)
{
c->value += VALUES[i];
c->weight += WEIGHTS[i];
c->cost += COSTS[i];
c->indices[c->num_indices++] = i;
}
int candidate_is_ok (const candidate *c)
{
return ((c->weight <= MAX_WEIGHT) && (c->cost <= MAX_COST));
}
You don't need dynamic allocation since the number of items is known at compile time.
candidate candidates[32]; // 32 == pow (2, 5)
int num_candidates = 0;
void candidates_insert (candidate *c)
{
candidates[num_candidates++] = *c;
}
And now the main code, which should be easy to understand:
int main ()
{
// insert empty candidate
{
candidate c;
candidate_init (&c);
candidates_insert (&c);
}
// generate all valid candidates
for (int i = 0; i < 5; i++) {
int n = num_candidates;
for (int j = 0; j < n; j++) {
candidate c = candidates[j];
candidate_add_item (&c, i);
if (candidate_is_ok (&c)) {
candidates_insert (&c);
}
}
}
// find candidate with maximum value
int max_value = 0;
int max_i = 0;
for (int i = 0; i < num_candidates; i++) {
if (candidates[i].value > max_value) {
max_value = candidates[i].value;
max_i = i;
}
}
// print solution
candidate_print (&candidates[max_i]);
}
In the function check():
You are throwing away the values of finalList, value, weight.
return finalList,value,weight,cost; is equivalent to return cost;
The value of cost is also thrown away because the return value is not used.
Using pointers is one way to pass multiple informations between functions.
Also, m became too big and nlist[m] etc. were causing out-of-range access.
Not knowing about the calculation, this code is at least printing something not zero without crushing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void check(int **finalList, int *value, int current,int limit, int *weight, int tempw, int budget, int *cost, int tempc, int Clist[], int x);
int main(void)
{
int nlist[5] = {1,2,3,4,5};
int values[5] = {4,5,7,2,9};
int weights[5] = {1,4,8,2,9};
int costs[5]= {3,6,2,1,8};
int n = 5;
int x,i,j,k,l,m,p=0;
int value=0, cost= 0, weight = 0,tempv=0, tempw = 0, tempc = 0;
int budget = 45;
int limit = 12;
int *finalList = calloc(n, sizeof(int));
for(x=0;x<n;x++)
{
for(i=0;i<n;i++)
{
int list[x+1];
for(j=0;j<=x;j++) list[j] = 0; /* initialize the list */
list[0] = nlist[i];
tempv = values[i];
tempw = weights[i];
tempc = costs[i];
for(j=0;j<x;j++)
{
for(k=0;k<n;k++)
{
list[0]=nlist[i];
tempv = values[i];
tempw = weights[i];
tempc = costs[i];
m = p;
for(l=0;l<x;l++)
{
if(m==i)
{
m++;
p++;
}
if(m<5)
{
list[l] = nlist[m];
tempv = tempv + values[m];
tempw = tempw + weights[m];
tempc = tempc + costs[m];
}
check(&finalList, &value,tempv, limit, &weight, tempw, budget, &cost, tempc, list,x);
}
p++;
}
}
check(&finalList, &value,tempv,limit, &weight, tempw, budget, &cost, tempc, list,x);
}
}
printf("\nMost efficient item list:" );
for(i=0;i<n;i++)
{
printf("%d", finalList[i]);
}
printf("\nWeight: %d", weight);
printf("\nCost: %d", cost);
free(finalList);
return 0;
}
void check(int **finalList, int *value, int current,int limit, int *weight, int tempw, int budget, int *cost, int tempc, int Clist[], int x)
{
if(tempw<=limit)
{
if(tempc<=budget)
{
if (current>*value)
{
*finalList = realloc(*finalList, sizeof(int)*(x+1));
if(*finalList == 0)
{
perror("realloc");
exit(1);
}
memcpy(*finalList, Clist, sizeof(int)*(x+1));
*value = current;
*weight = tempw;
*cost = tempc;
}
}
}
}

Resources