स्थानीय चरों के बिना एक डेक को हिलाएँ [बंद]


14

इस पहेली का उद्देश्य 52 कार्ड का डेक लेना है और इसे फेरबदल करना है ताकि प्रत्येक कार्ड यादृच्छिक स्थिति में हो।

दिया हुआ:

  • deck52 अलग-अलग पूर्णांकों का एक सरणी, कार्डों का प्रतिनिधित्व करता है। जब आप शुरू करते हैं, तो deckकुछ अज्ञात क्रम में प्रत्येक कार्ड में से एक होता है।
  • एक फ़ंक्शन, int rand(min, max)जो कि ints minऔर maxसमावेशी के बीच एक यादृच्छिक पूर्णांक देता है । आप मान सकते हैं कि यह फ़ंक्शन वास्तव में यादृच्छिक है।
  • एक फ़ंक्शन, 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 का उपयोग किया है, तो यहां कुछ परीक्षण कोड उपयोगी हो सकते हैं:

जावास्क्रिप्ट:

  • क्विक-एंड-डर्टी जावास्क्रिप्ट विज़ुअलाइज़र, कॉफ़ीस्क्रिप्ट स्रोत के साथ: https://gist.github.com/JustinMorgan/3989752bdfd579291cca
  • चलने योग्य संस्करण (बस अपने shuffle()फ़ंक्शन में पेस्ट करें ): http://jsfiddle.net/4zxjmy42/

सी#:

यह कोड सॉर्ट करता है और डेक को कई हजार बार फेरबदल करता है और कुछ बुनियादी पवित्रता परीक्षण करता है: प्रत्येक फेरबदल के लिए, यह पुष्टि करता है कि डेक में बिना किसी दोहराव के ठीक 52 कार्ड हैं। तब विज़ुअलाइज़र प्रत्येक कार्ड की आवृत्ति को डेक के प्रत्येक स्थान पर समाप्त करता है, जो एक ग्रेस्केल हीट मैप प्रदर्शित करता है।

विज़ुअलाइज़र का उत्पादन बिना किसी स्पष्ट पैटर्न के बर्फ जैसा दिखना चाहिए। जाहिर है यह सच यादृच्छिकता साबित नहीं कर सकता है, लेकिन यह स्पॉट-चेक करने का एक त्वरित और आसान तरीका है। मैं इसे या इसके जैसे कुछ का उपयोग करने की सलाह देता हूं, क्योंकि फेरबदल एल्गोरिथ्म में कुछ गलतियां आउटपुट में बहुत पहचानने योग्य पैटर्न का कारण बनती हैं। यहां दो कार्यान्वयन से आउटपुट का एक उदाहरण है, एक सामान्य दोष के साथ:

विजुअलाइज़र आउटपुट

त्रुटिपूर्ण संस्करण आंशिक रूप से डेक को फेरबदल करता है, इसलिए यदि आप हाथ से सरणी की जांच करते हैं तो यह ठीक लग सकता है। विज़ुअलाइज़र एक पैटर्न को नोटिस करना आसान बनाता है।


कई भाषाओं के मॉडल प्रभावी रूप से अनंत हैं, इस प्रकार $ डेक [52] और इसके बाद स्थानीय चर के स्थान पर उपयोग करने की अनुमति देता है। शायद इस पर भी रोक लगनी चाहिए।
तिमवी

2
क्या कार्यों को चर माना जाता है? फ़ंक्शन पैरामीटर को चर माना जाता है?
zzzzBov

1
@zzzzBov - मेरे मन में क्या था कि फंक्शन पैरामीटर्स को वैरिएबल माना जाएगा, लेकिन मैंने @ mellamokb के उत्तर से पहले यह निर्दिष्ट नहीं किया था। मुझे पता है कि यह deckअपने अलावा किसी भी पैरामीटर के बिना किया जा सकता है ।
जस्टिन मॉर्गन

1
@eBusiness - यह मेरे साथ एक समस्या है, सवाल ही नहीं। और मैं उत्थान कर रहा था क्योंकि उत्तर देने वाले को एक खामी मिली।
जस्टिन मोरगन

1
@user अज्ञात - मुझे लगता है कि मैं समझता हूं। इसका उत्तर मूल रूप से यह है कि जब तक आप swapअपने मूल उद्देश्य को पूरा करते हैं, तब तक आप जो चाहें लागू कर सकते हैं । मेरे swapदिए जाने का एक कारण यह था कि लोग इसे 'जादू' मान सकते थे और मुख्य समस्या पर ध्यान केंद्रित किए बिना अपनी पसंद की भाषा में काम करने की चिंता कर सकते थे। आप या तो ऐसा कर सकते हैं या अपना लिख ​​सकते हैं swap, यह आपके ऊपर है।
जस्टिन मॉर्गन

जवाबों:


9

जावास्क्रिप्ट

मेरा मानना ​​है कि यह समाधान का इच्छित रूप है, मैं प्रगति का ट्रैक रखने के लिए स्थिति 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

हास्केल

यहाँ एक बिंदु मुक्त कार्यान्वयन है। कोई चर, औपचारिक पैरामीटर या स्पष्ट पुनरावृत्ति नहीं। मैंने लैम्बडाबोट का उपयोग किया @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। अब मुझे हास्केल सीखना है तो मैं इसे पढ़ सकता हूं। : पी
जस्टिन मॉर्गन

प्रगति कैसे संग्रहीत है?
आआआआआआआआआआआ आआआआआ

8
मुझे किसी पर संदेह है लेकिन हास्केल प्रोग्रामर कहेंगे कि उनका कोड व्यर्थ है और इस पर गर्व करें।
आआआआआआआआआआ आआआआआ

4
यह ((.) .) . (. (++))और यह (((.) . (,)) .)मेरा पसंदीदा है। वाह लाम्बडबोट। बस वाह।
दान बर्टन

2
@eBusiness "बिंदु मुक्त" "व्यर्थ" के समान नहीं है।
fredoverflow

6

जे

इस बात को अनदेखा करना कि डेक एक परिवर्तनशील है, स्पष्ट है ...

52 ? 52

बेशक, यदि आप वास्तव में एक फ़ंक्शन चाहते हैं, तो यह वहाँ है, जो काम करेगा भले ही आप जोकर को दूर करना भूल जाएं (या कार्ड के अलावा कुछ और फेरबदल करने की कोशिश करें)।

{~ (# ? #)

इसलिए कि...

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

यह शायद सवाल के इरादे से बाहर है, जो रैंड ( ?) से खुद को फेरबदल करना होगा । मैं ऐसा बाद में कर सकता हूं जब मैं काम करने वाला नहीं हूं।

व्याख्या

का स्पष्टीकरण 52 ? 52:

  • x ? y y से x यादृच्छिक अद्वितीय आइटम है।

कांटे और कांटों के{~ (# ? #) कारण स्पष्टीकरण कठिन है । मूल रूप से, यह वही है , जिसमें एक निहित तर्क ( ) है।shuffle =: 3 : '((# y) ? (# y)) { y'y

  • # y y की लंबाई देता है
  • यह 52 देता है? पहले की तरह 52, जो 0..51 का यादृच्छिक क्रमांकन है
  • x { y सूचकांक x में y का आइटम है, या (इस मामले में) x में अनुक्रमित में आइटम है।
  • यह आपको केवल पूर्णांकों में नहीं, बल्कि जो कुछ भी है, उसमें फेरबदल करने देता है।

ऑपरेटरों के विवरण के लिए जे शब्दावली देखें , हालांकि रैंक और टैसिट प्रोग्रामिंग के कारण वाक्यविन्यास और शब्दार्थ काफी कठिन हैं।


+1: जब काम करने वाला हो तो कोड-गोल्फ पर काम करना .. lol I am too: P
mellamokb

1
क्या आप बता सकते हैं कि जे-बिगड़ा हुआ व्यक्ति क्या करता है? मैंने हाल ही में इसे एक इमोटिकॉन फैक्ट्री ( codegolf.stackexchange.com/questions/1294/anagram-code-golf/… ) में विस्फोट के रूप में सुना , जो सही लगता है।
जस्टिन मॉर्गन

@ जस्टिन: स्पष्टीकरण जोड़ा गया।
जेसी मिलिकन

यह एपीएल में भी काम करता है। वाक्यविन्यास समान है, इसलिए मैं एक नया उत्तर जोड़ने में परेशान नहीं करूंगा ( {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

फैक्टरैडिक प्रतिनिधित्व का उपयोग करना

एक क्रमपरिवर्तन के कारकत्‍मक निरूपण में मैं 0 से नी तक मान लेता हूं। तो एक यादृच्छिक क्रमपरिवर्तन rand(0,i)हर नी के लिए है।

जे में:

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

कहाँ ? xहै rand(0,x-1)और |.>:i.52है52 51 ... 1

फिर, यदि aइथ फैक्टैडिक का मान है , तो हम स्वैप करते हैं 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निरंतर उपयोग करने से बचने के लिए डेक की लंबाई ( ) का उपयोग करेंगे ।

जम्मू में पूरा कार्यक्रम:

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

सी#

यहाँ फिशर-येट्स एल्गोरिथ्म पर आधारित मेरा अपना जवाब है । यदि आपका रैंडम नंबर जनरेटर काफी अच्छा है तो आपको एक सही फेरबदल करना चाहिए।

अंग्रेजी संस्करण:

  1. बार-बार कार्ड को deck[0]उसी के साथ स्वैप करें deck[v], जहां vकार्ड का अंकित मूल्य है deck[0]। तक दोहराएं v == 0। यह आंशिक रूप से डेक को सॉर्ट करेगा, लेकिन इससे कोई फर्क नहीं पड़ता। अब आप जानते हैं कि कार्ड 0 डेक के सामने है, जिसका अर्थ है कि आप उस स्थान को सरणी में चोरी कर सकते हैं और इसे लूप काउंटर के रूप में उपयोग कर सकते हैं। स्थानीय चर की समस्या के लिए यह "धोखा" है।
  2. स्थिति 1 (डेक में दूसरा कार्ड) से शुरू होकर, कार्ड iको एक साथ स्वैप करें rand(i, 51)। ध्यान दें कि आपको जरूरत है rand(i, 51), नहीं rand(1, 51) । यह सुनिश्चित नहीं होगा कि प्रत्येक कार्ड यादृच्छिक है।
  3. 0 पर सेट करें deck[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)]);
}

जावास्क्रिप्ट संस्करण:

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 <= संख्या <तर्क।)

इसके अतिरिक्त - सॉगार्ट के पर्ल समाधान के समान, लेकिन जहां तक ​​मुझे पता है कि यह समस्या से ग्रस्त नहीं है:

deck = deck.sort_by{rand}

रूबी की sort_by सॉर्ट से भिन्न है - यह पहले सरणी को सॉर्ट करने के लिए मानों की सूची बनाता है, और उसके बाद ही उनके द्वारा सॉर्ट करता है। यह तब और तेज़ हो जाता है, जब हम उस संपत्ति का पता लगाना चाहते हैं, जो अन्य सभी मामलों में कुछ धीमी होती है। यह कोड गोल्फ में भी उपयोगी है: पी


मैं इसे प्रति धोखा नहीं कहूंगा, लेकिन deck[0..51]भाषा की एक विशेषता का उपयोग करके "कोई चर" नियम को स्कर्ट नहीं करता है। यह उचित है, मुझे लगता है कि यह कुछ चुनौती खो देता है। :) मैं रूबी को नहीं जानता; क्या आप (0..51).map{deck.delete_at(rand deck.length)}हिस्सा समझा सकते हैं ? क्या इससे कार्ड हटते हैं deck?
जस्टिन मॉर्गन

@JustinMorgan हाँ, 52 बार यह एक यादृच्छिक कार्ड को हटाता है deckऔर परिणाम की आंतरिक सूची में इसे जोड़ता mapहै। फिर जब वहाँ कुछ भी नहीं में छोड़ दिया है परिणाम में नकल हो जाता है । मूल रूप से एक अस्थायी है, लेकिन यह एक स्पष्ट चर के बजाय एक भाषा विशेषता है :)deckmapdeck
hobbs

deck.sort_by!{rand}छोटा है।
एरिक डुमिनील

1

जावास्क्रिप्ट

नोट: यह समाधान तकनीकी रूप से सही नहीं है क्योंकि यह 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जावास्क्रिप्ट में पास-दर-संदर्भ का कोई बदलाव नहीं होने के कारण थोड़ा संशोधित करना पड़ा ):

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 कभी भी मूल स्थान पर कब्जा नहीं करेगा, और क्योंकि आप केवल 51 उत्पन्न करने के लिए पर्याप्त रैंड कहते हैं! संभावित 52 में से क्रमपरिवर्तन!
आआआआआआआआआआ आआआआआ

2
@eBusiness: मूल कल्पना में, डेक को मनमाने ढंग से आदेश दिया जाता है, जरूरी नहीं कि आदेश 1-52 में हो। मैंने सिर्फ इसलिए इस्तेमाल किया क्योंकि यह सबसे आसान था।
मैलामोकब

1
@eBusiness: मैंने तत्व को उसी स्थान पर छोड़ने की संभावना के लिए संशोधित किया, deck[rand(0,i-1)]इसके बजाय का उपयोग करके deck[rand(0,i-2)]। इसके अलावा रास्ते i=0में रोकने के बजाय सभी को स्वैप करें i=1। क्या उससे मदद हुई?
मेलामोकब

हाँ, यह करना चाहिए, सिवाय इसके कि अब आप XOR स्वैप विनिर्देशन को तोड़ते हैं।
आआआआआआआआआआ आआआआआ

1

सी ++

#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

एक और पर्ल समाधान, जो वास्तव में समान रूप से वितरित आउटपुट का उत्पादन करता है:

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

say join " ", shuffle_integers 1 .. 52;

यह समाधान पर्ल का उपयोग करता है rand, जो 0 1. x <1. रेंज में एक यादृच्छिक संख्या x लौटाता है । यह इनपुट में प्रत्येक पूर्णांक में इस तरह की एक यादृच्छिक संख्या जोड़ता है, संख्याओं को उनके भिन्नात्मक भागों के अनुसार क्रमबद्ध करता है, और अंत में उन भिन्नात्मक भागों को फिर से दूर करता है ।

(मेरा मानना ​​है कि विशेष चर का उपयोग $_, $aऔर $bचुनौती की भावना के भीतर आता है, क्योंकि वे हैं कि कैसे पर्ल इनपुट करने के लिए mapऔर पास करता है sort, और वे कोड में किसी अन्य उद्देश्य के लिए उपयोग नहीं किए जाते हैं। किसी भी मामले में, मेरा मानना ​​है। वे वास्तव में इनपुट मूल्यों के लिए उपनाम हैं, स्वतंत्र प्रतियां नहीं। यह वास्तव में एक जगह में फेरबदल नहीं है, हालांकि, दोनों mapऔर sortस्टैक पर इनपुट की प्रतियां बनाते हैं।)


1

जावा

मुझे आश्चर्य है कि किसी ने स्पष्ट नहीं कहा: (मैं मान लूंगा (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

चूंकि हमें सच्ची यादृच्छिकता की आवश्यकता है, इसलिए कुछ बर्लेस्क ऐसा करने में सक्षम नहीं है क्योंकि बर्लेस्क में कोई I / O कार्यक्षमता नहीं है जिसे आपको STDIN के माध्यम से यादृच्छिकता के कुछ स्रोत प्रदान करने की आवश्यकता होगी।

शायद ऐसा ही कुछ मैं बाद के संस्करण में ठीक करूँगा (यानी स्टार्टअप पर एक यादृच्छिक बीज उत्पन्न करता हूं और इसे द्वितीयक स्टैक या कुछ इस तरह धक्का देता हूं, लेकिन बर्लेस्क इंटरप्रेटर में कोई I / O नहीं है)।


0

जावास्क्रिप्ट

मुझे यकीन नहीं है कि यह "धोखा" है, लेकिन मेरा समाधान एक फ़ंक्शन के तर्कों के मूल स्थानीय सरणी का उपयोग करता है। मैंने अपने स्व-निर्मित कार्यों को शामिल किया 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();

यह धोखा है, मुझे लगता है। हालांकि, यह बहुत चालाक धोखा है, इसलिए अच्छा काम है।
जस्टिन मॉर्गन 19

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

जावास्क्रिप्ट 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
जस्टिन मॉर्गन

स्पष्ट करने के लिए, उपरोक्त टिप्पणी नए संस्करण पर लागू होती है, जो अभी भी यादृच्छिक नहीं है।
जस्टिन मॉर्गन 16
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.