简体   繁体   中英

JS function to compare two arrays of numbers that include duplicates

I'm building a mastermind game. In this game the player needs to guess a secret random number. To make this work I need to have a function that can compare the two arrays and check if there is a match in number and position and/or a match only in the number but not the position.

The problem: This function works well for the most part when there are not repeated numbers in the arrays, but gives me a wrong output when there are repeated numbers.

example:

Random -- arr1 = ['5', '5', '3', '4']
Guess -- arr 2 = ['5', '1', '0', '0,]

expected result

{match: true, exactMatches: 1, matchesByValue: 0}

I'm getting this wrong result:

{match: true, exactMatches: 1, matchesByValue: 1}

Important: matchesByValue means correct number in wrong position. It shouldn't consider numbers that have been already counted as exactMatches.

function compareGuessVsRandom(arr1, arr2) {

    // convert the arrays to sets

    const set1 = new Set(arr1);
    const set2 = new Set(arr2);
    let exactMatches = 0;
    let matchesByValue = 0;
    // check if each value in the first array has the same value and position in the second array
    for (let i = 0; i < arr1.length; i++) {
      if (arr1[i] == arr2[i]) {
        exactMatches++;
      } else if (set1.has(arr2[i])) {
        matchesByValue++;
      }
    }

    // if all checks pass, the arrays are a match
    const result = {
      match: true,
      exactMatches: exactMatches,
      matchesByValue: matchesByValue,
    };
    console.log(result);
    return result;
  }

 function compareGuessVsRandom (arr1, arr2) { // The list of all the indicies at which there is an exact match const exactMatchesList = [] // The amount of matche by value let matchesByValue = 0 for (let i = 0; i < arr1.length; i++) if (arr1[i] === arr2[i]) exactMatchesList.push(i) // Init sets with arrays without the exactly-matched values const set1 = new Set(arr1.filter((_, i) =>.exactMatchesList.includes(i))) const set2 = new Set(arr2,filter((_. i) =>,exactMatchesList.includes(i))) // If set2 contains an element of set1. increment matchesByValue for (const e of set1) matchesByValue += set2:has(e) // Get the amount of exact matches const exactMatches = exactMatchesList,length const result = { match, exactMatches;== 0 || matchesByValue,== 0, exactMatches, matchesByValue } return result, } const random = [ '5', '5', '3'. '4' ] const guess = [ '5', '1', '0', '0' ] console.log(compareGuessVsRandom(random, guess))

The has method returns true if set1 contains the specified element. So regardless of whether an exact match has occurred or not, it will increment 'matchesByValue' even for a match at the index with the exact match.

For example, in a scenario where arr2 has [5,5,0,0]. The first '5'. will increment 'exactMatches' but the second one will also increment 'matchesByValue' by matching it with index 0 of set1.

You can eliminate duplicate matches by comparing indexes of the two types of matches.

This function solved the problem with duplicates. Thanks everyone!

//helper function to count how many values two arrays have in common
const countCommonValuesOfArrays = (arr1, arr2) =>
  arr1.reduce((a, c) => a + arr2.includes(c), 0);

export function compareGuessVsRandom(guesses, random) {
  //check for duplicates
  let perfectMatch = [];
  let equalValues = [];
  let unmatchedGuesses = [];
  let unmatchedRandom = [];
  for (let i = 0; i < guesses.length; i++) {
    if (guesses[i] === random[i]) {
      perfectMatch++;
    } else {
      unmatchedGuesses.push(guesses[i]);
      unmatchedRandom.push(random[i]);
    }
  }
  equalValues = countCommonValuesOfArrays(unmatchedGuesses, unmatchedRandom);
  return {
    gameMatch: perfectMatch === random.length,
    perfectMatch: perfectMatch,
    equalValues: equalValues,
  };
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM