কেন এই কোডটি এলোমেলো স্ট্রিং ব্যবহার করে "হ্যালো ওয়ার্ল্ড" মুদ্রণ করে?


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
ঠিক আছে, সেই নির্দিষ্ট বীজগুলি ঠিক তাই সঠিকভাবে কাজ করতে ঘটে। এলোমেলোভাবে সত্যই এলোমেলো নয়, এটি সিউডোরানডম।
ডুরকনব

341
এটি কাজ করে, যেমন অন্যেরা বলেছেন, কারণ এলোমেলো নয়। আমার কাছে, আরও আকর্ষণীয় প্রশ্ন হ'ল সেই ব্যক্তি যিনি লিখেছেন, এটি জোর করে চাপিয়ে দেয়, বা নির্ধারিত বীজের জন্য পরবর্তী এন মানগুলির জন্য এলোমেলোভাবে কী উত্পন্ন করবে তা অনুমান করার একটি সহজ উপায় আছে? ব্রুট জোর করা সহজ এবং আধুনিক হার্ডওয়্যার সহ খুব বেশি সময় নেওয়া উচিত নয়, তাই এটি করার একটি কার্যকর উপায় সন্ধান করা হয়েছিল। এটি স্থিতিশীল, আপনি সহজেই কোনও নেটওয়ার্ক জুড়ে অনুসন্ধান বিতরণ করতে পারেন।
জোমোরনো

78
আমি উদ্দেশ্য ভাবছি nমধ্যে for (int n = 0; ; n++)। তারা ব্যবহার করতে পারেন for(;;)বা while(true)পরিবর্তে!
ইঞ্জি ফুয়েড

13
সত্যিকারের এলোমেলো ক্রমে প্রতিটি সম্ভাব্য স্ট্রিং শেষ পর্যন্ত উপস্থিত হবে। একটি উচ্চ মানের সিউডো এলোমেলো ক্রমটি যথাযথভাবে দৈর্ঘ্যের প্রতিটি সম্ভাব্য স্ট্রিং (লগ_স (এন) - এন) বিটগুলি আশা করতে পারে (যেখানে এন পিআরএনজি অভ্যন্তরীণ অবস্থার বিট সংখ্যা এবং এন একটি ছোট সংখ্যা, সুবিধার্থে 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 বিটের মান।
স্টিফেন সি

80
র্যান্ডম সংখ্যা ক্রম প্রতিটি উপাদান মডিউল 27 নেওয়া হয়, এবং সেখানে প্রতিটি 6 উপাদান "hello\0"এবং "world\0"। আপনি যদি সত্যই এলোমেলো জেনারেটর ধরে রেখেছেন তবে যে সিকোয়েন্সটি আপনি খুঁজছেন তা পাওয়ার জন্য প্রতিক্রিয়াগুলি 27 ^ 6 (387,420,489) এ 1 হবে - সুতরাং এটি বেশ চিত্তাকর্ষক তবে বেশ মন খারাপ করার মতো নয়!
রাসেল বোরোগোভ

17
@ রাসেলবোরোগোভ: তবে এই প্রতিকূলতা এবং 2 ^ 64 সম্ভাব্য বীজের সাথে একটি প্রত্যাশিত 47.6 বিলিয়ন বীজ মান রয়েছে যা এই ক্রমটি দেয়। এটি কেবল একটি সন্ধানের বিষয়।
dan04

8
@ dan04 - আমি এই অনুমানটি করতে বেশ আগ্রহী ছিলাম না; PRNG বাস্তবায়নের উপর নির্ভর করে বীজ শব্দের আকার রাষ্ট্রের আকারের সমান হতে পারে না এবং ক্রমপথগুলি সমানভাবে বিতরণ করা যাবে না। তবে তবুও, অসুবিধাগুলি অবশ্যই ভাল, এবং যদি আপনি কোনও জুটি না খুঁজে পান তবে আপনি বিভিন্ন কেসিং ( "Hello" "World") ব্যবহার করে বা এর 122-kপরিবর্তে 96+kবা ... ব্যবহার করে আবার চেষ্টা করতে পারেন
রাসেল বোরোগোভ

7
@ থরবজরনআরভানএন্ডারসেন জাভাদোক উল্লেখ করেছেন যে "নির্দিষ্ট অ্যালগরিদমগুলি র্যান্ডম শ্রেণির জন্য নির্দিষ্ট করা হয়েছে। জাভা কোডের নিখুঁত বহনযোগ্যতার জন্য জাভা বাস্তবায়নগুলি অবশ্যই এলোমেলো ক্লাসের জন্য এখানে দেখানো সমস্ত অ্যালগরিদম ব্যবহার করতে হবে।"
এফটিহম্পসন

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 ফেরত দেয়
ব্যবহারকারী 253751

1
@ মিম্বিস কেন? মানে র্যান্ডম () প্রত্যেকবার র্যান্ডম নম্বর ফিরিয়ে আনতে হবে, কোনও ফিক্স অর্ডার করা নম্বর সেট নয়?
রুট ট্র্যাভেলার

5
@ রুরট্রেভেলার এক শুরু করার জন্য, new Random()কোনও সংখ্যা মোটেও ফেরায় না।
ব্যবহারকারী 253751

2
এই বীজগুলি গণনা করার কোনও উপায় আছে কি? কিছু যুক্তি থাকতে হবে ... বা এটি কেবল নিষ্ঠুর শক্তি।
সোহিত গোর

2
@ সোহিতগোর প্রদত্ত যে জাভার ডিফল্টটি Randomক্রিপ্টোগ্রাফিকভাবে নিরাপদ নয় (এটি আমি নিশ্চিত যে এটি একজন মের্সেন টুইস্টার, তবে আমাকে উক্তিটি দেবেন না), সম্ভবত "আমি এই সংখ্যাগুলি চাই" থেকে "পিছন দিকে কাজ করা সম্ভব" এটিই বীজ আমি ব্যবহার করব "। আমি স্ট্যান্ডার্ড সি লিনিয়ার কংগ্রেসনাল জেনারেটরের সাথে অনুরূপ কিছু করেছি।
ফান্ড মনিকার লসুইট

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
@ ওয়ানটিওথ্রি nextInt(27)মানে সীমার মধ্যে [0, 26]
ইঞ্জি ফুয়েড

30
@ ভ্যালকান বেশিরভাগ বীজের সর্বাধিক মানের খুব কাছাকাছি, ঠিক যদি আপনি 1 এবং 1000 এর মধ্যে এলোমেলো সংখ্যা নির্বাচন করেন, তবে আপনি যে সংখ্যাটি বেছে নিয়েছেন শেষ পর্যন্ত বেশিরভাগ সংখ্যার তিনটি সংখ্যা থাকবে। এটি অবাক করার মতো নয়, যখন আপনি এটি সম্পর্কে চিন্তা করেন :)
টমাস

18
@ ভ্যালকান আসলে আপনি যদি গণিত করেন তবে আপনি দেখতে পাবেন যে এগুলি শূন্যের কাছাকাছি সর্বাধিক মানের প্রায় কাছাকাছি রয়েছে (আমি মনে করি বীজটি প্রজন্মের কোডটিতে স্বাক্ষরযুক্ত হিসাবে ব্যাখ্যা করা হচ্ছে)। তবে সংখ্যার সংখ্যাটি আসল মান সহ কেবল লোগারিথ্মিকভাবে বৃদ্ধি পাওয়ায় সংখ্যাটি সত্যই যদি তা প্রকৃতপক্ষে না দেখা যায়।
টমাস

10
দুর্দান্ত উত্তর। এবং বোনাস পয়েন্টগুলির জন্য, আপনি এমন একটি বীজ খুঁজে পেতে পারেন যা একটি এলোমেলো সূচনা করবে যা চূড়ান্ত র্যান্ডমগুলির সূচনা করার জন্য প্রয়োজনীয় 4 টি বীজের ক্রম উত্পাদন করবে?
মারেক

13
@ মারেক: আমার মনে হয় না সিউডো দেবতারা এ জাতীয় আচরণকে অনুমোদন করবে।
ডেনিস তুলসকি

254

কোডটি কীভাবে কাজ করে এবং কীভাবে আপনি নিজের উদাহরণ তৈরি করতে পারেন তা বোঝানোর জন্য এখানে সকলেই দুর্দান্ত কাজ করেছিলেন, তবে এখানে একটি তথ্য তাত্ত্বিক উত্তর রয়েছে যা আমরা যুক্তিযুক্তভাবে সমাধানের জন্য কেন আশা করতে পারি যে ব্রুট ফোর্স অনুসন্ধান অবশেষে খুঁজে পাবে।

26 টি ছোট ছোট অক্ষরগুলি আমাদের বর্ণমালা গঠন করে Σ। বিভিন্ন দৈর্ঘ্যের শব্দ উত্পন্ন করার জন্য, আমরা আরও একটি বর্ধিত বর্ণমালা উত্পন্ন করতে একটি টার্মিনেটর প্রতীক যুক্ত করি Σ' := Σ ∪ {⊥}

আসুন αএকটি প্রতীক এবং এক্স সমানভাবে বিতরণ করা এলোমেলো পরিবর্তনশীল Σ'। প্রতীকটি প্রাপ্ত করার সম্ভাবনা P(X = α), এবং এর তথ্য সামগ্রী I(α), এর দ্বারা প্রদত্ত:

পি (এক্স = α) = 1 / | Σ '| = 1/27

আমি (α) = -লগ [পি (এক্স = α)] = -লগ (1/27) = লগ (27)

একটি শব্দ ω ∈ Σ*এবং এটির ⊥-সমাপ্ত সমাপ্তির জন্য ω' := ω · ⊥ ∈ (Σ')*, আমাদের কাছে রয়েছে

আমি (ω): = আমি (ω ') = | ω' | * লগ ((27) = (| ω | + 1) * লগ (27)

যেহেতু সিউডোরডম নম্বর জেনারেটর (পিআরএনজি) 32-বিট বীজ দিয়ে শুরু করা হয়েছে, তাই আমরা বেশিরভাগ দৈর্ঘ্যের শব্দ আশা করতে পারি

λ = তল [32 / লগ₂ (27)] - 1 = 5

কমপক্ষে একটি বীজ দ্বারা উত্পাদিত করা। এমনকি যদি আমরা একটি character-চরিত্রের শব্দটি অনুসন্ধান করতে চাই, তবে আমরা এখনও প্রায় ৪১.০ be% সময় সাফল্য অর্জন করব। খুব বাজে না.

Letters টি বর্ণের জন্য আমরা 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


আমার তথ্য তত্ত্বটি এক ধরণের দুর্বল তবে আমি এই প্রমাণটি পছন্দ করি। কেউ আমাকে ল্যাম্বডা লাইনটি ব্যাখ্যা করতে পারে, স্পষ্টতই আমরা একজনের তথ্য সামগ্রীটিকে অপরের সাথে ভাগ করে দিচ্ছি, তবে কেন এটি আমাদের শব্দের দৈর্ঘ্য দেয়? যেমনটি আমি বলেছিলাম যে আমি ধোঁয়াটে তাই স্পষ্টভাবে জিজ্ঞাসা করার জন্য ক্ষমা চেয়েছি (এনবি এটি শ্যানন সীমা-কোড আউটপুট থেকে কিছু করার জন্য)
মাইক এইচআর

1
@ মাইকএইচ-আর ল্যাম্বডা লাইনটি I(⍵)পুনরায় সাজানো সমীকরণ। I(⍵)32 (বিট) হয় এবং |⍵|5 (প্রতীক) হতে দেখা যায়।
আইসম্যান

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);
        }
    }
}

( আদর্শের উপর ডেমো। )

পুনশ্চ. -727295876, -128911, -1611659, -235516779


35

আমি এটি দেখে আগ্রহী হয়েছি, আমি একটি অভিধান শব্দ তালিকায় এই এলোমেলো শব্দ জেনারেটর চালিয়েছি ran ব্যাপ্তি: পূর্ণসংখ্যা। 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
আপনি আমার দিনটির মানুষটি করেছেন: ডিআই লং.মিন / ম্যাক্স দিয়ে এটি চেষ্টা করে এবং আমার সহকর্মীদের নাম অনুসন্ধান করেছে এবং কেবল পিটার খুঁজে পেয়েছি: (পিটার 4611686018451441623 পিটার 24053719 পিটার -4611686018403334185 পিটার -9223372036830722089 পিটার -51111686865993353687159 পিটার -111138687179 4611686017645756173 পিটার 781631731 পিটার 4611686019209019635 পিটার -9223372036073144077 পিটার -4611686017420317288 পিটার 1007070616 পিটার -9223372035847705192)
মার্সেল

25

বেশিরভাগ এলোমেলো সংখ্যার জেনারেটর আসলে "সিউডো এলোমেলো"। তারা হ'ল লিনিয়ার ক্রেগ্রুভেনশিয়াল জেনারেটর বা এলসিজি ( http://en.wikedia.org/wiki/Linear_congruential_generator )

একটি নির্দিষ্ট বীজ দিয়ে এলসিজিগুলি বেশ অনুমানযোগ্য। মূলত, এমন একটি বীজ ব্যবহার করুন যা আপনাকে আপনার প্রথম চিঠি দেয়, তারপরে এমন একটি অ্যাপ্লিকেশন লিখুন যা আপনার টার্গেটের স্ট্রিংয়ে পরবর্তী অক্ষরটি আঘাত না করা পর্যন্ত আপনার পরবর্তী অক্ষর (চর) তৈরি করে অবিরত রাখে এবং আপনাকে কতবার এলসিজি করতে হয়েছিল তা লিখুন। যতক্ষণ না আপনি প্রতিটি এবং প্রতিটি চিঠি তৈরি করেছেন Continue


3
ছদ্ম র্যান্ডম সংখ্যা জেনারেটরের উদাহরণ কী
চিলনিট

1
@ chiliNUT এই জাতীয় জেনারেটর হ'ল বাহ্যিক গ্যাজেটগুলি। কিছু বৈদ্যুতিন বাতি। বা খারাপভাবে লিখিত বিট যা 0 বা 1 টি পড়া হয় আপনি র্যান্ডম সংখ্যার খাঁটি ডিজিটাল জেনারেটর করতে পারবেন না, ডিজিটাল অ্যালগরিদম এলোমেলো নয়, এগুলি একেবারে নির্ভুল।
গাংনাস

@ চিলেনুট অনেক অপারেটিং সিস্টেম এনট্রপি সংগ্রহ করে । যেমন লিনাক্সে আপনি /dev/urandomএলোমেলো ডেটা পড়তে ডিভাইসটি ব্যবহার করতে পারেন । এটি অবশ্য একটি দুর্লভ সংস্থান। সুতরাং, এ জাতীয় এলোমেলো ডেটা সাধারণত পিআরএনজি বীজের জন্য ব্যবহৃত হয়।
অ্যাড্রিয়ান ডাব্লু

@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

এলোমেলো সবসময় একই ক্রম ফিরে আসে। এটি ক্রমান্বয়ে হিসাবে অ্যারে এবং অন্যান্য ক্রিয়াকলাপের জন্য ব্যবহৃত হয়।

বিভিন্ন সিকোয়েন্সগুলি পেতে, এটি "বীজ" নামক কিছু অবস্থানে ক্রমটি সূচনা করতে হবে।

র্যান্ডমস্টেটিং এ "র্যান্ডম" সিক্যুয়েন্সের আই পজিশনে (বীজ = -229985452) এলোমেলো নম্বর পান। তারপরে বীজের অবস্থানের পরে যথাক্রমে পরবর্তী ২ AS টি অক্ষরের জন্য ASCII কোড ব্যবহার করুন যতক্ষণ না এই মান 0 এর সমান হয় This এটি "হ্যালো" ফেরত দেয়। "ওয়ার্ল্ড" এর জন্য একই অপারেশন করা হয়।

আমি মনে করি যে কোডটি অন্য কোনও শব্দের জন্য কাজ করে নি। যে লোকটি প্রোগ্রাম করেছিল যে এলোমেলো ক্রমটি খুব ভাল করে জানে।

এটি খুব দুর্দান্ত গিক কোড!


10
আমি সন্দেহ করি যদি তিনি "র্যান্ডম সিকোয়েন্সটি খুব ভাল জানেন"। সম্ভবত, তিনি কাজ করে এমন একটি আবিষ্কার না করা পর্যন্ত কয়েক বিলিয়ন সম্ভাব্য বীজ চেষ্টা করেছিলেন।
dan04

24
@ ডান04 রিয়েল প্রোগ্রামাররা কেবল পিআরএনজি ব্যবহার করে না, তারা পুরো সময়টিকে হৃদয় দিয়ে মনে করে এবং প্রয়োজনীয় মানগুলি গণ্য করে।
টমাস

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 "এলোমেলো সংখ্যা জেনারেটরের বীজকে একটি মান হিসাবে সেট করে যা সম্ভবত এই নির্মাতার অন্য যে কোনও অনুরোধের চেয়ে পৃথক হতে পারে" ( জাভাদোক )। বর্তমান বাস্তবায়নে এটি বর্তমান সময়ের এবং একটি পালকের সংমিশ্রণ।
মার্টিন

প্রকৃতপক্ষে. সম্ভবত প্রাথমিক বীজের মান নির্দিষ্ট করার জন্য ব্যবহারিক ব্যবহারের ক্ষেত্রে রয়েছে। আমার ধারণা, আপনি যে সিউডোরডম কীফবগুলি পেতে পারেন সেগুলির অপারেটিং নীতিটি (আরএসএ বেশী?)
ডিড02392

4
@ ডিড02392 অবশ্যই বীজের মূল্য নির্দিষ্ট করার জন্য ব্যবহারিক ব্যবহারের ক্ষেত্রে রয়েছে। যদি আপনি কোনও সমস্যা সমাধানের জন্য কোনও প্রকার মন্টি কার্লো পদ্ধতির জন্য ডেটা সিমুলেট করে থাকেন তবে আপনার ফলাফলগুলি পুনরুত্পাদন করতে সক্ষম হওয়া ভাল। প্রাথমিক বীজ নির্ধারণ করা এটির সবচেয়ে সহজ উপায়।
Dason


3

এখানে ডেনিস Tulskiy জন্য একটি ছোটখাট উন্নতি হয় উত্তর । অর্ধেক সময় কেটে দেয়

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.