Naeem Khan
Naeem Khan

Reputation: 960

Comparing two array values in C

I am writing a program for school project in C which compares the values of two arrays and gives specific results depending on what the input was from user. Basically my output values are two, correctPosition and correctValue.

correctValue is a value that is in the valuesArray but not at the correct position in inputArray, for example; value "4" is at index 1 of valuesArray but is located at index 2 of inputArray.

correctPosition is a value that at the same index in both valuesArray and inputArray. For example; value "3" is at index 1 of valuesArray and inputArray

If an x value between two arrays match, then it can either be a correctValue or correctPosition. Here's a visual representation:

valuesArray: 2 3 3
------------------
inputArray:  1 2 3
Answer: correctPosition = 1, correctValue = 1.

inputArray:  2 1 3
Answer: correctPosition = 2, correctValue = 0.

inputArray:  2 3 3
Answer: correctPosition = 3, correctValue = 0.

Here's the code I have written for this:

#include <stdio.h>

int main() {

  int inputArray[3], valuesArray[3];
  int correctNumber = 0, positionMatch = 0;
  int x, y;
  int visitedMatch[3];

  valuesArray[0] = 2;
  valuesArray[1] = 3;
  valuesArray[2] = 3;
  inputArray[0] = 1;
  inputArray[1] = 2;
  inputArray[2] = 3;

  for( x = 0; x < 3; x++) {
    visitedMatch[x] = 0;
  }

  for(x = 0; x < 3; x++) {
    for(y = 0; y < 3; y++) {
      if (inputArray[x] == valuesArray[y] && visitedMatch[y] == 0) {
        if (x == y) { positionMatch++; } else { correctNumber++; }
        visitedMatch[y] = 1;
        break;
      }
    }
  }

  printf("correctPosition = %d, ", positionMatch);
  printf("correctValues = %d\n", correctNumber);
  return 0;
}

The problem is that for input 1 2 3, it first takes 1 and checks in the valuesArray and cannot find anything, so result stays 0. Then in second iteration where x = 1, it takes 2 and checks that it is in the array but not at the correct index, so correctValue counter becomes 1. Now in the final iteration where x = 2, it takes 3 and goes through the loop and finds the FIRST value "3" at index 2 because it was never visited before, so the final result becomes correctPosition = 0, correctValue = 2. If I write the input as 2 3 3, then it works fine and the output is correctPosition = 3, correctValue = 0. How can I fix this, what am I missing here?

Any help will be really appreciated.

Upvotes: 0

Views: 99

Answers (2)

bruno
bruno

Reputation: 32596

An other solution, a little more simple than the John Bollinger algorithm :

  • count the exact match and indicate these positions to be forget in both arrays

  • for each non forget position from inputArray seach the value in non forget position of valuesArray

    • if found for the first time increment correctNumber and indicate this position in valuesArray to be forget
    • if found but not the first time just indicate this position in valuesArray to be forget

The implementation can be (because I am lazy right now I give the values for the _inputArray through the preprocessor identifier I, see the compilations)

#include <stdio.h>

#define SZ 3

int main() {
  int valuesArray[SZ] = { 2,3,3 };
  int inputArray[SZ] = { I };
  int correctNumber = 0, positionMatch = 0;
  int x, y;
  int forgetValues[SZ] = { 0 }; /* useless to give more value because want 0 for the others */
  int forgetInput[SZ] = { 0 }; /* useless to give more value because want 0 for the others */

  /* count the exact matches */
  for (x = 0; x < SZ; x += 1) {
    if (inputArray[x] == valuesArray[x]) {
      positionMatch += 1;
      printf("correct match %d index %d\n", inputArray[x], x);
      forgetValues[x] = forgetInput[x] = 1; /* do not consider that position later */
    }
  }

  /* count correct values */
  for (x = 0; x < SZ; x += 1) {
    if (!forgetInput[x]) {
      int v = inputArray[x];
      int found = 0;

      for(y = 0; y < SZ; y += 1) {
        if (!forgetValues[y] && (valuesArray[y] == v)) {
          if (!found) {
            /* first time, count it */
            correctNumber += 1;
            found = 1;
            printf("correct value %d index %d / %d\n", v, x, y);
          }
          forgetValues[y] = 1; /* do not consider it later */
        }
      }
    }
  }

  printf("correctPosition = %d, ", positionMatch);
  printf("correctValues = %d\n", correctNumber);
  return 0;
}

Compilations and executions ;

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall -DI=1,2,3 c.c
pi@raspberrypi:/tmp $ ./a.out
correct match 3 index 2
correct value 2 index 1 / 0
correctPosition = 1, correctValues = 1
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall -DI=2,1,3 c.c
pi@raspberrypi:/tmp $ ./a.out
correct match 2 index 0
correct match 3 index 2
correctPosition = 2, correctValues = 0
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall -DI=2,3,3 c.c
pi@raspberrypi:/tmp $ ./a.out
correct match 2 index 0
correct match 3 index 1
correct match 3 index 2
correctPosition = 3, correctValues = 0

Upvotes: 1

John Bollinger
John Bollinger

Reputation: 181104

As I wrote in comments, I suggest a different approach. Yours is a bit untidy algorithmically, because logically, the evaluation of positionMatch contributors involves comparing each input value to exactly one corresponding other position, whereas evaluation of valueMatch contributors involves comparing each input value to the whole board.

These would be cleaner if separated. If you had to worry about handling very large boards, then it would also be relevant that separating the two steps could produce a solution whose cost scales linearly with the size of the board instead of quadratically. Specifically, the approach I'm suggesting is

  1. Scan the two arrays once to compute the positionMatch count and to build for each array a histogram of the number of appearances of each symbol.

  2. Scan the two histograms, computing a sum of the the minimum, for each symbol, of the number of counts for that symbol in the two histograms. This yields the total number of correct numbers, but does not distinguish those in the correct position from those incorrect positions.

  3. Subtract the positionMatch computed in (1) from the sum computed in (2) to yield the correctNumber.

With that said, however, you should be able to tweak your current code to compute the correct results. The main thing missing is avoiding use of an element of the valuesArray that should provide a positionMatch to instead provide a correctNumber. But that's a situation that you can test. When you detect a match (inputArray[x] == valuesArray[y] && visitedMatch[y] == 0), you presently exercise one of only two alternatives, depending on whether x == y. To compute the counts correctly, you should instead have three:

  • If x == y then increment positionMatch and break from the inner loop. (You can mark the position visited, too, but you don't need to do.)
  • Otherwise, if inputArray[y] == valueArray[y] then do nothing. That element of valueArray did or will contribute to positionMatch, so it should not contribute to correctNumber. Just continue to the next inner-loop iteration.
  • Else increment correctNumber, mark position y visited, and break from the inner loop

Alternatively, you could adapt your current approach to simulate my suggested one without actually constructing physical histograms. These changes would be needed:

  • In the outer loop, determine whether to increment positionMatch. Continue to the inner loop either way.
  • In the inner loop, ignore whether x == y, and instead increment correctNumber and mark the position visited whenever you find a match. This is a substitute for computing and evaluating histograms.
  • at the end, subtract positionMatch from correctNumber before reporting the results.

Upvotes: 2

Related Questions