Sorting an array of structs Efficiently - c

I am sorting an array of structs using qsort, and I am looking for a more efficient way to extract the top three highest scores by partially sorting the array. My structure looks like this:
typedef struct {
double score;
int player_num;
} player_t;
and I have malloced an array of structures like this:
player_t *players = malloc(SIZE * sizeof(player_t));
The way I sort this array of structures is by first sorting the scores, and if the scores have ties, then sort by the player number.
My code looks like this with qsort:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 6
#define MAX 3
int scorecmp(const void *a, const void *b);
int ComparePlayerScore( const void* ap , const void* bp );
int CompareInt( const int a , const int b );
typedef struct {
double score;
int player_num;
} player_t;
int
main(int argc, char *argv[]) {
int i;
int player_numbers[] = {1, 2, 3, 4, 5, 6};
double scores[] = {0.765, 0.454, 0.454, 0.345, 0.643, 0.532};
player_t *players = malloc(SIZE * sizeof(player_t));
for (i = 0; i < SIZE; i++) {
players[i].score = scores[i];
players[i].player_num = player_numbers[i];
}
qsort(players, SIZE, sizeof(*players), ComparePlayerScore);
for (i = 0; i < MAX; i++) {
printf("Player %d: Score: %.3f\n", players[i].player_num, players[i].score);
}
free(players);
return 0;
}
int ComparePlayerScore( const void* ap , const void* bp ) {
const player_t* const a = ap;
const player_t* const b = bp;
if( a->score == b->score ){
return CompareInt( a->player_num , b->player_num );
}
else if( a->score > b->score ) {
return -1;
}
else {
return 1;
}
}
int CompareInt( const int a , const int b ) {
if( a < b ){
return -1;
}
else if( a > b ){
return 1;
}
return 0;
}
I am just looking for another way to do this, but a more efficient way to extract the top 3 the scores, along with the respective player numbers. Like a way where I can extract the top three elements of the array without having to sort the whole array first everytime.

This is my offering. Since you have #define MAX for how many top scores you want to find, I have considered that.
The program makes a single pass of the data, and 1 pass of the topmost for each of the records. I have used a fixed array, you'll have to adapt to your needs.
#include <stdio.h>
#define SIZE 6
#define MAX 3
typedef struct {
double score;
int player_num;
} player_t;
int main(int argc, char *argv[])
{
player_t players[SIZE] = {{2.0, 2}, {4.0, 5}, {1.0, 4}, {1.0, 1}, {5.0, 3}, {4.0, 6}};
int order[MAX+1] = {0};
int found = 1;
int i, j;
int bigger;
for(i = 1; i < SIZE; i++) {
bigger = 0;
for(j = 0; j < found; j++) {
if(players[i].score > players[ order[j] ].score) {
bigger = 1;
break;
}
else if(players[i].score == players[ order[j] ].score &&
players[i].player_num < players[ order[j] ].player_num) {
bigger = 1;
break;
}
}
if(bigger) {
memmove(order + j + 1, order + j, (found - j) * sizeof order[0]);
order[j] = i;
if(found < MAX) {
found++;
}
}
}
for(i = 0; i < found; i++) {
printf("%d %f\n", players[ order[i] ].player_num, players[ order[i] ].score);
}
return 0;
}
Program output:
3 5.000000
5 4.000000
6 4.000000

Just a simple try, see online demonstration on http://ideone.com/8A1lnP.
struct top3_players {
player_t *top[3];
};
void top3_determine(struct top3_players *top, player_t *players, size_t n) {
player_t *top1 = NULL;
player_t *top2 = NULL;
player_t *top3 = NULL;
for (size_t i = 0; i < n; i++) {
player_t *player = &players[i];
if (top1 == NULL || ComparePlayerScore(player, top1) < 0) {
top3 = top2;
top2 = top1;
top1 = player;
} else if (top2 == NULL || ComparePlayerScore(player, top2) < 0) {
top3 = top2;
top2 = player;
} else if (top3 == NULL || ComparePlayerScore(player, top3) < 0) {
top3 = player;
}
}
top->top[0] = top1;
top->top[1] = top2;
top->top[2] = top3;
}

Here is a solution that keeps track of the top three scores by storing pointers to them. When you add a player or change a score, an update function is called to keep the top-score list current. The advantage here is that you only ever need to iterate over a list of three elements. I modified your original code to demonstrate how this might work:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 6
#define MAX 3
typedef struct {
double score;
int player_num;
} player_t;
void update_topscores(player_t **top, player_t *pplayer);
int
main(int argc, char *argv[]) {
int i;
int player_numbers[] = {1, 2, 3, 4, 5, 6};
double scores[] = {0.765, 0.454, 0.454, 0.345, 0.643, 0.532};
player_t *players = malloc(SIZE * sizeof(player_t));
player_t **topscores = calloc(3, sizeof(player_t *));
for (i = 0; i < SIZE; i++) {
players[i].score = scores[i];
players[i].player_num = player_numbers[i];
update_topscores(topscores, &(players[i]));
}
for (i = 0; i < SIZE; i++) {
printf("Player %d: Score: %.3f\n",
players[i].player_num, players[i].score);
}
puts("Top Scores");
for (i = 0; i < 3; i++) {
printf("Player %d: Score: %.3f\n",
topscores[i]->player_num, topscores[i]->score);
}
/* Change score for player 4 */
players[3].score = 0.755;
update_topscores(topscores, &(players[3]));
puts("New Top Scores");
for (i = 0; i < 3; i++) {
printf("Player %d: Score: %.3f\n",
topscores[i]->player_num, topscores[i]->score);
}
free(players);
free(topscores);
return 0;
}
void update_topscores(player_t **top, player_t *pplayer)
{
int i;
player_t *temp;
for (i = 0; i < 3; i++)
if (top[i] == NULL) {
top[i] = pplayer;
return ;
}
for (i = 0; i < 3; i++) {
if ((pplayer->score) > (top[i]->score)) {
temp = top[i];
top[i] = pplayer;
update_topscores(top, temp);
break;
}
}
return ;
}
You can see that there is a function update_topscores() that is used to update the list. In the above code, this is used when building the initial list of players. Then, when the score of Player 4 is updated, the function is called again, resulting in a new list of top scores. The list is not sorted, but it would be easy to do so if desired, and you would only be sorting a list of three entries.
There was an additional allocation for three pointers to player pointers, topscores, which must of course be freed at the end.
Here is a sample output:
Player 1: Score: 0.765
Player 2: Score: 0.454
Player 3: Score: 0.454
Player 4: Score: 0.345
Player 5: Score: 0.643
Player 6: Score: 0.532
Top Scores
Player 1: Score: 0.765
Player 5: Score: 0.643
Player 6: Score: 0.532
New Top Scores
Player 1: Score: 0.765
Player 4: Score: 0.755
Player 5: Score: 0.643

Related

Sort struct array in lexicographical order

I need to sort students according to their surname or if their surname is the same according to their name in lexicographical order.
#include <stdio.h>
struct Student {
char name[20], surname[20];
};
void sort(struct Student students[], int n) {
int i, j, temp;
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
if (students[j].surname > students[i].surname ||
students[j].name > students[i].name) {
temp = i;
students[i] = students[j];
students[j] = students[temp];
}
}
void main() {
struct Student students[6] = {
{"Mujo", "Mujic"},
{"Meho", "Mujic"},
{"Pero", "Peric"},
{"Beba", "Bebic"},
{"Mujo", "Mujic"},
{"Fata", "Fatic"},
};
sort(students, 6);
int i;
for (i = 0; i < 6; i++)
printf("%s %s\n", students[i].surname, students[i].name);
}
This prints only one student six times. Could you help me to fix this?
Note: using auxiliary arrays is not allowed
Your swap code is dubious — broken, I believe. A big warning bell is the type of temp — it needs to be a struct Student.
You have:
temp = i;
students[i] = students[j];
students[j] = students[temp];
You need:
struct Student temp = students[i];
students[i] = students[j];
students[j] = temp;
Obviously, remove the definition int temp; as well.
However, there are other problems too (as ever). You can't usefully compare strings using relational operators — use strcmp(). And your ordering test is wrong too, even when revised to use strcmp().
This code does the job, sorting names in descending order:
#include <stdio.h>
#include <string.h>
struct Student
{
char name[20];
char surname[20];
};
static void sort(struct Student students[], int n)
{
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
int rc = strcmp(students[j].surname, students[i].surname);
if (rc > 0 ||
(rc == 0 && strcmp(students[j].name, students[i].name) > 0))
{
struct Student temp = students[i];
students[i] = students[j];
students[j] = temp;
}
}
}
}
static void dump_array(const char *tag, size_t size, const struct Student *students)
{
printf("%s (%zu):\n", tag, size);
for (size_t i = 0; i < size; i++)
printf("%s %s\n", students[i].surname, students[i].name);
}
int main(void)
{
struct Student students[] =
{
{"Mujo", "Mujic"},
{"Meho", "Mujic"},
{"Pero", "Peric"},
{"Zebra", "Elephant"},
{"Beba", "Bebic"},
{"Mujo", "Mujic"},
{"Abelone", "Shells"},
{"Fata", "Fatic"},
};
enum { NUM_STUDENTS = sizeof(students) / sizeof(students[0]) };
dump_array("Before", NUM_STUDENTS, students);
sort(students, NUM_STUDENTS);
dump_array("After", NUM_STUDENTS, students);
return 0;
}
Output:
Before (8):
Mujic Mujo
Mujic Meho
Peric Pero
Elephant Zebra
Bebic Beba
Mujic Mujo
Shells Abelone
Fatic Fata
After (8):
Shells Abelone
Peric Pero
Mujic Mujo
Mujic Mujo
Mujic Meho
Fatic Fata
Elephant Zebra
Bebic Beba

Need help on 0/1 knapsack-problem in C with highest "value" solution, but least "weight" wenn same (highest) "value"

I am already puzzling for two weeks programming a knapsack problem in C.
Since I didn't manage to get it working with structs directly, I have made a solution with an extra array. If you know how to use the structs directly, that would be great!
But the main problem is, that when I get multiple solutions with the same value, I'd want to only get the solution with the least weight.
My code till now:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdbool.h>
#include <string.h>
#define TEAMS 5
#define max_players 20
typedef struct Team
{
char name [10];
int players;
bool Is_Playing;
int points;
} Team;
struct Team one = { "Ones", 12, true, 18 };
struct Team two = { "Twos", 4, true, 10 };
struct Team three = { "Threes", 5, true, 9 };
struct Team four = { "Fours", 12, true, 22 };
struct Team five = { "Fives", 8, true, 15 };
typedef struct selection_entry
{
int points;
int team;
struct selection_entry *prev;
} selection_entry;
Team *teams[TEAMS] = { &one, &two, &three, &four, &five };
int selection(int players[], const int *selection_points, size_t n,
int capacity, int **solution)
{
int i, j;
selection_entry **table;
int result;
selection_entry *head;
/* Allocate the table */
table = malloc((n + 1) * sizeof(selection_entry *));
for (i = 0; i <= n; i++) {
table[i] = malloc((capacity + 1) * sizeof(selection_entry));
}
/* Calculate the points and build chains */
for (i = 0; i <= n; i++) {
for (j = 0; j <= capacity; j++) {
if (i == 0 || j == 0) {
/* Initialising the first row or column */
table[i][j].points = 0;
table[i][j].team = 0;
table[i][j].prev = NULL;
}
else if (players[i - 1] <= j) {
/* Can add team */
if (selection_points[i - 1] + table[i - 1][j - players[i - 1]].points
> table[i - 1][j].points) {
/* Add team */
table[i][j].points = selection_points[i - 1] + table[i - 1][j - players[i - 1]].points;
table[i][j].team = i - 1;
table[i][j].prev = &table[i - 1][j - players[i - 1]];
}
else {
/* Don't add team */
table[i][j].points = table[i - 1][j].points;
table[i][j].team = table[i - 1][j].team;
table[i][j].prev = table[i - 1][j].prev;
}
}
else {
/* Don't add team */
table[i][j].points = table[i - 1][j].points;
table[i][j].team = table[i - 1][j].team;
table[i][j].prev = table[i - 1][j].prev;
}
}
}
/* Read back the solution */
*solution = calloc(n, sizeof(int));
for (i = 0, head = &table[n][capacity];
head->prev != NULL;
head = head->prev, i++) {
(*solution)[head->team] = 1;
}
result = table[n][capacity].points;
for (i = 0; i <= n; i++) {
free(table[i]);
}
free(table);
return result;
}
int GetSelectionArraySize()
{
int s=0;
for (int i = 0; i < TEAMS; i++)
{
if (teams[i]->Is_Playing)
{
s++;
}
}
return s;
}
void main()
{
int a_size = GetSelectionArraySize();
int players[a_size];
int selection_points[a_size];
int i, j=0;
for (int i = 0; i < TEAMS; i++)
{
if (teams[i]->Is_Playing)
{
players[j] = teams[i]->players;
selection_points[j] = teams[i]->points;
j++;
}
}
const int capacity = max_players;
const size_t n = sizeof(players) / sizeof(players[0]);
int *solution;
int points = selection(players, selection_points, n, capacity, &solution);
fprintf(stdout, "Value: %d\n", points);
for (i = 0; i < n; i++)
{
if (solution[i])
{
fprintf(stdout, "Team %d with %d players and %d points.\n", i, players[i], selection_points[i]);
}
}
free(solution);
}
Problems:
I can't figure out why this isn't working properly and how I get it to give me the best solution (highest points but least players within the maximum specified number of players).
Sub-problem:
The array-workaround annoys me, but I fail in making it work with the original arrays of structs directly...
Thank you very much in advance!!!
Kindest regards!
Ralf
I'm not going into detail of your code, but instead lets have a look at the problem and the knapsack-like solution.
Basically, the relevant properties of your solution are value and weight, where weight is constrained and a solution A is better than solution B, if A.value > B.value or if A.value = B.value AND A.weight < B.weight as long as A and B satisfy the constraint.
So, given a list of potential items [item1, [others...]], where a solution including items1 is possible, you need to find the better solution
subresult1 = solve([others...], weightconstraint - item1.weight)
candidate1 = (subresult1.value + item1.value, subresult1.weight + item1.weight)
candidate2 = solve([others...], weightconstraint)
if (candidate1.value > candidate2.value) return candidate1
if (candidate1.value == candidate2.value && candidate1.weight < candidate2.weight) return candidate1
return candidate2
I hope this pseudo-code is clear enough to explain the logic to be implemented.

Sorting one array and copying the order over to another

I have two arrays side by side, one lists the different teams and the other lists the scores. I am able to sort the order of scores in descending order. Can this order then be used to move the corresponding team to the correct position of the leader board? eg. move the two teams with 100 points (USA and Germany) to the top of the board
#include <stdio.h>
int main()
{
char teams[18][20]={"England","Ireland","Wales","Scotland","France","Italy","Germany","Uraguay","Belgium","USA","Mexico","Australia","Belize","Denmark","Sweden","Japan","South Africa","Algeria"};
int points[18]={43,5,77,23,89,0,100,46,94,100,45,55,32,65,11,37,26,78};
int i;
int j;
int a;
for (i = 0; i < 18; ++i)
{
printf("%i ",i+1);
printf("%s",teams[i]);
printf("\t%d\n", points[i]);
}
printf("\n");
for (i = 0; i < 18; ++i)
{
for (j = i + 1; j < 18; ++j)
{
if (points[i] < points[j])
{
a = points[i];
points[i] = points[j];
points[j] = a;
}
}
}
for (i = 0; i < 18; ++i)
{
printf("%i ",i+1);
printf("%s",teams[i]);
printf("\t%d\n", points[i]);
}
return 0;
}
As mentioned in a comment, the typical solution is to model your data as an array of structures, rather than separate arrays. This makes sense, since the data is associated with each other.
You'd have something like:
struct score {
const char *name;
int points;
} scores[] = {
{ "England", 43 },
{ "Ireland", 5 },
/* and so on */
};
Then you can use qsort() (or your own sorting code, if that's of interest) to sort entire structure instances, and the all the data will remain together since entire structures are being moved around.
Also arrange your teams array when sorting;
a = points[i];
b = teams[i];
points[i] = points[j];
teams[i] = teams[j];
points[j] = a;
teams[j] = b;
The obvious way (as pointed out by others) is embedding your arrays into a struct, but if you are forced to use parallel arrays you can build your own function and sort both arrays at once:
#include <stdio.h>
static int comp(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
static void swap(int v1[], char *v2[], int a, int b)
{
int temp1;
char *temp2;
temp1 = v1[a];
v1[a] = v1[b];
v1[b] = temp1;
temp2 = v2[a];
v2[a] = v2[b];
v2[b] = temp2;
}
static void sort(int v1[], char *v2[], int left, int right, int (*comp)(const void *, const void *))
{
int i, last;
if (left >= right) return;
swap(v1, v2, left, (left + right) / 2);
last = left;
for (i = left + 1; i <= right; i++) {
if (comp(&v1[i], &v1[left]) < 0)
swap(v1, v2, ++last, i);
}
swap(v1, v2, left, last);
sort(v1, v2, left, last - 1, comp);
sort(v1, v2, last + 1, right, comp);
}
int main(void)
{
char *teams[] = {"England","Ireland","Wales","Scotland","France","Italy","Germany","Uraguay","Belgium","USA","Mexico","Australia","Belize","Denmark","Sweden","Japan","South Africa","Algeria"};
int points[] = {43,5,77,23,89,0,100,46,94,100,45,55,32,65,11,37,26,78};
size_t i, n = sizeof(points) / sizeof(*points);
sort(points, teams, 0, n - 1, comp);
for (i = 0; i < n; i++) {
printf("%s->%d\n", teams[i], points[i]);
}
return 0;
}
Output:
Italy->0
Ireland->5
Sweden->11
Scotland->23
South Africa->26
Belize->32
Japan->37
England->43
Mexico->45
Uraguay->46
Australia->55
Denmark->65
Wales->77
Algeria->78
France->89
Belgium->94
Germany->100
USA->100

How do I find distance between couple of points (x, y) from origin, and then sort the points, who is closest to (0, 0)?

i need to enter number of points(x,y), and then sort the points,from the closest one to (0,0) to the one that is far.. for example:
Enter number of points: 3
Enter point: 1 6
Enter point: 2 5
Enter point: 4 4
Sorted points:(2,5) (4,4) (1,6)
now i did a function that will find the distance,and i did an array and put the distance between two coordinate x and y,and i want to use merge sort to sort the array, my problem is how to go back and print the actual coordinate x y ... (i hope you would understand the problem),what can i do? i thought of putting the cordinate an array and sort them but that won't work :\
(and i didn't learn struct so i can't use unless if there is no other way ...)
plz anyone can help me i really have no idea have to continue:\
#include <stdio.h>
#include <stdlib.h>
void Enter_numbers(int x,int *z,int *first_coordinate,int *second_coordinate);
int distance(int a,int b);
void merge(int a[], int na, int b[], int nb, int c[]);
int merge_sort(int ar[], int n);
int main()
{
int x;
int *z;
int *first_coordinate;
int *second_coordinate;
printf("Enter number of points: ");
scanf("%d",&x);
z=(int*)malloc(x*sizeof(int));
first_coordinate=(int*)malloc(x*sizeof(int));
second_coordinate=(int*)malloc(x*sizeof(int));
Enter_numbers(x,z,first_coordinate,second_coordinate);
free(z);
free(first_coordinate);
free(second_coordinate);
return 0;
}
int distance(int a,int b)
{
int dis;
dis=((a*a)+(b*b));
return dis;
}
void Enter_numbers(int x,int *z,int *first_coordinate,int *second_coordinate)
{
int a=0,b=0;
int i=0;
int diss=0;
while(x>0)
{
printf("Enter points: ");
scanf("%d %d",&a,&b);
diss=distance(a,b);
z[i]=diss;
first_coordinate[i]=a;
second_coordinate[i]=b;
++i;
x--;
}
}
and the merge sort function i will use after i figure what to do :
int merge_sort(int ar[], int n)
{
int len;
int *temp_array, *base;
temp_array = (int*)malloc(sizeof(int)*n);
if(temp_array == NULL) {
printf("Dynamic Allocation Error in merge_sort");
return FAILURE;
}
for (len = 1; len < n; len *= 2) {
for (base = ar; base < ar + n; base += 2 * len) {
merge(base, len, base + len, len, temp_array);
memcpy(base, temp_array, 2*len*sizeof(int));
}
}
free(temp_array);
return SUCCESS;
}
and here is merge ...
void merge(int a[], int na, int b[], int nb, int c[])
{
int ia, ib, ic;
for(ia = ib = ic = 0; (ia < na) && (ib < nb); ic++)
{
if(a[ia] < b[ib]) {
c[ic] = a[ia];
ia++;
}
else {
c[ic] = b[ib];
ib++;
}
}
for(;ia < na; ia++, ic++) c[ic] = a[ia];
for(;ib < nb; ib++, ic++) c[ic] = b[ib];
}
I would use a struct for solving this task.
If you haven't learned struct yet, this seems to be a good time to learn it.
Note: If you really can't use stuct, see the last part of the answer.
With struct it could be something like:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int x;
int y;
int squared_distance;
} dpoint;
int squared_dst(int x, int y)
{
return (x*x + y*y);
}
// Compare function used for sorting
int compare_dpoint_dst(const void * e1, const void * e2)
{
dpoint* p1 = (dpoint*)e1;
dpoint* p2 = (dpoint*)e2;
if (p1->squared_distance > p2->squared_distance) return 1;
if (p1->squared_distance < p2->squared_distance) return -1;
return 0;
}
void print_dpoint(dpoint dp)
{
printf("(%d, %d) : sd = %d\n", dp.x, dp.y, dp.squared_distance);
}
#define N 5
int main(void) {
// Array of points (fixed size for simplicity)
dpoint ps[N];
// Dummy input (for simplicity)
int x[N] = {1,5,2,3,4};
int y[N] = {9,3,7,1,3};
for (int i = 0; i < N; ++i)
{
ps[i].x = x[i];
ps[i].y = y[i];
}
// Calculate squared distance for all points
for (int i = 0; i < N; ++i)
{
ps[i].squared_distance = squared_dst(ps[i].x, ps[i].y);
}
printf("unsorted:\n");
for (int i = 0; i < N; ++i)
{
print_dpoint(ps[i]);
}
// Sort the points
qsort (ps, sizeof(ps)/sizeof(*ps), sizeof(*ps), compare_dpoint_dst);
printf("sorted:\n");
for (int i = 0; i < N; ++i)
{
print_dpoint(ps[i]);
}
return 0;
}
Notice that you can do the sorting on the squared distance so that you don't need square root in the program.
The program above will generate:
unsorted:
(1, 9) : sd = 82
(5, 3) : sd = 34
(2, 7) : sd = 53
(3, 1) : sd = 10
(4, 3) : sd = 25
sorted:
(3, 1) : sd = 10
(4, 3) : sd = 25
(5, 3) : sd = 34
(2, 7) : sd = 53
(1, 9) : sd = 82
No use of struct
If you for some reason can't use struct, you can use a shadow array to track the sorting but you'll have to write your own sorting. I don't recommend this approach - learn about structinstead. Anyway, it could be something like:
int x[N];
int y[N];
int sd[N]; // squared distance
int sw[N]; // swap order
// read input and calculate distance
// ...
// Fill sw with 0, 1, 2, ....
for (int i=0; i < N; ++i) sw[i] = i;
mySort(sd, sw, N);
// Now you can use sw for printing
for (int i=0; i < N; ++i)
{
// print element sw[i]
printf("(%d,%d)\n", x[sw[i]], y[sw[i]]);
}
}
void mySort(int sd[], int sw[], int N)
{
// .... code for sorting
// ....
// Assume that you need to swap element i and j here
temp = sd[i];
sd[i] = sd[j];
sd[j] = temp;
// Then do exactly the same for sw
temp = sw[i];
sw[i] = sw[j];
sw[j] = temp;
// ....
// ....
}

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