Святковий обмін подарунків


11

Ще одна проблема нашого внутрішнього гольфу ... ця навколо свят минулого року.

ПРОБЛЕМА

Енді, Барб, Карл, Діді, Граф та Фран купують подарунки один одному. Намалюйте імена для обміну подарунками.

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

ВХОД

Жоден.

ВИХІД

Відформатовано як у цьому прикладі:

Енді купує Барба
Барб купує Карл
Карл купує Діді
Діді купує граф
Граф купує Фран
Френ купує Енді


Чи слід сортувати вихід за назвою?
Енайсекс

@Eelvex Ні, не потрібно.
Стів

1
Сьогодні це питання було дубльовано запитанням, і ключове слово, яке я шукав, не з’явило його, тому для подальших пошуків: derangement.
Пітер Тейлор

Відповіді:


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

Я не знаю [J], але чи спрацювало б це, якби імена мали різну довжину?
zx8754

Ні. Код використовує той факт, що всі імена мають 4 символи. Він буде працювати різної довжини з дуже невеликими змінами.
Енайсекс

Це також експлуатує те, що є парна кількість людей. Зауважте, що якщо X дає Y, Y завжди буде давати і X.
Адам

3

c99 - 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специфікаторами друку, як пише сторінка man.

Переміщення - це погано, але робити це таким чином заважає мені перевіряти умови "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]);
}

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

Haskell, 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")!!)

Повністю випадковий вихід (який все ще задовольняє специфікації).

Це генерує всі перестановки списку імен, вибирає одне навмання (я думаю, що це найкоротший спосіб у Хаскеллі перетасувати список - якщо хтось має щось менше, я б оцінив це), а потім кожна людина купує подарунок для наступної людини у списку.


Я спробував цей час, я не знаю, чи працює: 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

Гольфскрипт: 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
  • Дякуємо гніблеру "AndyBarbCarlDidiEarlFran"4/, оновлено та отримало на 7 символів менше
  • 57 символів рішення, в основному, Nabb: D, і також помітив, що ;9randє більш випадковим, ніж мій6rand*

1
"AndyBarbCarlDidiEarlFran"4/
гніблер

ах, дякую @gnibbler, класно, збираємось оновити його.
ВИ

Не знаєте, чому ви використовуєте 6rand*- 0=randабо, можливо, ;9randє кращим. Для петлі, {.n+\' buys for '}%(коротше ..
Nabb

хе; став таким же символом рахувати з J зараз: D і дякую @Nabb, я використовував, 6rand*тому що я думав, що це однаковою мірою рандомізує 6 елементів масиву (я думаю, я помилявся, оскільки ;9randвиглядає справді випадковим, ніж мій)
ВИ

3

Japt -R, 41 байт

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

-2 байти завдяки @Oliver!

Спробуй це!

Такий підхід я застосував на високому рівні:

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

У мене є невелика історія з цією проблемою, коли я створив програму "таємний Санта" для своєї роботи років тому. Ми в кінцевому підсумку попросили декількох претендентів на роботу, щоб вони також працювали над цим :)


@Oliver - дякую за поради! Схоже, що ãне повертається пара, яка пов'язує перший з останнім елементом. Я працюю над тим, щоб змусити це працювати, але думав, що дам вам знати. Ще раз спасибі! ethproductions.github.io/japt / ...
Dana

43 ?
Dana

1
Ах, ти маєш рацію. Я думаю, що це спрацювало б для 42
Олівер


Зачекайте, що робити "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]


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

Вибачте, моєму Python вкрай не вистачає ... це цикл в той час, як в основному циклічно, поки він не знайде рішення, яке дозволяє уникнути "X купує за X"?
Стів

@Steve: Це майже все, що вона робить. mapвикликає str.__eq__кожну пару відповідних значень у L та M, і цикл продовжує тривати, поки жодне з них не буде істинним.
Анон.

@Steve, так. хоча ймовірно коротше jsut переміщати записи випадковим чином з 1 на 5, я думаю, що це не в дусі питання
gnibbler

Коли я вперше поставив це питання на роботі, ви абсолютно праві. Мої колеги швидко вказали, що це не виключено за моїми визначеннями ... тому я залишив це, як це відбувається, коли розміщую тут.
Стів

1

Д: 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, і компенсації завжди однакові в циклі. Однак передбачити вихід певного циклу неможливо, якщо у вас немає частини цього виводу.


Ось така інтерпретація, яку я мав намір (і в основному це рішення, на яке ми приземлилися).
Стів

Має бути 210. Ви рахуєте новий рядок в кінці файлу?
гніблер

@gnibbler: Я, мабуть, був. Я тільки що ввів файл у туалет, я не збираюся рахувати це вручну.
Анон.

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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.