2

Given an array [1, 2, 2, 3, 4, 4, 5], is it possible to shuffle the array while preventing the duplicates to be next to each other?

For example:

  • [1, 2, 3, 4, 2, 5, 4] is an acceptable solution.
  • [1, 2, 3, 4, 4, 2, 5] is not an acceptable solution since 4 is next to another 4

This seems like a simple question but after thinking about it, the solution seems complicated. Any help is greatly appreciated, thanks!!

  • Where's the data coming from? What's the guarantee that this stays solvable? You commented beneath something about 3 dupes in 60items. What's the average/worst rate of duplicates? – Thomas Feb 25 '22 at 08:43
  • I'm manipulating the data so it should always be solvable. Right now the most duplicates that could occur is 3 but that's subject to change in the future, could be more or less – Brandon Bohach Feb 26 '22 at 21:42

1 Answers1

0

If you don't care about the execution time of the algorithm, just shuffle a few times until you get the result you want

let arr = [1, 2, 2, 3, 4, 4, 5];

const hasDublicateItems = (arr) => arr.some((v, i, a) => v === a[i+1]);

while (hasDublicateItems(arr)) 
  arr = arr.sort(() => (Math.random() > .5) ? 1 : -1);

console.log(arr);
.as-console-wrapper{min-height: 100%!important; top: 0}
A1exandr Belan
  • 4,442
  • 3
  • 26
  • 48
  • Not bad for small arrays with few duplicates, but my use case will have up to 3 duplicates and 60 total items. I'll try this for now and see how it works. Thanks for the quick response! – Brandon Bohach Feb 25 '22 at 06:14
  • @BrandonBohach, So did you try this code in prod? What performance you get? Can you provide the worst input data for tests? – A1exandr Belan Feb 26 '22 at 08:37
  • Seems to be working pretty nicely, no performance issues that I've noticed. Thanks a lot!! – Brandon Bohach Feb 26 '22 at 21:41
  • 2 things: `() => Math.random() - .5` is sufficient, you don't need the ternary expression. But this "shuffle" doesn't create great results. You should use a better shuffle-function https://stackoverflow.com/a/2450976/6567275 – Thomas Feb 28 '22 at 05:15