How group students with different scores in leveled groups

Viewed 38

I need to create groups of students to work together, but i need to level the groups using his grades. So, i don't want only the good grades students in one hand and the bad grades on other. I want to mix them all using his grades to randomize that.

So, i have the name and the score for every student. I need 3 homework groups, so i calculated the score of all / 3. To know the value who every single group need.

Now it's the problem, i don't know how can i insert the students in this groups without be over the max value for one group and how guarantee every group with same number of students.

Until now, i make this:

var totalScore = 0;

for (var i = 0; i < students.length; i++) {
    totalScore = totalScore + students[i].score;
}

var maxScoreForGroup = totalScore / 3;

console.log(maxScoreForGroup);

for (var o = 0 ; o < students.length; o++) {
    if ((students[o].score + homeWork1[0].scoreTotal) < maxScoreForGroup) {
    homeWork1[0].students.push(students[o].name);
    homeWork1[0].scoreTotal = homeWork1[0].scoreTotal + students[o].score;
  } else if ((students[o].score + homeWork2[0].scoreTotal) < maxScoreForGroup) {
    homeWork2[0].students.push(students[o].name);
    homeWork2[0].scoreTotal = homeWork2[0].scoreTotal + students[o].score;
  } else {
    homeWork3[0].students.push(students[o].name);
    homeWork3[0].scoreTotal = homeWork3[0].scoreTotal + students[o].score;
  }
}

But i'm getting in homeWork1 only 2 students with score 10 each, in homework2 only 2 students with score 10 and 7.5, and in homework 3 every other student.

How can i change this to get 3 groups with 3 students and every group with the same score total?

My array of students

var students = [
    {
    "name": "Charles",
    "score": 10
  },
  {
    "name": "Max",
    "score": 10
  },
    {
    "name": "Samuel",
    "score": 10
  },
    {
    "name": "Carl",
    "score": 7.5
  },
    {
    "name": "James",
    "score": 7.5
  },
    {
    "name": "Frank",
    "score": 7.5
  },
    {
    "name": "George",
    "score": 5
  },
    {
    "name": "Timothy",
    "score": 5
  },
    {
    "name": "Paul",
    "score": 5
  },
]

My output is

"[{"scoreTotal":20,"students":["Charles","Max"]}]"
"[{"scoreTotal":17.5,"students":["Samuel","Carl"]}]"
"[{"scoreTotal":30,"students":["James","Frank","George","Timothy","Paul"]}]"

I made this fiddle too

2 Answers

I have used this link first answer helped by James to separate my students in different arrays. That worked really well.

Thanks for the help.

Here's another approach that might work for you.

We shuffle the students array, split into groups of n students (in this case 3), then get the total scores of each group.

If the groups have the same total score we add to our possibleGroups array.

You can change the number of attempts or just repeat to get different groupings.

const students = [ { "name": "Charles", "score": 10 }, { "name": "Max", "score": 10 }, { "name": "Samuel", "score": 10 }, { "name": "Carl", "score": 7.5 }, { "name": "James", "score": 7.5 }, { "name": "Frank", "score": 7.5 }, { "name": "George", "score": 5 }, { "name": "Timothy", "score": 5 }, { "name": "Paul", "score": 5 }, ] 

function shuffle(arr) {
    for (let i = arr.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [arr[i], arr[j]] = [arr[j], arr[i]];
    }
    return arr;
}

function getTotalScore(a) { 
    return a.reduce((total, student) => total + student.score, 0);
}

function allEqual(a) {
    return (new Set(a).size) === 1;
}

function split(a, groupSize) {
    return a.reduce((sums, x, idx) => { 
        if (idx % groupSize === 0) {
            sums.push([]);
        }
        sums[sums.length - 1].push(x);
        return sums;
    }, [])
}

let attempts = 20;
let n = 3;

let possibleGroups = [];
for(let i = 0; i < attempts; i++) {
    let groups = split(shuffle([...students]), n);
    let scores = groups.map(getTotalScore);
    if (allEqual(scores)) {
        possibleGroups.push( { scoreTotal: scores[0], groups } );
    }
}

console.log('Possible groupings:');
possibleGroups.forEach((group, idx) => { 
    console.log(`Grouping ${idx + 1}:`);
    console.log(JSON.stringify(group, null, 2))
})
.as-console-wrapper { max-height: 100% !important; }

Related