1

I have 2 arrays, in parallel:

defenders = {1,5,7,9,12,18};
attackers = {3,10,14,15,17,18};

Both are sorted, what I am trying to do is rearrange the defending array's values so that they win more games (defender[i] > attacker[i]) but I am having issues on how to swap the values in the defenders array. So in reality we are only working with the defenders array with respect to the attackers.

I have this but if anything it isn't shifting much and Im pretty sure I'm not doing it right. Its suppose to be a brute force method.

void rearrange(int* attackers, int* defenders, int size){
int i, c, j;
int temp;

for(i = 0; i<size; i++){
  c = 0;
  j = 0;
  if(defenders[c]<attackers[j]){
            temp = defenders[c+1];
            defenders[c+1] = defenders[c];
            defenders[c] = temp;
            c++;
            j++;
     }
    else
        c++;
        j++;

   }
}

Edit: I did ask this question before, but I feel as if I worded it terribly, and didn't know how to "bump" the older post.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Jude
  • 449
  • 1
  • 7
  • 17
  • You are initializing `c` and `j` in beginning of each loop. Is it OK? – MikeCAT Mar 07 '16 at 01:21
  • Note: Be careful not to cause out-of-range access. – MikeCAT Mar 07 '16 at 01:22
  • @MikeCAT I was doing this so c and j wouldn't become huge numbers. I also had an if statement to limit c+1 but it didn't do much. – Jude Mar 07 '16 at 01:24
  • 1
    Possible duplicate of [Rearrange an array to be optimal in comparison to another array](http://stackoverflow.com/questions/35806804/rearrange-an-array-to-be-optimal-in-comparison-to-another-array) – Tom Karzes Mar 07 '16 at 01:26
  • Also note that the only the first of the statements after `else` is run in the else case. The second (`j++`) is executed unconditionally. – Daniel Jour Mar 07 '16 at 01:27
  • 1
    @gsamaras yes I edited the my post to include my explanation – Jude Mar 07 '16 at 01:30
  • OK I saw that good. Why you are not happy with the answer there @Jude? – gsamaras Mar 07 '16 at 01:31
  • @gsamaras Well kind of a dumb reason, but I was actually a bit loss on the explanation he gave me but I did not really want to reply with constant questions. I was hoping with a better explanation perhaps with code I've already attempted I see something I feel more in tune with. – Jude Mar 07 '16 at 01:35
  • OK @Jude, next time do not accept the answer and ask questions, but for now, let me recap, you can modify the `defenders` array, but we keep the attackers array fixed, right? – gsamaras Mar 07 '16 at 01:38
  • @gsamaras Yes the attackers array is fixed – Jude Mar 07 '16 at 01:42
  • OK, I am working on it @Jude! – gsamaras Mar 07 '16 at 01:44
  • for ease of understanding and readability by us humans: 1) indent consistently (as if all optional braces writen) indent after every opening brace '{'. unindent before every closing brace '}'. never use tabs for indenting because every wordprocessor/editor has the tab stops/tab widths set differently. Suggest using 4 spaces per indent level as that is visible even with variable width fonts. 2) follow the axiom: *only one statement per line and (at most) one variable declaration per statement.* – user3629249 Mar 07 '16 at 03:54
  • what, exactly, constitutes a win (or loss) between the attackers and the defenders? – user3629249 Mar 07 '16 at 03:55
  • The increment through the two arrays is never done because the variable `i` is not being used in the `for()` loop and `c` and `j` are being reset to 0 inside the top of the `for()` loop. So only the first two entries in the defenders[] array and the first entry in the `attackers[]` array are ever accessed. So the most this loop does is 'maybe' swap the first two entries in `defenders[]` – user3629249 Mar 07 '16 at 04:03

2 Answers2

0

The problem is that you are resetting c and j to zero on each iteration of the loop. Consequently, you are only ever comparing the first value in each array.

Another problem is that you will read one past the end of the defenders array in the case that the last value of defenders array is less than last value of attackers array.

Another problem or maybe just oddity is that you are incrementing both c and j in both branches of the if-statement. If this is what you actually want, then c and j are useless and you can just use i.

I would offer you some updated code, but there is not a good enough description of what you are trying to achieve; I can only point out the problems that are apparent.

Nicholas Smith
  • 975
  • 7
  • 18
0

To be honest, I didn't look at your code, since I have to wake up in less than 2.30 hours to go to work, hope you won't have hard feelings for me.. :)


I implemented the algorithm proposed by Eugene Sh. Some links you may want to read first, before digging into the code:

  1. qsort in C
  2. qsort and structs
  3. shortcircuiting

My approach:

  1. Create merged array by scanning both att and def.
  2. Sort merged array.

  3. Refill def with values that satisfy the ad pattern.

  4. Complete refilling def with the remaining values (that are defeats)*.

*Steps 3 and 4 require two passes in my approach, maybe it can get better.

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  char c; // a for att and d for def
  int v;
} pair;

void print(pair* array, int N);
void print_int_array(int* array, int N);
// function to be used by qsort()
int compar(const void* a, const void* b) {
    pair *pair_a = (pair *)a;
    pair *pair_b = (pair *)b;
    if(pair_a->v == pair_b->v)
        return pair_b->c - pair_a->c; // d has highest priority
    return pair_a->v - pair_b->v;
}

int main(void) {
    const int N = 6;
    int def[] = {1, 5, 7, 9, 12, 18};
    int att[] = {3, 10, 14, 15, 17, 18};
    int i, j = 0;
    // let's construct the merged array
    pair merged_ar[2*N];
    // scan the def array
    for(i = 0; i < N; ++i) {
        merged_ar[i].c = 'd';
        merged_ar[i].v = def[i];
    }
    // scan the att array
    for(i = N; i < 2 * N; ++i) {
        merged_ar[i].c = 'a';
        merged_ar[i].v = att[j++]; // watch out for the pointers
        // 'merged_ar' is bigger than 'att'
    }
    // sort the merged array
    qsort(merged_ar, 2 * N, sizeof(pair), compar);
    print(merged_ar, 2 * N);
    // scan the merged array
    // to collect the patterns
    j = 0;
    // first pass to collect the patterns ad
    for(i = 0; i < 2 * N; ++i) {
        // if pattern found
        if(merged_ar[i].c == 'a' &&     // first letter of pattern
           i < 2 * N - 1         &&     // check that I am not the last element
           merged_ar[i + 1].c == 'd') {     // second letter of the pattern
            def[j++] = merged_ar[i + 1].v;  // fill-in `def` array
            merged_ar[i + 1].c = 'u';   // mark that value as used
        }
    }
    // second pass to collect the cases were 'def' loses
    for(i = 0; i < 2 * N; ++i) {
        // 'a' is for the 'att' and 'u' is already in 'def'
        if(merged_ar[i].c == 'd') {
            def[j++] = merged_ar[i].v;
        }
    }
    print_int_array(def, N);
    return 0;
}

void print_int_array(int* array, int N) {
    int i;
    for(i = 0; i < N; ++i) {
        printf("%d ", array[i]);
    }
    printf("\n");
}

void print(pair* array, int N) {
    int i;
    for(i = 0; i < N; ++i) {
                printf("%c %d\n", array[i].c, array[i].v);
        }
}

Output:

gsamaras@gsamaras:~$ gcc -Wall px.c
gsamaras@gsamaras:~$ ./a.out 
d 1
a 3
d 5
d 7
d 9
a 10
d 12
a 14
a 15
a 17
d 18
a 18
5 12 18 1 7 9
Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • Now I felt I should of added my entire code, I am a bit unsure how to add this but I scanned in the values into my 2 arrays (defender/attackers) that are both dynamically allocated. I then called mergesort on both arrays. Which is how I have the end result array in my original question. I am not sure how easily I can make things work with a struct but I can try – Jude Mar 07 '16 at 02:29
  • Well I worked on my approach now @Jude and it works nicely. Hope it helps. :D You can re-think why your approach didn't work in first place. Also, nice question, +1. – gsamaras Mar 07 '16 at 02:30
  • @Jude why not using a struct? Because your arrays are dynamically allocated? It doesn't make a difference when using the arrays (if they are dynamically allocated or not!!). – gsamaras Mar 07 '16 at 02:33
  • REALLY? I didn't see anywhere that mention @TomKarzes. Even if that's the case, I hope he will actually *study* my answer and learn! Thanks for the upvote anyway. :) – gsamaras Mar 07 '16 at 07:31
  • Well, it's a duplicate (and should have been closed as such). There were two other identical posts before this one. So yeah, homework assignment. – Tom Karzes Mar 07 '16 at 07:33
  • You are right @TomKarzes, at least there are two good answers now. – gsamaras Mar 07 '16 at 07:35