Jak policzyć countback?

0

Cześć.
Od jakiegoś czasu, rozwiązując pewien problem, po pokonaniu jednej przeszkody natrafiam na 3 następne.

var wyniki =
{
	tablica: [
	["sierotka", "marysia", 2, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 1, 2],
	["wilk", "zLasu", 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 1, 2],
	],
	ranking: [
	["sierotka", "marysia", 53],
	["wilk", "zLasu", 53]
	],
}

Potrzebuję policzyć countback. To znaczy: W wypadku dwóch osób o tej samej liczbie punktów liczy się pierwsza konkurencja potem druga, trzecia ... i aż nie będzie się różnić.
Na własnej skórze doświadczyłem że javascript zaokrągla liczby większe niż 13 lub 16 (nie pamiętam) miejsc po przecinku.
Więc countbacku nie jestem w stanie policzyć mnożąc przez kolejne ujemne potęgi 10 i segregując.
Nie mam pojęcia jak to policzyć (przypisać odpowiednie miejsca osobom z tą samą liczbą punktów).
Pomocy!

0

Nie rozumiem dlaczego chcesz na siłę budować z tego jedną liczbę.
Co jest nie tak z wykorzystaniem pętli?

const firstScore = [1, 2, 3, 4, 5, 6];
const secondScore = [1, 2, 3, 40, 50, 60];

// Podejście z wykorzystaniem biblioteki standardowej:
const idx = firstScore.find((score, scoreIdx) => {
  return score > secondScore[scoreIdx];
});

// -> jeśli idx === undefined, wygrał drugi gracz; w przeciwnym wypadku wygrał pierwszy

// Podejście z wykorzystaniem pętli:
for (let i = 0; i < firstScore.length; ++i) {
  if (firstScore[i] > secondScore[i]) {
    // wygrał gracz A
  }

  if (secondScore[i] > firstScore[i]) {
    // wygrał gracz B
  }
}
0

A czy to ma zastosowanie również gdy jest powiedzmy 30 osób z tym samym wynikiem i każdy ma inaczej rozłożone punkty?

0

Akurat mój przykład jest dla dwóch osób - dla większej liczby trzeba będzie podejść nieco inaczej.
Jak zrobiłbyś to przeliczenie ręcznie, na kartce?

0

Najprościej to by było przemnożyć przez te potęgi 10'tki. Potem tylko posortować i voilà. Bo jak to analizuje po jednym na kartce to to wszystko rozbija się na przypadki a te przypadki na kolejne przypadki.

0

O ile Twoją odpowiedzią nie jest mnożyłbym ręcznie przez potęgi dziesiątek, nie udzieliłeś odpowiedzi na moje pytanie.

0

Lol nie. Najpierw w pierwszej konkurencji grupuje ludzi co mieli po 0 po 1 i po 2. Potem każdą z tych grup grupuję na kolejną podgrupę. Czyli na przykład:
2->1 2->2 2->0 i tak dalej i tak dalej aż każdy jest w jednej grupie.

0

Powiedzmy, że mamy taką punktację:

Osoba | K1 | K2 | K3 | K4 | Suma
---- |
Jan | 2 | 2 | 5 | 10 | 19
Paweł | 2 | 2 | 4 | 11 | 19
Mateusz | 5 | 5 | 0 | 0 | 10

Możesz rozpisać, jak widzisz to (ręcznie) na tym przykładzie?

0

Osoba | K1 | K2 | K3 | K4 | Suma
---- |
Jan | 2 | **2 **| 5x | 10 | 19
Paweł | 2 | 2 | 4y | 11p | 19
Naruto | 2 | 2 | 4y | 12j | 18

Mateusz | 5 | 5 | 0 | 0 | 10

x - grupa 2boldX
y - grupa 2boldY
j - grupa 2boldYj
p - grupa 2boldYp

Dla ostatniego nie liczę countbacku bo nie ma innego z tą samą liczbą punktów.
Poza tym w konkurencji można zdobyć 0 1 lub 2 punkty.
Lepiej by to wyglądało z kolorami ale mi się nie chciało ;-)

0

Czym są 2boldX, 2boldY i tym podobne?

0

Grupami. Żeby każdy uczestnik miał indywidualną grupę. Ale to służy wyłącznie obliczeniom na kartce bo prościej posługiwać się liczbami.

0

Hm, popraw mnie jeśli się mylę, ale czy w takim wypadku nie wystarczy podejść tak:

Wejście:
> Jan: 2, 2, 5, 10 (suma: 19)
> Paweł: 2, 2, 4, 11 (suma: 19)
> Naruto: 2, 2, 4, 10 (suma: 18)
> Mateusz: 5, 5, 0, 0 (suma: 10)

-> Czwarte miejsce przypisujemy Mateuszowi, ponieważ ma najmniej punktów.

Pozostał: Jan, Paweł oraz Naruto.

-> Trzecie miejsce przypisujemy Naruto, ponieważ ma aktualnie najmniej punktów (po wyrzuceniu z listy Mateusza).

Pozostał: Jan oraz Paweł.

-> Drugie miejsce przypisujemy Pawłowi, ponieważ sprawdzamy: 2 == 2, 2 == 2, 4 < 5

Pozostał: Jan.

-> Pierwsze miejsce przypisujemy Janowi, ponieważ tylko on został.

Nie rozumiem, dlaczego dokonujesz tego enigmatycznego podziału na jakieś grupy 2boldYp czy inne.

0

Mam braki w dziedzinie algorytmiki i improwizuje. Twój pomysł świetny tylko nie wiem jak go zakodować :D

2

Taka wersja napisana na kolanie:

function getHighestScore(scores) {
    let highestScore = scores[0];

    for (let i = 1; i < scores.length; ++i) {
        const currentScore = scores[i];

        // Jeśli sumaryczna liczba punktów jest mniejsza, od razu odrzuć ten wynik
        if (currentScore.summary < highestScore.summary) {
            continue;
        }

        // Jeśli sumaryczna liczba punktów jest większa, od razu wybierz ten wynik
        if (currentScore.summary > highestScore.summary) {
            highestScore = currentScore;

            continue;
        }

        // Jeśli sumaryczna liczba punktów jest taka sama - porównaj każdy punkt osobno
        for (let j = 0; j < currentScore.points.length; ++j) {
            // Jeśli aktualnie przetwarzany gracz ma punkt o mniejszej wartości, od razu przerwij przetwarzanie;
            // Jest to sytuacja, która ma miejsce w przypadku porównywania Pawła oraz Jana (tj.: 4 < 5)
            if (currentScore.points[j] < highestScore.points[j]) {
                break;
            }

            // Jeśli aktualnie przetwarzany gracz ma punkt o większej wartości, wybierz tego gracza
            if (currentScore.points[j] > highestScore.points[j]) {
                highestScore = currentScore;
            }
        }
    }

    return highestScore;
}

function getWinners(scores) {
    const winners = [];

    while (scores.length > 0) {
        const highestScore = getHighestScore(scores);

        // Zapisz gracza do listy wygranych
        winners.push(highestScore.name);

        // Usuń wynik z puli
        scores.splice(scores.indexOf(highestScore), 1);
    }

    return winners;
}

console.log(
    getWinners([
        {name: 'Paweł', points: [2, 2, 4, 11], summary: 19},
        {name: 'Jan', points: [2, 2, 5, 10], summary: 19},
        {name: 'Mateusz', points: [5, 5, 0, 0], summary: 10},
        {name: 'Naruto', points: [2, 2, 4, 10], summary: 18},
    ]),
);

Spróbuj przeanalizować, co tu się dzieje (choć nie jest łatwo ;-)).

2

Inny sposób:

const example = [
  {name: 'Paweł', points: [2, 2, 4, 11], summary: 19},
  {name: 'Jan', points: [2, 2, 5, 10], summary: 19},
  {name: 'Mateusz', points: [5, 5, 0, 0], summary: 10},
  {name: 'Naruto', points: [2, 2, 4, 10], summary: 18},
]

const getWinners = (arr) => {
  return [...arr]
    .sort((a, b) => {
      if(a.summary !== b.summary) {
        return b.summary - a.summary
      }
    
      for (let i = 0; i < a.points.length; i++) {
        if (a.points[i] !== b.points[i]) {
          return b.points[i] - a.points[i]
        }
      }
    })
    .map(item => item.name)
}

console.log(getWinners(example)) // ["Jan", "Paweł", "Naruto", "Mateusz"]
0

Tak sobie wracam do tego wątku z nieco większą wiedzą i się zastanawiam....
@Maciej Cąderek czemu zamiast po prostu arr napisałeś [...arr] ?

1

Żeby zrobić kopię tablicy i nie zmieniać tablicy początkowej niepotrzebnie (.sort() modyfikuje tablicę)

1 użytkowników online, w tym zalogowanych: 0, gości: 1