I have an array with 8 numbers, 1-8
arr = [1, 2, 3, 4, 5, 6, 7, 8]
each number in the array is part of a group
1 & 2 - group a
3 & 4 - group b
5 & 6 - group c
7 & 8 - group d
What I need to do is match each number in my array, with another number from the same array, but they can not be in the same group
- 1 & 2 may not be matched with 1 or 2
- 3 & 4 may not be matched with 3 or 4
- 5 & 6 may not be matched with 5 or 6
- 7 & 8 may not be matched with 7 or 8
Conditions
- May not be predetermined, given the same inputs, different solutions must be possible
- no repeat pairings for example if 2 pairs with 8, 4 can not also pair with 8
- They must be paired one at a time, with the ability to leave some pairings unfinished and come back at a later date to complete more pairings
- Pairings cannot be reset or undone, once paired it is permanent
- One pairing can not run both ways in all cases. For example, if 2 is paired to 3 then 3 can not always pair with 2. It is acceptable if this happens from time to time, but it can not be an intended feature.
- We can not assume the pairings will be made in any specific order. For example, the first pairing may be made by 1, or maybe 7 or 3 and so on. Any number may need to be paired at any time.
My problem is that if you pick it in just the right order, you can get stuck on the last number where the only pairing left would be to pair with itself or it's groupmate.
I want to stress a condition here because it keeps being overlooked in answers. I want pairings to be made one at a time. This means that you should be able to space making each pairing out as far as you want. I want to be able to make a pairing on day 0, and then I can come back day 1, week 2, or year 2750 to make the second pairing. This is necessary. Each and every single pairing must be made completely independent of each other, and at the end, the last number must be still able to make a valid pairing.
example...
6 with 8
7 with 6
5 with 7
3 with 5
8 with 4
2 with 3
4 with 2
1 with _
This order leaves 1 with no option but itself.
What can I do to make it so no matter what the last number always has a viable pairing?
update: I have added a fairly good solution in the answers section. If you are still struggling to understand what I want to accomplish try reading my answer in the answers section. The attached code is outdated since I have found a currently usable answer.
antiquated code below
function selectGiftee(req, res, db){
const {user_id, group_id} = req.body
db.select('name', 'user_id', 'giftee_id', 'group_id').from('users')
.then (data => {
if (data.length) {
// only sending available giftees
const taken = [];
const fullList = [];
let available = [];
// figure out which giftees are taken
data.forEach( user => {
if (user.giftee_id !== null){
taken.push(user.giftee_id)
}
if (user.group_id === group_id) {
taken.push(user.user_id)
}
})
// add all giftees to a list
data.forEach( user => {
fullList.push(user.user_id)
})
// only add available giftees to the available list
available = fullList.filter(val => !taken.includes(val));
// respond with only giftees that are not taken
res.json(available)