алгоритм Тайного Санты (SSA - Secret Santa Algorithm)

423
20 декабря 2016, 23:50

Готовлю новогоднюю вечеринку с друзьями, решили сыграть в тайного санту. Но до нового года не встречаемся, поэтому жеребьевка удаленно. Захотелось поиграться с кодом, вышел вот такой:

Secret Santa Algorithm

Цель - рандомно раскидать кто кому дарит подарок, так, чтобы не вышло ситуации, что человек дарит самому себе)

Смущает наличие костыля

if (j + 1 == guests.get(j))

Как думаете, что можно улучшить? Ожидается лаконичный, простой, не зависающий на большом количестве участников, выполняющий свою задачу алгоритм.

import java.util.*; 
class Rextester {
    public static void main(String args[]) {
        int GUESTS_NUMBER = 10;
        List<Integer> guests = new ArrayList<>();
        for (int i = 0; i < GUESTS_NUMBER;) {
            guests.add(++i);
        }
        boolean shuffled = false;
        outer:
        while (!shuffled) {
            Collections.shuffle(guests);
            shuffled = true;
            for (int j = 0; j < guests.size(); j++) {
                if (j + 1 == guests.get(j)) {
                    shuffled = false;
                    continue outer;
                }
            }
        }
        for (int j = 0; j < guests.size(); j++)
            System.out.println(j + 1 + " gives a gift to -> " + guests.get(j));
    }
}
Answer 1

А почему бы не сделать так?

  1. Перенумеровать участников, пусть их n.
  2. Сгенерировать коллекцию { 1, 2, ..., n } и перетасовать её (Collections.shuffle)
  3. Участник в первым номером в полученной коллекции делает подарок второму участнику в коллекции, второй — третьему, третий — четвёртому, ..., последний — первому.

Алгоритм генерирует просто цикл длины n. Особенность — никогда не будут сгенерированы несколько коротких циклов, всегда только один длинный.

Answer 2

В Вашем алгоритме можно в цикле сделать проверку, если дарим самому себе, меняемся со следующим в очереди, если последний то с первым. Вот мой вариант:

public class Test {
    public static void main(String args[]) {
        int SANTA_NUMBERS = 10;
        List<Integer> santaList = new ArrayList<>();
        for (int i = 0; i < SANTA_NUMBERS; ) {
            santaList.add(++i);
        }
        List<Integer> guests = new ArrayList<>(santaList);
        Collections.shuffle(guests);
        //в этом цикле проверяем
        for (int i = 0; i < santaList.size(); i++) {
            if (santaList.get(i) == guests.get(i)) {
                if (i + 1 < santaList.size()){
                    Integer receiver = guests.get(i + 1);
                    guests.set(i + 1, guests.get(i));
                    guests.set(i , receiver);
                }else {
                    Integer receiver = guests.get(1);
                    guests.set(1, guests.get(i));
                    guests.set(i , receiver);
                }
            }
        }
        for (int j = 0; j < santaList.size(); j++)
            System.out.println(santaList.get(j) + " gives a gift to -> " + guests.get(j));
    }
}
READ ALSO
Сколько весит объект в java?

Сколько весит объект в java?

Есть в проекте одна проблема, которая решается двумя способамиНо я не могу оценить какой способ будет "дешевле" для памяти

369
Java и Jsoup помогите

Java и Jsoup помогите

Вот мой код

368
Вывод всех значений HashMap

Вывод всех значений HashMap

Добрый деньПрограмма должна выдавать ключ и несколько значений по этому ключу, но значения выводятся в виде кода: [{Person@1b6d3586=[Phone@4554617c, Phone@74a14482]}]...

339
Обработка исключений Java

Обработка исключений Java

Доброго времени сутокРешал учебную задачу

414