रैंडम स्ट्रिंग्स का उपयोग करने वाला यह कोड "हैलो वर्ल्ड" क्यों प्रिंट करता है?


1769

निम्नलिखित प्रिंट स्टेटमेंट "हैलो वर्ल्ड" को प्रिंट करेगा। क्या कोई इसे समझा सकता है?

System.out.println(randomString(-229985452) + " " + randomString(-147909649));

और randomString()इस तरह दिखता है:

public static String randomString(int i)
{
    Random ran = new Random(i);
    StringBuilder sb = new StringBuilder();
    while (true)
    {
        int k = ran.nextInt(27);
        if (k == 0)
            break;

        sb.append((char)('`' + k));
    }

    return sb.toString();
}

158
ठीक है, उन विशेष बीज अभी तो पूरी तरह से बाहर काम करने के लिए होता है। रैंडम वास्तव में यादृच्छिक नहीं है, यह छद्म आयामी है।
Doorknob

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

78
मैं करने के उद्देश्य से आश्चर्य nमें for (int n = 0; ; n++)। वे उपयोग कर सकते हैं for(;;)या while(true)इसके बजाय!
Eng.Fouad

13
वास्तव में यादृच्छिक क्रम में हर संभव स्ट्रिंग अंततः दिखाई देगा। एक उच्च गुणवत्ता वाले छद्म यादृच्छिक अनुक्रम में लंबाई के हर संभव स्ट्रिंग (log_s (N) - n) बिट्स की उम्मीद कर सकते हैं (जहाँ N PRNGs आंतरिक स्थिति में बिट्स की संख्या है और n एक छोटी संख्या है, सुविधा के लिए 8 चुन सकते हैं) ) चक्र में दिखाई देने के लिए। इस कोड को स्वतंत्र रूप से चुने गए हार्डकॉस्ट स्टार्ट पॉइंट (चरित्र बैकटिक का मूल्य) के उपयोग से कुछ मदद मिलती है जो लगभग पूरे 8 बिट्स वापस मिल जाती है।
dmckee --- पूर्व-मध्यस्थ ने बिल्ली

13
यह एक पोस्टिंग से है जो मैंने कुछ साल पहले लिखा था। vanillajava.blogspot.co.uk/2011/10/randomly-no-so-random.html
पीटर लॉरी

जवाबों:


917

जब एक java.util.Randomविशिष्ट बीज पैरामीटर (इस मामले में -229985452या -147909649) के साथ एक आवृत्ति का निर्माण किया जाता है , तो यह उस बीज मान के साथ शुरू होने वाली यादृच्छिक संख्या पीढ़ी एल्गोरिथ्म का अनुसरण करता है ।

हर Randomएक ही बीज के साथ निर्मित संख्याओं का एक ही पैटर्न हर बार उत्पन्न होगा।


8
@ वल्कन - जावदोक का कहना है कि बीज 48 बिट्स का होता है। docs.oracle.com/javase/7/docs/api/java/util/Random.html । और इसके अलावा, वास्तविक बीज 32 बिट मान हैं।
स्टीफन C

80
यादृच्छिक संख्या अनुक्रम के प्रत्येक तत्व सापेक्ष 27 से लिया जाता है, और वहाँ से प्रत्येक में 6 तत्व हैं "hello\0"और "world\0"। यदि आपने वास्तव में यादृच्छिक जनरेटर मान लिया है, तो ऑड्स 27 ^ 6 (387,420,489) में 1 होगा जो आप देख रहे थे - इसलिए यह बहुत प्रभावशाली है, लेकिन बहुत दिमाग उड़ाने वाला नहीं है!
रसेल बोरोगोव

17
@RussellBorogove: लेकिन उन बाधाओं के साथ, और 2 ^ 64 संभावित बीज, एक अपेक्षित 47.6 बिलियन बीज मान हैं जो उस क्रम को देते हैं। यह सिर्फ एक खोजने की बात है।
dan04

8
@ dan04 - मैं यह अनुमान लगाने के लिए बिल्कुल तैयार नहीं था; PRNG के कार्यान्वयन के आधार पर, बीज शब्द का आकार राज्य के आकार के बराबर नहीं हो सकता है, और अनुक्रम पथ समान रूप से वितरित नहीं किए जा सकते हैं। लेकिन फिर भी, बाधाओं निश्चित रूप से अच्छे हैं, और यदि आप एक जोड़ी नहीं पा सके आप अलग अलग आवरण (के साथ फिर से कोशिश कर सकते "Hello" "World"हैं), या का उपयोग कर 122-kके बजाय 96+k, या ...
रसेल Borogove

7
@ ThorbjørnRavnAndersen Javadoc निर्दिष्ट करता है कि "विशेष एल्गोरिदम क्लास रैंडम के लिए निर्दिष्ट हैं। जावा कार्यान्वयन को जावा कोड के निरपेक्ष पोर्टेबिलिटी के लिए, क्लास रैंडम के लिए यहां दिखाए गए सभी एल्गोरिदम का उपयोग करना चाहिए।"
FThompson

1137

अन्य उत्तर बताते हैं कि क्यों, लेकिन यहाँ है कैसे।

का एक उदाहरण दिया Random:

Random r = new Random(-229985452)

r.nextInt(27)उत्पन्न करने वाले पहले 6 नंबर हैं:

8
5
12
12
15
0

और जो पहले 6 नंबर r.nextInt(27)दिए गए Random r = new Random(-147909649)हैं, वे हैं:

23
15
18
12
4
0

फिर वर्ण के पूर्णांक निरूपण में वे संख्याएँ जोड़ें `(जो 96 है):

8  + 96 = 104 --> h
5  + 96 = 101 --> e
12 + 96 = 108 --> l
12 + 96 = 108 --> l
15 + 96 = 111 --> o

23 + 96 = 119 --> w
15 + 96 = 111 --> o
18 + 96 = 114 --> r
12 + 96 = 108 --> l
4  + 96 = 100 --> d

48
गंभीर रूप से, new Random(-229985452).nextInt(27)हमेशा 8.
user253751

1
@ मिनीबिस क्यों? मेरा मतलब है कि रैंडम () को हर बार रैंडम नंबर वापस करना चाहिए, न कि फिक्स ऑर्डर नंबर सेट?
रोज़ट्रेलर

5
@rootTraveller एक शुरुआत के लिए, new Random()एक संख्या को बिल्कुल भी वापस नहीं करता है।
user253751

2
क्या इन बीजों की गणना करने का कोई तरीका है? कुछ तर्क होना चाहिए ... या यह केवल क्रूर बल है।
सोहित गोर

2
@SohitGore यह देखते हुए कि जावा का डिफ़ॉल्ट Randomक्रिप्टोग्राफिक रूप से सुरक्षित नहीं है (मुझे पूरा यकीन है कि यह एक मेर्सेन ट्विस्टर है, लेकिन मुझे उस पर उद्धरण नहीं देना है), "शायद मुझे ये नंबर चाहिए" से पीछे काम करना संभव है "यह" है बीज मैं उपयोग करेंगे "। मैंने मानक सी रैखिक बधाई जनरेटर के साथ कुछ ऐसा ही किया है।
निधि मोनिका का मुकदमा 20

280

मैं इसे यहाँ छोड़ दूँगा। जिसके पास बहुत अधिक (सीपीयू) समय बचे, उसके लिए प्रयोग करने में संकोच न करें :) इसके अलावा, अगर आपको इस चीज़ को सभी सीपीयू कोर (बस धागे उबाऊ हैं, ठीक है?) को जलाने के लिए कुछ कांटे-जुड़ने में महारत हासिल है, तो कृपया साझा करें? तुम्हारा कोड। मुझे इसकी तारीफ़ करने में गर्व है।

public static void main(String[] args) {
    long time = System.currentTimeMillis();
    generate("stack");
    generate("over");
    generate("flow");
    generate("rulez");

    System.out.println("Took " + (System.currentTimeMillis() - time) + " ms");
}

private static void generate(String goal) {
    long[] seed = generateSeed(goal, Long.MIN_VALUE, Long.MAX_VALUE);
    System.out.println(seed[0]);
    System.out.println(randomString(seed[0], (char) seed[1]));
}

public static long[] generateSeed(String goal, long start, long finish) {
    char[] input = goal.toCharArray();
    char[] pool = new char[input.length];
    label:
    for (long seed = start; seed < finish; seed++) {
        Random random = new Random(seed);

        for (int i = 0; i < input.length; i++)
            pool[i] = (char) random.nextInt(27);

        if (random.nextInt(27) == 0) {
            int base = input[0] - pool[0];
            for (int i = 1; i < input.length; i++) {
                if (input[i] - pool[i] != base)
                    continue label;
            }
            return new long[]{seed, base};
        }

    }

    throw new NoSuchElementException("Sorry :/");
}

public static String randomString(long i, char base) {
    System.out.println("Using base: '" + base + "'");
    Random ran = new Random(i);
    StringBuilder sb = new StringBuilder();
    for (int n = 0; ; n++) {
        int k = ran.nextInt(27);
        if (k == 0)
            break;

        sb.append((char) (base + k));
    }

    return sb.toString();
}

आउटपुट:

-9223372036808280701
Using base: 'Z'
stack
-9223372036853943469
Using base: 'b'
over
-9223372036852834412
Using base: 'e'
flow
-9223372036838149518
Using base: 'd'
rulez
Took 7087 ms

24
@OneTwoThree का nextInt(27)मतलब है सीमा के भीतर [0, 26]
Eng.Fouad

30
@ वल्कन अधिकांश बीज अधिकतम मूल्य के बहुत करीब हैं, जैसे अगर आप 1 और 1000 के बीच यादृच्छिक संख्याओं का चयन करते हैं, तो आपके द्वारा चुने जाने वाले अधिकांश नंबरों के तीन अंक होंगे। यह आश्चर्य की बात नहीं है, जब आप इसके बारे में सोचते हैं :)
थॉमस

18
@ वल्कन वास्तव में यदि आप गणित करते हैं तो आप देखेंगे कि वे शून्य के अधिकतम मूल्य के करीब हैं (मुझे लगता है कि बीज को पीढ़ी कोड में अहस्ताक्षरित के रूप में व्याख्या किया जा रहा है)। लेकिन क्योंकि अंकों की संख्या केवल वास्तविक मूल्य के साथ तार्किक रूप से बढ़ती है, संख्या वास्तव में करीब लगती है जब यह वास्तव में नहीं होती है।
थॉमस

10
बहुत बढ़िया जवाब। और बोनस अंक के लिए, क्या आप एक बीज पा सकते हैं जो एक रैंडम को इनिशियलाइज़ करेगा जो अंतिम रैंडम के आरंभ के लिए आवश्यक 4 बीजों के अनुक्रम का उत्पादन करेगा?
मारेक

13
@Marek: मुझे नहीं लगता कि छद्म यादृच्छिक के देवता इस तरह के व्यवहार का अनुमोदन करेंगे।
डेनिस तुलस्की

254

यहां सभी ने यह समझाने का एक बड़ा काम किया कि कोड कैसे काम करता है और यह दर्शाता है कि आप अपने स्वयं के उदाहरणों का निर्माण कैसे कर सकते हैं, लेकिन यहां एक सूचना सैद्धांतिक उत्तर दिखाती है कि हम यथोचित समाधान की उम्मीद कर सकते हैं कि आखिरकार जानवर बल खोज आखिर में मिल जाएगा।

26 अलग-अलग लोअर-केस अक्षर हमारी वर्णमाला बनाते हैं Σ। विभिन्न लंबाई के शब्दों को उत्पन्न करने की अनुमति देने के लिए, हम आगे एक विस्तारित वर्णमाला प्राप्त करने के लिए एक टर्मिनेटर प्रतीक जोड़ते हैं Σ' := Σ ∪ {⊥}

आज्ञा αदेना एक प्रतीक और एक्स एक समान रूप से वितरित यादृच्छिक चर खत्म Σ'। उस प्रतीक को प्राप्त करने की संभावना P(X = α), और इसकी सूचना सामग्री, I(α)द्वारा दिए गए हैं:

P (X = α) = 1 / | | '| = 1/27

I (α) = -log₂ [P (X = α)] = -log 1/ (1/27) = log 27 (27)

एक शब्द ω ∈ Σ*और उसके ⊥-समाप्त समकक्ष के लिए ω' := ω · ⊥ ∈ (Σ')*, हमारे पास है

I ()): = I (ω ') = | |' | * log * (27) = (| ω | + 1) * log 27 (27)

चूँकि Pseudorandom Number Generator (PRNG) को 32-बिट बीज के साथ आरंभीकृत किया गया है, हम लंबाई के अधिकांश शब्दों की अपेक्षा कर सकते हैं

λ = मंजिल [32 / log₂ (27)] - 1 = 5

कम से कम एक बीज से उत्पन्न होना। यहां तक ​​कि अगर हमें 6-वर्ण शब्द की खोज करनी थी, तब भी हम लगभग 41.06% सफल होंगे। जर्जर भी नहीं।

7 अक्षरों के लिए हम 1.52% के करीब देख रहे हैं, लेकिन मुझे यह महसूस नहीं हुआ कि इसे देने से पहले:

#include <iostream>
#include <random>

int main()
{
    std::mt19937 rng(631647094);
    std::uniform_int_distribution<char> dist('a', 'z' + 1);

    char alpha;
    while ((alpha = dist(rng)) != 'z' + 1)
    {
        std::cout << alpha;
    }
}

आउटपुट देखें: http://ideone.com/JRGb3l


मेरा सूचना सिद्धांत एक तरह से कमजोर है लेकिन मुझे यह प्रमाण पसंद है। क्या कोई मुझे लंबोदर रेखा समझा सकता है, स्पष्ट रूप से हम एक के साथ दूसरे की सूचना सामग्री को विभाजित कर रहे हैं, लेकिन यह हमें हमारी शब्द-लंबाई क्यों देता है? जैसा कि मैंने कहा कि मैं थोड़े कठोर हूँ तो स्पष्ट पूछने के लिए क्षमा याचना (NB यह शैनन की सीमा से कुछ करना है -from कोड आउटपुट)
माइक एचआर

1
@ मिख-आर लाम्बा लाइन I(⍵)समीकरण को फिर से व्यवस्थित किया गया है। I(⍵)32 (बिट्स) है और |⍵|5 (प्रतीक) निकला है।
iceman

67

मैंने इन बीजों को खोजने के लिए एक त्वरित कार्यक्रम लिखा:

import java.lang.*;
import java.util.*;
import java.io.*;

public class RandomWords {
    public static void main (String[] args) {
        Set<String> wordSet = new HashSet<String>();
        String fileName = (args.length > 0 ? args[0] : "/usr/share/dict/words");
        readWordMap(wordSet, fileName);
        System.err.println(wordSet.size() + " words read.");
        findRandomWords(wordSet);
    }

    private static void readWordMap (Set<String> wordSet, String fileName) {
        try {
            BufferedReader reader = new BufferedReader(new FileReader(fileName));
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim().toLowerCase();
                if (isLowerAlpha(line)) wordSet.add(line);
            }
        }
        catch (IOException e) {
            System.err.println("Error reading from " + fileName + ": " + e);
        }
    }

    private static boolean isLowerAlpha (String word) {
        char[] c = word.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (c[i] < 'a' || c[i] > 'z') return false;
        }
        return true;
    }

    private static void findRandomWords (Set<String> wordSet) {
        char[] c = new char[256];
        Random r = new Random();
        for (long seed0 = 0; seed0 >= 0; seed0++) {
            for (int sign = -1; sign <= 1; sign += 2) {
                long seed = seed0 * sign;
                r.setSeed(seed);
                int i;
                for (i = 0; i < c.length; i++) {
                    int n = r.nextInt(27);
                    if (n == 0) break;
                    c[i] = (char)((int)'a' + n - 1);
                }
                String s = new String(c, 0, i);
                if (wordSet.contains(s)) {
                    System.out.println(s + ": " + seed);
                    wordSet.remove(s);
                }
            }
        }
    }
}

मेरे पास अब यह पृष्ठभूमि में चल रहा है, लेकिन यह पहले से ही एक क्लासिक पैंग्राम के लिए पर्याप्त शब्द पाया गया है:

import java.lang.*;
import java.util.*;

public class RandomWordsTest {
    public static void main (String[] args) {
        long[] a = {-73, -157512326, -112386651, 71425, -104434815,
                    -128911, -88019, -7691161, 1115727};
        for (int i = 0; i < a.length; i++) {
            Random r = new Random(a[i]);
            StringBuilder sb = new StringBuilder();
            int n;
            while ((n = r.nextInt(27)) > 0) sb.append((char)('`' + n));
            System.out.println(sb);
        }
    }
}

( Ideone पर डेमो। )

Ps। -727295876, -128911, -1611659, -235516779


35

मैं इससे सहमत था, मैंने इस यादृच्छिक शब्द जनरेटर को एक शब्दकोश शब्द सूची में चलाया। श्रेणी: Integer.MIN_VALUE से पूर्णांक। MAX_VALUE

मुझे 15131 हिट मिले।

int[] arrInt = {-2146926310, -1885533740, -274140519, 
                -2145247212, -1845077092, -2143584283,
                -2147483454, -2138225126, -2147375969};

for(int seed : arrInt){
    System.out.print(randomString(seed) + " ");
}

प्रिंटों

the quick browny fox jumps over a lazy dog 

7
आपने मेरा दिन आदमी बना दिया: DI ने इसे Long.Min / Max के साथ आजमाया और अपने सहयोगियों के नामों की खोज की और केवल याचिकाकर्ता को पाया: (पीटर 4611686018451441623 याचिकाकर्ता 24053719 याचिकाकर्ता -461168601403418185 peter -922337203683072208 peter -46116866016016016016016016016016017017017017184187184187 है, जो अब तक का है। 4611686017645756173 याचिकाकर्ता 781631731 याचिकाकर्ता 4611686019209019635 याचिकाकर्ता -9223372036073144077 याचिकाकर्ता -4611686017420317288 याचिकाकर्ता 1007070616 पीटर -9223372035847705192)
Marcel

25

अधिकांश यादृच्छिक संख्या जनरेटर वास्तव में, "छद्म यादृच्छिक" हैं। वे लीनियर कंज्यूमर्स जेनरेटर हैं, या LCGs ( http://en.wikipedia.org/wiki/Linear_congruential_generator )

एलसीजी एक निश्चित बीज दिए जाने के कारण काफी अनुमानित हैं। मूल रूप से, एक बीज का उपयोग करें जो आपको अपना पहला पत्र देता है, फिर एक ऐप लिखें जो अगले इंट (चार) को तब तक उत्पन्न करता है जब तक कि आप अपने लक्ष्य स्ट्रिंग में अगले अक्षर को हिट न करें और लिख लें कि आपको कितनी बार एलसीजी को लागू करना था। तब तक जारी रखें जब तक आप प्रत्येक अक्षर को उत्पन्न नहीं कर लेते।


3
एक गैर छद्म यादृच्छिक संख्या जनरेटर का एक उदाहरण
chiliNUT

1
@chiliNUT ऐसे जनरेटर बाहरी गैजेट हैं। कुछ इलेक्ट्रॉनिक लैंप। या बुरी तरह से लिखा हुआ बिट जो 0 या 1 पढ़ा जाता है। आप यादृच्छिक संख्याओं का शुद्ध डिजिटल जनरेटर नहीं कर सकते हैं, डिजिटल एल्गोरिदम यादृच्छिक नहीं हैं, वे बिल्कुल सटीक हैं।
गैंगनस

@chiliNUT कई ऑपरेटिंग सिस्टम एंट्रोपी एकत्र करते हैं । उदा लिनक्स में आप /dev/urandomयादृच्छिक डेटा को पढ़ने के लिए डिवाइस का उपयोग कर सकते हैं । हालांकि यह एक दुर्लभ संसाधन है। इसलिए, इस तरह के यादृच्छिक डेटा का उपयोग आमतौर पर PRNGs को बीज बनाने के लिए किया जाता है।
एड्रियन डब्ल्यू

@ AdrianW विकिपीडिया का कहना urandomहै कि अभी भी छद्म यादृच्छिक en.wikipedia.org/wiki//dev/random
chiliNUT

1
हां, लेकिन यह क्रिप्टोग्राफिक रूप से सुरक्षित है, जिसका अर्थ है कि कोई भी ब्रूट फोर्स अटैक नहीं कर सकता है (जैसे "यादृच्छिक" अनुक्रम "हैलो वर्ल्ड" के लिए बीज को खोजने के लिए) यादृच्छिक क्रम से बनाया गया है /dev/random। ऊपर मैंने जिस लेख का हवाला दिया है वह कहता है कि लिनक्स कर्नेल कीबोर्ड टाइमिंग, माउस मूवमेंट्स और आईडीई टाइमिंग से एन्ट्रापी उत्पन्न करता है और विशेष फाइल / देव / रैंडम और / डेव / यूरेनियम के माध्यम से अन्य ऑपरेटिंग सिस्टम प्रक्रियाओं को रैंडम कैरेक्टर डेटा उपलब्ध कराता है। मुझे विश्वास है कि यह वास्तव में यादृच्छिक है। हो सकता है कि यह पूरी तरह से सही न हो। लेकिन /dev/randomकम से कम होता है कुछ एन्ट्रापी।
एड्रियन डब्ल्यू

23

जैसा कि जावा के साथ मल्टी-थ्रेडिंग बहुत आसान है, यहां एक ऐसा संस्करण है जो उपलब्ध सभी कोर का उपयोग करके एक बीज की खोज करता है: http://ideone.com/ROhmTA

import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class SeedFinder {

  static class SearchTask implements Callable<Long> {

    private final char[] goal;
    private final long start, step;

    public SearchTask(final String goal, final long offset, final long step) {
      final char[] goalAsArray = goal.toCharArray();
      this.goal = new char[goalAsArray.length + 1];
      System.arraycopy(goalAsArray, 0, this.goal, 0, goalAsArray.length);
      this.start = Long.MIN_VALUE + offset;
      this.step = step;
    }

    @Override
    public Long call() throws Exception {
      final long LIMIT = Long.MAX_VALUE - this.step;
      final Random random = new Random();
      int position, rnd;
      long seed = this.start;

      while ((Thread.interrupted() == false) && (seed < LIMIT)) {
        random.setSeed(seed);
        position = 0;
        rnd = random.nextInt(27);
        while (((rnd == 0) && (this.goal[position] == 0))
                || ((char) ('`' + rnd) == this.goal[position])) {
          ++position;
          if (position == this.goal.length) {
            return seed;
          }
          rnd = random.nextInt(27);
        }
        seed += this.step;
      }

      throw new Exception("No match found");
    }
  }

  public static void main(String[] args) {
    final String GOAL = "hello".toLowerCase();
    final int NUM_CORES = Runtime.getRuntime().availableProcessors();

    final ArrayList<SearchTask> tasks = new ArrayList<>(NUM_CORES);
    for (int i = 0; i < NUM_CORES; ++i) {
      tasks.add(new SearchTask(GOAL, i, NUM_CORES));
    }

    final ExecutorService executor = Executors.newFixedThreadPool(NUM_CORES, new ThreadFactory() {

      @Override
      public Thread newThread(Runnable r) {
        final Thread result = new Thread(r);
        result.setPriority(Thread.MIN_PRIORITY); // make sure we do not block more important tasks
        result.setDaemon(false);
        return result;
      }
    });
    try {
      final Long result = executor.invokeAny(tasks);
      System.out.println("Seed for \"" + GOAL + "\" found: " + result);
    } catch (Exception ex) {
      System.err.println("Calculation failed: " + ex);
    } finally {
      executor.shutdownNow();
    }
  }
}

मेरी तरह जावा नोब करने के लिए, आपको आउटपुट नंबर के साथ प्रत्यय Lऔर तर्क प्रकार को बदलने की आवश्यकता है long, यानी randomString(long i)चारों ओर खेलने के लिए। :)
फ्रूट

21

रैंडम हमेशा उसी क्रम को वापस करते हैं। यह क्रमपरिवर्तन के रूप में सरणियों और अन्य कार्यों को फेरबदल करने के लिए उपयोग किया जाता है।

अलग-अलग अनुक्रम प्राप्त करने के लिए, यह आवश्यक है कि किसी क्रम में अनुक्रम को "बीज" कहा जाए।

RandomSting को "यादृच्छिक" क्रम के i स्थिति (बीज = -229985452) में यादृच्छिक संख्या मिलती है। फिर बीज स्थिति के बाद अनुक्रम में अगले 27 वर्णों के लिए ASCII कोड का उपयोग करता है जब तक कि यह मान 0. के बराबर न हो। यह "हेलिकॉप्टर" लौटाता है। एक ही ऑपरेशन "दुनिया" के लिए किया जाता है।

मुझे लगता है कि कोड किसी अन्य शब्दों के लिए काम नहीं करता था। वह लड़का जिसने क्रमादेशित क्रम को बहुत अच्छी तरह से जानता था।

यह बहुत ही बढ़िया geek कोड है!


10
मुझे संदेह है कि अगर वह "यादृच्छिक अनुक्रम को अच्छी तरह से जानता है"। अधिक संभावना है, उसने बस एक बार काम करने तक अरबों संभव बीज की कोशिश की।
dan04

24
@ dan04 असली प्रोग्रामर केवल PRNG का उपयोग नहीं करते हैं, वे पूरे अवधि को दिल से याद करते हैं और आवश्यकतानुसार मान बढ़ाते हैं।
थॉमस

1
"रैंडम हमेशा एक ही सीक्वेंस लौटाता है" - रैंडम के बाद () डालें या इसे एक कोड के रूप में दिखाएं। अन्य वाक्य गलत है।
गंगनुस

14

प्रिंसिपल एक ही बीज से निर्मित रैंडम क्लास है जो हर बार संख्याओं के समान पैटर्न उत्पन्न करेगा।


12

डेनिस तुलस्की के उत्तर से व्युत्पन्न , यह विधि बीज उत्पन्न करती है।

public static long generateSeed(String goal, long start, long finish) {
    char[] input = goal.toCharArray();
    char[] pool = new char[input.length];
    label:
        for (long seed = start; seed < finish; seed++) {
            Random random = new Random(seed);

            for (int i = 0; i < input.length; i++)
                pool[i] = (char) (random.nextInt(27)+'`');

            if (random.nextInt(27) == 0) {
                for (int i = 0; i < input.length; i++) {
                    if (input[i] != pool[i])
                        continue label;
                }
                return seed;
            }

        }

    throw new NoSuchElementException("Sorry :/");
}

10

जावा डॉक्स से, रैंडम क्लास के लिए बीज मान निर्दिष्ट करते समय यह एक जानबूझकर विशेषता है।

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

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html

हालांकि, आपको लगता है कि अनुमानित 'यादृच्छिक' संख्या होने में निहित सुरक्षा मुद्दे हैं।


3
यही कारण है कि Random" डिफॉल्ट कंस्ट्रक्टर का बीज यादृच्छिक संख्या जनरेटर के बीज को इस कंस्ट्रक्टर के किसी भी अन्य आह्वान से अलग होने की संभावना के लिए निर्धारित करता है" ( javadoc )। वर्तमान कार्यान्वयन में यह वर्तमान समय और एक काउंटर का संयोजन है।
मार्टिन

वास्तव में। वर्तमान में प्रारंभिक बीज मूल्य निर्दिष्ट करने के लिए व्यावहारिक उपयोग के मामले हैं, फिर। मुझे लगता है कि उन छद्म आयामी keyfobs के ऑपरेटिंग सिद्धांत आप प्राप्त कर सकते हैं (RSA वाले?)
deed02392

4
@ deed02392 निश्चित रूप से बीज के मूल्य को निर्दिष्ट करने के लिए व्यावहारिक उपयोग के मामले हैं। यदि आप किसी समस्या को हल करने के लिए किसी प्रकार के मोंटे कार्लो दृष्टिकोण का उपयोग करने के लिए डेटा का अनुकरण कर रहे हैं तो आपके परिणामों को पुन: पेश करने में सक्षम होना अच्छी बात है। एक प्रारंभिक बीज निर्धारित करना सबसे आसान तरीका है।
दासन


3

यहां डेनिस तुलस्किया जवाब के लिए एक मामूली सुधार है । यह समय को आधा काट देता है

public static long[] generateSeed(String goal, long start, long finish) {
    char[] input = goal.toCharArray();

    int[] dif = new int[input.length - 1];
    for (int i = 1; i < input.length; i++) {
        dif[i - 1] = input[i] - input[i - 1];
    }

    mainLoop:
    for (long seed = start; seed < finish; seed++) {
        Random random = new Random(seed);
        int lastChar = random.nextInt(27);
        int base = input[0] - lastChar;
        for (int d : dif) {
            int nextChar = random.nextInt(27);
            if (nextChar - lastChar != d) {
                continue mainLoop;
            }
            lastChar = nextChar;
        }
        if(random.nextInt(27) == 0){
            return new long[]{seed, base};
        }
    }

    throw new NoSuchElementException("Sorry :/");
}

1

यह सब बीज के बारे में है । एक ही बीज हर समय एक ही परिणाम देता है। यहां तक ​​कि आप अपने कार्यक्रम को फिर से चलाते हैं और फिर से वही आउटपुट देते हैं।

public static void main(String[] args) {

    randomString(-229985452);
    System.out.println("------------");
    randomString(-229985452);

}

private static void randomString(int i) {
    Random ran = new Random(i);
    System.out.println(ran.nextInt());
    System.out.println(ran.nextInt());
    System.out.println(ran.nextInt());
    System.out.println(ran.nextInt());
    System.out.println(ran.nextInt());

}

उत्पादन

-755142161
-1073255141
-369383326
1592674620
-1524828502
------------
-755142161
-1073255141
-369383326
1592674620
-1524828502
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.