Перемішайте колоду без локальних змінних [закрито]


14

Завдання цієї головоломки - взяти колоду з 52 карт і перемістити її так, щоб кожна картка опинилася у випадковому положенні.

Подано:

  • Масив deckіз 52 різних цілих чисел, що представляють карти. Коли ви почнете, deckмістить точно одну з кожної картки в якомусь невідомому порядку.
  • Функція, int rand(min, max)яка повертає випадкове ціле число між ints minта maxinclusive. Можна припустити, що ця функція справді випадкова.
  • Функція, void swap(x, y)яка розміщує дві карти в колоді. Якщо ви зателефонуєте swap(x, y), картки на місцях xі yпереключать місця.

Коли:

  • Програма дзвінки shuffle()(або shuffle(deck)або, deck.shuffle()однак, ваша реалізація любить працювати),

Потім:

  • deck повинна містити рівно одну з кожної картки в абсолютно випадковому порядку.

Улов:

Ви не можете оголосити будь-які змінні. Телефонуйте swapі randскільки завгодно, але ви не можете оголосити будь-які власні змінні. Сюди входять forлічильники циклів - навіть неявні, як у foreach.

Роз'яснення:

  • Ви можете змінити незначні деталі відповідно до обраної вами мови. Наприклад, ви можете написати swapдля переключення двох цілих чисел за посиланням. Необхідно змінити, щоб зробити цю роботу своєю мовою, а не зробити головоломку легшою.
  • deck може бути глобальною змінною, або ви можете прийняти її як параметр.
  • Ви можете робити все, що завгодно, до вмісту deck, але ви не можете змінити його довжину.
  • Ваші картки можуть бути пронумеровані 0-51, 1-52, або що завгодно.
  • Ви можете писати це будь-якою мовою, але ніяких підманів за допомогою вбудованої shuffleфункції вашої мови .
  • Так, ви могли написати той самий рядок 52 рази. Ніхто не буде вражений.
  • Час виконання не має значення, але справжня випадковість має значення.
  • Це насправді не гольф коду, але сміливо мінімізуйте / притуплюйте код.

Редагувати: код та візуалізатор

Якщо ви використовували .NET або JavaScript, ось вам може бути корисний тестовий код:

JavaScript:

C #:

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

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

Вихід візуалізатора

Дефектна версія частково переміщує колоду, тому може виглядати чудово, якщо ви вивчили масив вручну. Візуалізатор полегшує помітити візерунок.


Багато мов моделюють масиви настільки ефективно нескінченними, що дозволяє використовувати $ deck [52] і далі замість локальних змінних. Можливо, це теж слід заборонити.
Тімві

2
Чи вважаються функції змінними? чи параметри функції вважаються змінними?
zzzzBov

1
@zzzzBov - Що я мав на увазі, це те, що параметри функції вважатимуться змінними, але я не вказав це перед відповіддю @ mellamokb. Я знаю, що це можна зробити без будь-яких параметрів, окрім deckсамого себе.
Джастін Морган

1
@eBusiness - Це проблема в мені, а не саме питання. І я виступав за те, що відповідач знайшов лазівку.
Джастін Морган

1
@user невідомо - я думаю, я розумію. Відповідь в основному полягає в тому, що ви можете припускати будь-яку реалізацію, яка swapвам подобається, якщо вона виконує її основне призначення. Частина моєї причини зробити swapдане було в тому, щоб люди могли сприймати це як "магію" і сконцентруватися на головній проблемі, не турбуючись про те, щоб вони працювали своєю мовою. Ви можете це зробити або написати своє swap, це залежить від вас.
Джастін Морган

Відповіді:


9

JavaScript

Я вважаю, що це задумана форма рішення, я використовую карту в положенні 0, щоб слідкувати за прогресом, лише перетасовуючи картки, які вже використовувались як лічильник, це досягає стандартних 52! перестановки з ідеальним рівним розподілом. Процедура ускладнюється свопом XOR, не дозволяючи, щоб елемент мінявся самим собою.

Редагувати: я вбудував сортування, яке сортує кожен елемент перед тим, як він буде використаний, таким чином дозволяючи цьому працювати з несортованим масивом. Я також відмовився від рекурсивного виклику на користь циклу.

deck=[]
for(a=0;a<52;a++){
    deck[a]=a
}
function swap(a,b){
    deck[a]=deck[b]^deck[a]
    deck[b]=deck[b]^deck[a]
    deck[a]=deck[b]^deck[a]
}
function rand(a,b){
    return Math.floor(Math.random()*(1+b-a))+a
}
function shuffle(){
    while(deck[0]!=0){ //Sort 0 into element 0
        swap(0,deck[0])
    }
    while(deck[0]<51){ //Run 51 times
        while(deck[deck[0]+1]!=deck[0]+1){ //Sort element deck[0]+1 into position deck[0]+1
            swap(deck[deck[0]+1],deck[0]+1)
        }
        swap(0,deck[0]+1) //Swap element deck[0]+1 into position 0, thus increasing the value of deck[0] by 1
        if(rand(0,deck[0]-1)){ //Swap the element at position deck[0] to a random position in the range 1 to deck[0]
            swap(deck[0],rand(1,deck[0]-1))
        }
    }
    if(rand(0,51)){ //Swap the element at position 0 to a random position
        swap(0,rand(1,51))
    }
}
for(c=0;c<100;c++){
    shuffle()
    document.write(deck+"<br>")
}

Саме це я і мав на увазі. Незабаром я тестую це, і я, мабуть, прийму.
Джастін Морган

Здається, працює добре, хоча при більш детальному огляді це не зовсім так, як у мене. Прийнятий, і я скоро опублікую свою відповідь.
Джастін Морган

Це також відомий як алгоритм перемикання Кнута ( en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle ).
Боб

14

Хаскелл

Ось безпроблемна реалізація. Немає змінних, формальних параметрів або явної рекурсії. Я використовував lambdabot «s@pl (" безглуздий ") рефакторинг функції зовсім небагато.

import Data.List
import Control.Applicative
import Control.Monad
import System.Random

shuffle :: [a] -> IO [a]
shuffle = liftM2 (<$>) ((fst .) . foldl' (uncurry ((. flip splitAt) . (.) .
          (`ap` snd) . (. fst) . flip flip tail . (ap .) . flip flip head .
          ((.) .) . (. (++)) . flip . (((.) . (,)) .) . flip (:))) . (,) [])
          (sequence . map (randomRIO . (,) 0 . subtract 1) . reverse .
          enumFromTo 1 . length)

main = print =<< shuffle [1..52]

Ось моя тестова процедура, щоб переконатися, що номери були рівномірно розподілені:

main = print . foldl' (zipWith (+)) (replicate 52 0)
       =<< replicateM 1000 (shuffle [1..52])

Ось оригінальний алгоритм:

shuffle :: [a] -> IO [a]
shuffle xs = shuffleWith xs <$>
             sequence [randomRIO (0, i - 1) | i <- reverse [1..length xs]]

shuffleWith :: [a] -> [Int] -> [a]
shuffleWith xs ns = fst $ foldl' f ([], xs) ns where
    f (a,b) n = (x:a, xs++ys) where
        (xs, x:ys) = splitAt n b

+1 для Haskell Тепер я повинен вивчити Haskell, щоб я міг прочитати це. : P
Джастін Морган

Як зберігається прогрес?
aaaaaaaaaaaa

8
Я сумніваюся, що хтось із програмістів Haskell скаже, що їх код безглуздий, і пишатись цим.
aaaaaaaaaaaa

4
Це ((.) .) . (. (++))та це (((.) . (,)) .)моє улюблене. Нічого собі лямбдабот. Просто, вау.
Ден Бертон

2
@eBusiness "точка безкоштовно" - це зовсім не те, що "безглуздо".
fredoverflow

6

J

Ігнорування цієї колоди є змінною, є очевидне ...

52 ? 52

Звичайно, якщо ви дійсно хочете функції, є ось це, що буде працювати, навіть якщо ви забудете видалити джокери (або спробуйте перетасувати щось, крім карт).

{~ (# ? #)

Так що ...

shuffle =: {~ (# ? #)
deck =: i. 52
shuffle deck

Це, мабуть, поза наміром питання, що було б реалізувати переміщення з ранду (? ). Я можу це зробити пізніше, коли я не повинен працювати.

Пояснення

Пояснення 52 ? 52:

  • x ? y це x випадкових унікальних предметів від y.

Пояснення {~ (# ? #)складніше через вилки та гачки . В основному, це те саме shuffle =: 3 : '((# y) ? (# y)) { y', що має один неявний аргумент ( y).

  • # y дає довжину y
  • Це дає 52? 52, як і раніше, що є випадковою перестановкою 0..51
  • x { y - це пункт y в індексі x, або (в даному випадку) елементи в індексах в x.
  • Це дозволяє переміщувати перемішати все, що передається, а не лише цілі числа.

Докладніше про оператори див. J Vocabulary , хоча синтаксис і семантика є досить складними через рангове і негласне програмування.


+1: Робота над кодом-гольф, коли, як передбачається, працювати ..
хай

1
Чи можете ви пояснити, що це робить для людей з обмеженими можливостями? Нещодавно я чув, як це описано як вибух на заводі смайликів ( codegolf.stackexchange.com/questions/1294/anagram-code-golf/… ), який звучить прямо.
Джастін Морган

@Justin: Пояснення додано.
Джессі Мілікан

Це працює і в APL. Синтаксис той самий, тому я не буду турбуватись, додаючи нову відповідь ( {52?⍵}це анонімна функція, яка бере 52 аргументовані елементи зі свого аргументу. Тут буде список 52 цілих чисел)
Arc676

4

Пітон

import random
def rand(x, y):
 return random.randrange(x, y+1)

def swap(deck, x, y):
 deck[x] ^= deck[y]
 deck[y] ^= deck[x]
 deck[x] ^= deck[y]

def shuffle(deck):
 if len(deck)>1:
  deck[1:]=shuffle(deck[1:])
  if rand(0,len(deck)-1)>0:swap(deck, 0, rand(1, len(deck)-1))
 return deck

print shuffle(range(52))

Що [1:]означає? Це повторюється в підмасиві deck?
Джастін Морган

Так, [1:] означає підрядний масив від індексу 1 до кінця масиву. Тож він рекурсивно переміщує все, крім першого елемента, призначає (копіює) його назад на те саме місце в оригінальному масиві, а потім випадковим чином десь розміщує перший елемент.
Кіт Рендалл

Дуже розумний. Я думаю, що це одне з найкрасивіших рішень тут, і він правильно використовує алгоритм Фішера-Йейта. +1. Це було приємним способом побачити красу мов, з якими я не знайомий.
Джастін Морган

2
Можливо, вам сподобається a, b = b, aтрюк.
Рей

3

Використання факторадикального подання

У факторадичному поданні перестановки елемент i приймає значення від 0 до Ni. Тож випадкова перестановка є просто rand(0,i)для кожного Ni.

В J:

? |.>:i.52
2 39 20 26 ... 2 0 1 0 0 0

де ? xє rand(0,x-1)і |.>:i.52є52 51 ... 1

Потім, якщо aце значення Ith factoradic, ми робимо обмін: swap(deck[i], deck[i+a]). Список пар, які потрібно поміняти:

(,. i.52) ,. (,. ((?|.>:i.52)+i.52))
0 33
1 20
2  3
...
49 50
50 50
51 51

Своп, який ми будемо використовувати, працює так:

deck
24 51 14 18 ...
deck =: 0 1 swap deck
51 24 14 18 ...

Це насправді не "за посиланням", але в Дж. Немає реальних функцій.

Ми будемо використовувати довжину колоди ( #deck), щоб не використовувати константу.

Повна програма на J:

deck =: 52 ? 52                           NB. Initial random deck
swap =: 4 : 'deck =: (x { y) (|.x) } y'   NB. Given swap "function"
f =: 3 : 0                                NB. function that calls the swap for a pair
({.y) swap deck
}.y
)
f^:(#deck) (,.,.[:,.]+[:?[:|.>:) i.#deck

3

C #

Ось моя власна відповідь, заснована на алгоритмі Фішера-Йейта . Якщо ваш генератор випадкових чисел достатньо хороший, ви повинні мати ідеальне переміщення.

Англійська версія:

  1. Неодноразово міняйте картку на deck[0]таку deck[v], де vзнаходиться номінал картки deck[0]. Повторюйте до тих пір, покиv == 0 . Це частково сортуватиме колоду, але це не має значення. Тепер ви знаєте, що Картка 0 знаходиться на передній частині колоди, а це означає, що ви можете вкрасти цей простір у масиві та використовувати його як лічильник циклу. Це ключовий "обман" для проблеми локальних змінних.
  2. Починаючи з позиції 1 (друга карта в колоді), поміняйте її на iту, яка знаходиться на rand(i, 51). Зауважте, що вам потрібно rand(i, 51), НЕ rand(1, 51) . Це не забезпечить рандомізацію кожної картки.
  3. Встановити deck[0]на 0. Тепер вся колода перемішується для першої карти , за винятком, так свопу deck[0]з , deck[rand(0, 51)]і ви зробили.

C # версія:

public static void shuffle(int[] deck)
{
    while (deck[0] > 0)
        swap(ref deck[0], ref deck[deck[0]]);

    for (deck[0] = 1; deck[0] < 52; deck[0]++)
        swap(ref deck[deck[0]], ref deck[rand(deck[0], 51)]);

    deck[0] = 0;
    swap(ref deck[0], ref deck[rand(0, 51)]);
}

Версія Javascript:

while (deck[0] > 0)
    swap(0, deck[0]);

for (deck[0] = 1; deck[0] < 52; deck[0]++)
    swap(deck[0], rand(deck[0], 52));

deck[0] = 0;
swap(0, rand(0, 52));

... де відбувається swap(a, b)обмін deck[a]на deck[b].


2

Рубін, одна лінія

Це вважається обманом? Це має бути настільки випадковим, як це виходить.

deck=(0..51).to_a # fill the deck
deck[0..51] = (0..51).map{deck.delete_at(rand deck.length)}

( randМетод Рубі бере лише один аргумент, а потім генерує число n таким, що 0 <= число <аргумент.)

Додатково - подібний до рішення Perg Sogart, але наскільки я знаю, це не страждає від цієї проблеми:

deck = deck.sort_by{rand}

Rub_'s sort_by відрізняється від сортування - він спочатку генерує список значень для сортування масиву і лише після цього сортує їх. Це швидше, коли дорого дізнатись властивість, за якою ми сортуємо, дещо повільніше у всіх інших випадках. Це також корисно в коді гольфу: P


Я б не називав це обманом, сам по собі, але deck[0..51]чи є спідницею правило "без змінних", використовуючи особливості мови. Це справедливо, я просто думаю, що це втрачає частину виклику. :) Я не знаю Рубі; чи можете ви пояснити (0..51).map{deck.delete_at(rand deck.length)}частину? Це видаляє картки з deck?
Джастін Морган

@JustinMorgan так, 52 рази видаляє випадкову карту deckі додає її до внутрішнього списку mapнакопичуваних результатів. Тоді , коли не залишилося нічого в deckв mapрезультаті отримує копіюється deck. В основному є тимчасова, але це мовна функція, а не явна змінна :)
hobbs

deck.sort_by!{rand}коротше.
Ерік Дюмініл

1

JavaScript

ПРИМІТКА. Це рішення технічно не є правильним, оскільки воно використовує другий параметр iу виклику до shuffle, який вважається зовнішньою змінною.

function shuffle(deck, i) {
    if (i <= 0)
        return;
    else {
        swap(deck[rand(0,i-1)], deck[i-1]);
        shuffle(deck, i - 1);
    }
}

Подзвоніть з shuffle(deck,52)

Повний робочий приклад (довелося swapтрохи змінити, оскільки в JavaScript немає прохідних посилань):

function rand(min, max) { return Math.floor(Math.random()*(max-min+1)+min); }
function swap(deck, i, j) {
    var t=deck[i];
    deck[i] = deck[j];
    deck[j] = t;
}

function shuffle(deck, i) {
    if (i <= 0)
        return;
    else {
        swap(deck, rand(0,i-1), i-1);
        shuffle(deck, i - 1);
    }
}

// create deck
var deck=[];
for(i=0;i<52;i++)deck[i]=i;
document.writeln(deck);
shuffle(deck,52);
document.writeln(deck);

Молодці. Що я мав на увазі, розглядав параметри shuffleяк змінних, але я не вказав це так +1. Гарне використання рекурсії теж.
Джастін Морган

-1, не генерує всіх перестановок, це очевидно, тому що елемент 51 ніколи не займе свого початкового місця, і тому, що ви викликаєте лише rand, достатній для генерування 51! перестановки з можливих 52!
aaaaaaaaaaaa

2
@eBusiness: В оригінальній специфікації колоду довільно упорядковується, не обов'язково в порядку 1-52. Я просто використовував це, тому що це було найпростіше.
mellamokb

1
@eBusiness: я змінив, щоб дозволити можливість залишити елемент на тому ж місці, використовуючи deck[rand(0,i-1)]замість deck[rand(0,i-2)]. Також поміняйте місцями, i=0а не зупиняючись на i=1. Чи допомагає це?
mellamokb

Так, це слід зробити, за винятком того, що ви порушили специфікацію XOR своп.
aaaaaaaaaaaa

1

C ++

#include <cstdlib>
#include <ctime>
#include <iostream>

int deck[52];

void swap(int a, int b) {
    deck[a] ^= deck[b];
    deck[b] ^= deck[a];
    deck[a] ^= deck[b];
}

int r(int a, int b) {
    return a + (rand() % (b - a + 1));
}

void s(int *deck) {
    swap(1, r(2, 51));
    deck[0] *= 100;

    for(deck[0] += 2; (deck[0] % 100) < 51; deck[0]++) {
        swap(deck[0] % 100,
          r(0, 1) ? r(1, (deck[0] % 100) - 1) : r((deck[0] % 100) + 1, 51));
    }
    swap(51, r(1, 50)); 

    deck[0] = (deck[0] - 51) / 100;
    swap(r(1, 51), 0);
}

int main(int a, char** c)
{
    srand(time(0));

    for (int i = 0; i < 52; i++)
        deck[i] = i;

    s(deck);
    s(deck);

    for (int i = 0; i < 52; i++)
        std::cout << deck[i] << " ";
}

Уникає обміну елементами з собою, тому доводиться двічі викликати випадковість.


swap(deck[rand(1, 51)], (deck[0] - 51) / 100);Як swapдізнатись, куди поставити друге значення? Ви також пропали ).
Джастін Морган

На жаль, спасибі Я почав переміщувати цю частину під час перегляду і, мабуть, відволікся перед тим, як закінчити її: P
Метью

Downvote був не від мене, BTW. Я тестую, коли зможу.
Джастін Морган

ДОБРЕ. Я полегшив тестування, надавши повну програму.
Матвій

1
Дуже розумний. Моє власне рішення використовувалося deck[0], але не так, як у вас є.
Джастін Морган


1

Ще одне рішення Perl, яке фактично дає рівномірно розподілений вихід:

sub shuffle_integers {
    map int, sort {$a-int $a <=> $b-int $b} map $_+rand, @_;
}

say join " ", shuffle_integers 1 .. 52;

У цьому рішенні використовується Perl rand, який повертає випадкове число x у діапазоні 0 ≤ x <1. Він додає таке випадкове число до кожного цілого числа на вході, сортує числа відповідно до їх дробових частин і, нарешті, знову відбирає ці дробові частини .

(Я вважаю , що використання спеціальних змінних $_, $aі $bпадає в дусі виклик, так як ті , як Perl проходить вхід в mapі sort, і вони не використовуються для інших цілей , в коді. У будь-якому випадку, я вважаю , вони насправді псевдоніми до вхідних значень, а не незалежних копій. Однак, це насправді не є заміщенням на місці; і те mapй інше і sortстворюють копії вхідних даних у стеку.)


1

Java

Я здивований, що очевидного ніхто не заявив: (Я припускаю, що swap (x, x) нічого не робить.

    static void shuffle(){
        swap(1,rand(0,1));
        swap(2,rand(0,2));
        swap(3,rand(0,3));
        swap(4,rand(0,4));
        swap(5,rand(0,5));
        swap(6,rand(0,6));
        swap(7,rand(0,7));
        swap(8,rand(0,8));
        swap(9,rand(0,9));
        swap(10,rand(0,10));
        swap(11,rand(0,11));
        swap(12,rand(0,12));
        swap(13,rand(0,13));
        swap(14,rand(0,14));
        swap(15,rand(0,15));
        swap(16,rand(0,16));
        swap(17,rand(0,17));
        swap(18,rand(0,18));
        swap(19,rand(0,19));
        swap(20,rand(0,20));
        swap(21,rand(0,21));
        swap(22,rand(0,22));
        swap(23,rand(0,23));
        swap(24,rand(0,24));
        swap(25,rand(0,25));
        swap(26,rand(0,26));
        swap(27,rand(0,27));
        swap(28,rand(0,28));
        swap(29,rand(0,29));
        swap(30,rand(0,30));
        swap(31,rand(0,31));
        swap(32,rand(0,32));
        swap(33,rand(0,33));
        swap(34,rand(0,34));
        swap(35,rand(0,35));
        swap(36,rand(0,36));
        swap(37,rand(0,37));
        swap(38,rand(0,38));
        swap(39,rand(0,39));
        swap(40,rand(0,40));
        swap(41,rand(0,41));
        swap(42,rand(0,42));
        swap(43,rand(0,43));
        swap(44,rand(0,44));
        swap(45,rand(0,45));
        swap(46,rand(0,46));
        swap(47,rand(0,47));
        swap(48,rand(0,48));
        swap(49,rand(0,49));
        swap(50,rand(0,50));
        swap(51,rand(0,51));
    }

Гаразд, добре, може бути коротше:

package stackexchange;

import java.util.Arrays;

public class ShuffleDry1
{
    static int[] deck = new int[52];

    static void swap(int i, int j){
        if( deck[i]!=deck[j] ){
            deck[i] ^= deck[j];
            deck[j] ^= deck[i];
            deck[i] ^= deck[j];
        }
    }

    static int rand(int min, int max){
        return (int)Math.floor(Math.random()*(max-min+1))+min;
    }

    static void initialize(){
        for( int i=0 ; i<deck.length ; i++ ){
            deck[i] = i;
            swap(i,rand(0,i));
        }
    }

    static void shuffle(){
        while( deck[0]!=0 ) swap(0,deck[0]);
        for( deck[0]=52; deck[0]-->1 ; ) swap(deck[0],rand(deck[0],51));
        swap(0,rand(0,51));
    }

    public static void main(String[] args) {
        initialize();
        System.out.println("init: " + Arrays.toString(deck));
        shuffle();
        System.out.println("rand: " + Arrays.toString(deck));
    }

}

1

Бурлеск

Що ви насправді просите, це випадкова перестановка списку цілих чисел? r@дасть нам усі перестановки, і ми просто виберемо випадкову.

blsq ) {1 2 3}r@sp
1 2 3
2 1 3
3 2 1
2 3 1
3 1 2
1 3 2
blsq ) {1 2 3}r@3!!BS
2 3 1

Оскільки нам потрібна справжня випадковість, щось бурлескне не в змозі зробити, тому що в Бурлеску немає функцій вводу / виводу, вам потрібно буде надати джерело випадковості через STDIN.

Це, мабуть, щось, що я виправлю в пізнішій версії (тобто генерую випадкове насіння під час запуску і натискаю на вторинний стек або щось подібне, але сам інтерпретатор Burlesque не має вводу / виводу).


0

Javascript

Я не впевнений, чи це "обман", але моє рішення використовує нативний локальний масив аргументів функції. Я включив свої власні функції rand() swap()та filldeck(). Цікаво зазначити, що це має працювати з колодою будь-якого розміру.

    var deck = [];

    function shuffle(){
        main(deck.length);
    }

    function main(){
        arguments[0] && swap( arguments[0]-=1, rand(0, deck.length-1) ), main(arguments[0]);
    }

        function rand(min, max){
            return Math.floor( Math.random()*(max-min+1) )+min;
        }

        function swap(x, y){
            var _x = deck[x], _y = deck[y];
            deck[x] = _y, deck[y] = _x;
        }


        function filldeck(dL){
            for(var i=0; i<dL; i++){
                var ran = rand(1,dL);
                while( deck.indexOf(ran) >= 0 ){
                    ran = rand(1,dL);
                }
                deck[i] = ran;
            }
        }

    filldeck(52);
    shuffle();

Думаю, це обман. Однак це дуже розумне обман, так приємна робота.
Джастін Морган

0

Tcl , 32 байти

Зловживання timeфункцією, яка служить для вимірювання того, скільки часу витрачається сценарій, працює, але також може слугувати циклічним механізмом без оголошення будь-яких змінних.

time {lswap $D [rand] [rand]} 52

Спробуйте в Інтернеті!


Чи я правда, що це здійснює лише 52 випадкові заміни? Цього недостатньо для справжнього переміщення. Я пробіг її кілька разів і нарахував в середньому 8 карт, які все ще знаходяться у вихідних положеннях, і ймовірність цього при справжньому перетасуванні становить приблизно 9x10 ^ -6 .
Джастін Морган

@JustinMorgan: Чи можете ви, будь ласка, пояснити мені краще розрахунок ймовірності?
серхіол

-1

perl - це не правильне переміщення, як пояснено в коментарях!

my @deck = (0..51);
@deck = sort {rand() <=> rand()} @deck;
print join("\n",@deck);

Я думаю, що я нічого не використовував як своп тощо. Це було потрібно як частина проблеми?


4
Це спрацювало б, якби сортування за випадковою функцією було способом отримання рівномірного випадкового розподілу. Однак це не так. -1
ааааааааааа

і чому це не так? ви могли б дати мені посилання, щоб прочитати ???
sogart

2
Якість результату сильно різниться залежно від алгоритму сортування, але майже у всіх випадках результат буде дуже далеким від рівномірної випадкової функції розподілу. Ось стаття на цю тему: sroucheray.org/blog/2009/11/…
aaaaaaaaaaaaa

-1

JavaScript 4 рядки

function shuffle() {
  while(deck[0]!=0)swap(deck[0],rand(1,51))
  while(deck[0]++!=104)swap(deck[0]%51+1,rand(1,51))
  deck[0]=0
  swap(0,rand(0,51))
}

Оригінальна відповідь, що була недостатньо випадковою. Своп не гарантував торкання кожного елемента в колоді.

// shuffle without locals
function shuffle() {
  deck.map(function(){swap(deck[rand(0,51)],deck[rand(0,51)])});
}

Не створює справжнього випадкового переміщення. Ось тест на візуалізатор: jsfiddle.net/muk1bthm . Я shuffleтрохи змінив ваш код, щоб він відповідав моїй swapреалізації, але ось це дослівно: jsfiddle.net/m7km4u6g
Джастін Морган

Для уточнення вищезазначений коментар стосується нової версії, яка досі не є випадковою.
Джастін Морган
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.