Обмен праздничными подарками

11

Еще одна проблема, связанная с нашим внутренним игрой в гольф ... на этот раз во время каникул в прошлом году.

ПРОБЛЕМА

Энди, Барб, Карл, Диди, Эрл и Фрэн покупают друг другу подарки. Нарисуйте имена для обмена подарками.

  1. Каждый человек покупает один подарок и получает один подарок.
  2. Никто не покупает их собственный подарок.
  3. Многократный запуск решения должен давать разные результаты (пара даритель-получатель не должна быть предсказуемой или идентичной от прогона к прогону).

ВХОД

Никто.

ВЫХОД

Отформатирован как в этом примере:

Энди покупает для Барб
Барб покупает для Карл
Карл покупает для Диди
Диди покупает для Эрл
Эрл покупает для Фран
Фран покупает для Энди

Стив
источник
Должен ли вывод сортироваться по имени?
Eelvex
@Eelvex Нет, не обязательно.
Стив
1
Это было дублировано вопросом сегодня, и ключевое слово, которое я искал, не включало его, поэтому для будущих поисков: расстройство.
Питер Тейлор

Ответы:

4

J, 57

(,.' buys for ',"1|.)(?~6){6 4$'AndyBarbCarlDidiEarlFran'

например

   (,.' buys for ',"1|.)(?~6){6 4$'AndyBarbCarlDidiEarlFran'
Carl buys for Earl
Andy buys for Barb
Fran buys for Didi
Didi buys for Fran
Barb buys for Andy
Earl buys for Carl
Eelvex
источник
Я не знаю [J], но сработает ли это, если бы имена имели разную длину?
zx8754
Нет. Код использует тот факт, что все имена имеют длину 4 символа. Это будет работать для разных длин с очень небольшим количеством изменений.
августа
Это также использует, что есть четное количество людей. Обратите внимание, что если X дает Y, Y всегда будет давать X тоже.
Адам
3

с99 - 252 символа

#include <stdio.h>
#define G for(i=0;i<6;i++)
char*n="Andy\0Barb\0Carl\0Didi\0Earl\0Fran",*p[7];int i,j;int main()
{FILE*r=fopen("/dev/random","r");G p[i]=n+5*i;G{j=fgetc(r)%6;p[7]=p[j]
;p[j]=p[i];p[i]=p[7];}G printf("%s buys for %s\n",p[i],p[(i+1)%6]);}

Незначительное улучшение благодаря использованию циклического характера перестановки. Эта версия всегда строит стратегию покупки в форме петли, поэтому она менее случайна, чем предыдущая (271 символьная) версия, но я считаю, что она все еще соответствует спецификации.

Требуется платформа, которая работает /dev/random. Я должен быть в состоянии отбросить около 8, пропуская \0s в большой строке, но мой libc, похоже, не имеет дело со %4sспецификаторами печати, как написано на странице руководства.

Перестановка плохая, но при таком подходе мне не нужно проверять условия «Foo покупает для Foo» .

Удобочитаемый:

#include <stdio.h>

char *n="Andy\0Barb\0Carl\0Didi\0Earl\0Fran",
  *p[7]; /* 7th cell for temp */
int i,j;

int main(){
  FILE*r=fopen("/dev/random","r");
  for(i=0;i<6;i++)
    p[i]=n+5*i;   /* Initialize the pointers */
  for(i=0;i<6;i++){
    j=fgetc(r)%6; /* Poor numeric properties. Cest le Code Golf */
    p[7]=p[j];
    p[j]=p[i];
    p[i]=p[7];
  }
  for(i=0;i<6;i++)
    printf("%s buys for %s\n",p[i],p[(i+1)%6]);
}
dmckee --- котенок экс-модератора
источник
3

Windows PowerShell, 83

$i=random 5
($n=-split'Andy Barb Carl Didi Earl Fran')|%{"$_ buys for "+$n[++$i%6]}

История:

  • 2011-02-11 22:01 (136) - Первая попытка.
  • 2011-02-11 22:05 (130) - Подчеркнул несколько вещей. Теперь тасуем имена, а не индексы.
  • 2011-02-13 16:13 (128) - Мне не нужен модуль, так как $iбудет воссоздан каждый раз.
  • 2011-02-13 16:20    (87) - заимствовал идею у анона. «S C # решение . Просто сгенерируйте случайное смещение, а затем просто дайте им подарок в кругах.
  • 2011-02-13 16:26    (83) - Изменены генерация и индексация случайных чисел. Вытащил $_в строку, чтобы сохранить +.
детеныш
источник
3

Хаскелл, 241 189 знаков

import Data.List
import Random
main=randomRIO(0,719)>>=mapM_ putStrLn.f
f n=map(\(x,y)->x++" buys for "++y).zip(l n).tail$cycle$l n
l=(permutations(words"Andy Barb Carl Didi Earl Fran")!!)

Полностью случайный вывод (который все еще удовлетворяет спецификации).

Это генерирует все перестановки в списке имен, выбирает одно случайным образом (я думаю, что это самый короткий способ в Хаскелле перетасовать список - если у кого-то есть что-то меньшее, я был бы признателен), а затем каждый человек затем покупает подарок для следующего человека в списке.

Anon.
источник
Я попробовал этот ad-hoc, я не уверен, работает ли он: paste.ubuntuusers.de/399798
FUZxxl
@Anon: permutations$words"Andy Barb Carl Didi Earl Fran"и некоторые другие уловки, которые я попробовал в своей улучшенной версии. Я забыл, что permutationsэто не входит в 98 List, поэтому вы должны использовать длинное имя. Посмотри на это.
FUZxxl
А для специальных целей: r=tail.cycle. и чем это встроить.
FUZxxl
Получил до 202 символов. Посмотрите: paste.ubuntuusers.de/399799
FUZxxl
1
А для 189 символов замените третью строку в моем примере на:main=randomRIO(0,719)>>=mapM_ putStrLn.f
FUZxxl
3

Golfscript: 72 64 57 символов

"AndyBarbCarlDidiEarlFran"4/{;9rand}${.n+\' buys for '}%(

тесты

$ golfscript codegolf-838.gs 
Fran buys for Carl
Carl buys for Andy
Andy buys for Barb
Barb buys for Didi
Didi buys for Earl
Earl buys for Fran

$ golfscript codegolf-838.gs 
Didi buys for Earl
Earl buys for Andy
Andy buys for Barb
Barb buys for Carl
Carl buys for Fran
Fran buys for Didi
  • Спасибо gnibbler за "AndyBarbCarlDidiEarlFran"4/, обновил и получил 7 символов меньше
  • Решение 57 символов в основном по Nabb: D, а также заметил, что ;9randэто более случайный, чем мой6rand*
ВЫ
источник
1
"AndyBarbCarlDidiEarlFran"4/
gnibbler
ах, спасибо @gnibbler, круто, собираюсь обновить его.
ВЫ
Не уверен, почему вы используете 6rand*- 0=randили, возможно ;9rand, предпочтительнее. Ибо петля {.n+\' buys for '}%(короче ..
Набб
хе; теперь с J у меня стало одинаковое число символов: D и спасибо @Nabb, я использовал, 6rand*потому что думал, что он одинаково рандомизирует массив из 6 элементов (я думаю, что я ошибался, поскольку ;9randвыглядит действительно случайным, чем мой)
ВЫ
3

Japt -R, 41 байт

`AÌ)B¼C¤E¤FÎÂDi¹`qe ö¬ê1 ò mq` ¿ys f 

-2 байта благодаря @Oliver!

Попробуй!

Это подход, который я выбрал на высоком уровне:

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

У меня есть небольшая история с этой проблемой, так как я создал программу «секретный Санта» для моей работы много лет назад. В итоге мы попросили нескольких соискателей проработать это :)

Dana
источник
@ Оливер - спасибо за советы! Похоже, что ãне возвращает пару, которая связывает первый с последним элементом. Я работаю над тем, чтобы заставить это работать, но подумал, что дам вам знать. Спасибо еще раз, хотя! ethproductions.github.io/japt/...
Dana
43 ?
Dana
1
Ах, ты прав. Я думаю, что это будет работать для 42
Оливер
1
41 байт
Оливер
Подождите , что делает "q"в .ö("q")сделай
ASCII-только
2

Питон - 118 символов

from random import*;L="Andy Barb Carl Didi Earl Fran".split()
for i in sample(range(6),6):print L[i-1],"buys for",L[i]

Питон - 120 символов

import random as R;L="Andy Barb Carl Didi Earl Fran".split();R.shuffle(L)
for i in range(6):print L[i-1],"buys for",L[i]
gnibbler
источник
2

R - 85 символов

paste(n<-sample(c('Andy','Barb','Carl','Didi','Earl','Fran')),'buys for',n[c(6,1:5)])
candles_and_oranges
источник
1

Питон - 154 символа

import random as R;L="Andy Barb Carl Didi Earl Fran".split();M=L[:]
while any(map(str.__eq__,L,M)):R.shuffle(M) 
for i in zip(L,M):print"%s buys for %s"%i
gnibbler
источник
Извините, мой Python сильно отсутствует ... Цикл while в основном цикличен, пока не найдет решение, которое избегает "X покупок для X"?
Стив
@ Стив: Это в значительной степени то, что он делает. mapвызывает str.__eq__каждую пару соответствующих значений в L и M, и цикл продолжается до тех пор, пока ни одно из них не станет истинным.
Анон.
@ Стив, да. хотя, вероятно, короче смещать записи случайным образом с 1 на 5, я думаю, что это не в духе вопроса
gnibbler
Когда я впервые задал вопрос на работе, вы совершенно правы. Мои коллеги быстро отметили, что это не исключено моими определениями ... поэтому я оставил это как есть при публикации здесь.
Стив
1

D: 233 персонажа

import std.random,std.stdio;void main(){auto p=["Andy","Barb","Carl","Didi","Earl","Fran"];auto q=p.dup;o:while(1){for(int i;i<6;++i)if(p[i]==q[i]){randomShuffle(q);continue o;}break;}foreach(i,a;p)writefln("%s buys for %s",a,q[i]);}

Более разборчиво:

import std.random, std.stdio;

void main()
{
    auto p = ["Andy", "Barb", "Carl", "Didi", "Earl", "Fran"];
    auto q = p.dup;

    o:while(1)
    {
        for(int i; i < 6; ++i)
            if(p[i] == q[i])
            {
                randomShuffle(q);
                continue o;
            }

        break;
    }

    foreach(i, a; p)
        writefln("%s buys for %s", a, q[i]);
}
Джонатан М Дэвис
источник
1

Питон (175)

import random as r
n=['Andy','Barb','Carl','Didi','Earl','Fran']
m=n[:]
r.shuffle(m)
b=' buys for '
for i in n:
 h=m.pop()
 while h==i:
  m.append(h)
  h=m.pop()
 print(i+b+h)
Джон
источник
1

Схема, 173

Дает одно из двух решений.

(define(m lst)
    (printf"~v buys for ~v~n"(car lst)(cadr lst))
    (if(eq?(cadr lst)'Andy)0(m(cdr lst)))
)
(m((if(odd?(random 2))reverse values)'(Andy Barb Carl Didi Earl Fran Andy)))

источник
1

C #, 210 183 символов

using System;class a{static void Main(){var n="Andy Barb Carl Didi Earl Fran".Split();var c=0,i=new Random().Next(1,6);for(;c<6;c++)Console.WriteLine(n[c]+" buys for "+n[(c+i)%6]);}}

Кучи по шаблону :(

Это решение не является абсолютно случайным - всегда есть один или несколько «циклов» людей, например, A-> C-> E-> A, и смещения всегда одинаковы в циклах. Однако невозможно предсказать вывод конкретного прогона, если у вас нет части этого вывода.

Anon.
источник
Это интерпретация, которую я намеревался (и в основном решение, которое мы нашли).
Стив
Должно быть 210. Считаете ли вы новую строку в конце файла?
Гнибблер
@gnibbler: я, вероятно, был. Я только что загрузил файл в wc, я не собираюсь считать это вручную.
Анон.
1
Как насчет var n="Andy Barb Carl Didi Earl Fran".Split()? Сохраняет 16 байтов. Вы можете опустить аргумент Main(), который сохраняет еще 9 байтов. И вы можете объединить объявление cи i: int c,i=...;for(c=0;...что сохраняет еще два.
Джои
@Joey: подправил согласно вашим предложениям, спасибо.
Анон.
0

Рубин - 89 символов

(a=%w(Andy Barb Carl Didi Earl Fran).shuffle).zip(a.reverse).each{|e|puts e*' buys for '}

Выход:

Andy buys for Didi
Barb buys for Earl
Fran buys for Carl
Carl buys for Fran
Earl buys for Barb
Didi buys for Andy
steenslag
источник
1
Вы можете использовать mapвместо each.
Догберт
1
проблема с этим решением состоит в том, что, если у вас есть нечетное количество людей, средний человек подарит себе покупки Эрла для покупок Марка Фрэна для покупок Энди Барба для покупок Карла Диди для покупок Диди Карл для покупок Барби Энди для покупок Фрэнка Марда для Эрла
StudleyJr
0

MathGolf , 41 байт

"δ%è╘+µ√♂JÇ"2/$╦╕ää▐δáw_╪" buys for "+m+n

Попробуйте онлайн!

объяснение

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

"δ%è╘+µ√♂JÇ"                                push the string "δ%è╘+µ√♂JÇ"
            2/                              split into segments of two characters
              $                             transform to ordinals using base 256
               ╦                            fetch dictionary words (['Andy', 'barb', 'Carl', 'Earl', 'Fran'])
                ╕ää                         Push "didi"
                   ▐                        append to end of list
                    δ                       capitalize all strings in list
                     áw                     sort by random character in each string (shuffle)
                       _                    duplicate TOS
                        ╪                   right-rotate bits in int, list, str
                         " buys for "       push the string " buys for "
                                     +      Add to all strings in list
                                      m+    zip add the two arrays
                                        n   join array with newline
maxb
источник