Skip to content

Instantly share code, notes, and snippets.

@kyle-west
Last active December 7, 2023 17:04
Show Gist options
  • Save kyle-west/087fd0bdb416f458a1ef28f143bf9083 to your computer and use it in GitHub Desktop.
Save kyle-west/087fd0bdb416f458a1ef28f143bf9083 to your computer and use it in GitHub Desktop.
Classic Secret Santa Problem in 4 lines. Guarantees mathematically that no one will give to themselves and no two will give to each other.
function secretSanta(...names) {
const randomized = [...names].sort(() => Math.random() - Math.random());
const derrangement = [...randomized]
derrangement.unshift(derrangement.pop()) // shifting ensures a derrangement of the randomized list
return Object.fromEntries(randomized.map((name, idx) => [name, derrangement[idx]]))
}
secretSanta('Alice', 'Bob', 'Carter', 'David', 'Emily')
// { Carter: 'Emily', Bob: 'Carter', David: 'Bob', Alice: 'David', Emily: 'Alice' }
@kyle-west
Copy link
Author

For explanation of the math behind how this works: https://www.youtube.com/watch?v=5kC5k5QBqcc

@kyle-west
Copy link
Author

kyle-west commented Sep 30, 2022

You can also do all this as a one-liner, but it is much less readable:

const secretSanta = 
  (...names) => Object.fromEntries(
    [...names].sort(() => Math.random() - 0.5)
              .map((giver, idx, getters) => [giver, getters[(idx + 1) % getters.length]])
  )

@kyle-west
Copy link
Author

kyle-west commented Dec 7, 2023

As a party trick, here is that same function minimized (under 100 bytes - it's 94, even room to add a let at the front and still be under):

s=(...n)=>Object.fromEntries(n.sort(_=>Math.random()-.5).map((x,i,a)=>[x,a[(i+1)%a.length]]))

@kyle-west
Copy link
Author

kyle-west commented Dec 7, 2023

Unrelated

FizzBuzz in 39 bytes:

f=n=>(n%3?'':'Fizz')+(n%5?'':'Buzz')||n

isPalindrome in 46 bytes:

p=s=>[...s].every((c,i)=>c==s[(s.length-i)-1])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment