අහඹු නූල් භාවිතා කරන මෙම කේතය “හෙලෝ වර්ල්ඩ්” මුද්‍රණය කරන්නේ ඇයි?


1775

පහත මුද්‍රණ ප්‍රකාශය "හෙලෝ වර්ල්ඩ්" මුද්‍රණය කරයි. කිසිවෙකුට මෙය පැහැදිලි කළ හැකිද?

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
හොඳයි, එම බීජ පරිපූර්ණ ලෙස ක්‍රියාත්මක වේ. අහඹු ලෙස සැබවින්ම අහඹු නොවේ, එය ව්‍යාජ ය.
tckmn

341
අනෙක් අය පැවසූ පරිදි එය ක්‍රියාත්මක වන්නේ අහඹු නොවන නිසාය. මට නම් වඩාත් සිත්ගන්නාසුලු ප්‍රශ්නයක් වනු ඇත්තේ එය ලියූ පුද්ගලයා තිරිසන් ලෙස බල කිරීම හෝ දී ඇති බීජයක් සඳහා ඊළඟ එන් අගයන් සඳහා අහඹු ලෙස ජනනය කරන්නේ කුමක්ද යන්න අනාවැකි කීමට පහසු ක්‍රමයක් තිබේද යන්නයි. තිරිසන් බල කිරීම පහසු වන අතර නවීන දෘඩාංග සමඟ වැඩි කාලයක් ගත නොවිය යුතුය, එබැවින් එය කළ හැකි ශක්‍ය ක්‍රමයක් විය. එය ස්ථිතික බැවින් ඔබට සෙවුමක් පහසුවෙන් ජාලයක් හරහා බෙදා හැරිය හැක.
jmoreno

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
පීටර් ලෝරි

Answers:


918

java.util.Randomනිශ්චිත බීජ පරාමිතියක් සමඟ නිදසුනක් සාදන විට (මෙම අවස්ථාවේදී -229985452හෝ -147909649), එය එම බීජ අගයෙන් ආරම්භ වන අහඹු සංඛ්‍යා උත්පාදන ඇල්ගොරිතම අනුගමනය කරයි .

සෑම Randomඑම බීජ සංඛ්යා එම රටාව සෑම කාල ජනනය වනු ඇත ඉදි.


8
Ul වුල්කන් - javadoc පවසන්නේ බීජ බිටු 48 ක් බවයි. docs.oracle.com/javase/7/docs/api/java/util/Random.html . ඊට අමතරව, නියම බීජ බිට් 32 අගයන් වේ.
ස්ටීවන් සී

80
සසම්භාවී සංඛ්‍යා අනුක්‍රමයේ සෑම මූලද්‍රව්‍යයක්ම මොඩියුලෝ 27 ලෙස ගනු ලබන අතර, එක් එක් "hello\0"සහ මූලද්‍රව්‍ය 6 ක් ඇත "world\0". ඔබ සැබවින්ම අහඹු උත්පාදක යන්ත්‍රයක් යැයි උපකල්පනය කරන්නේ නම්, ඔබ සොයන අනුක්‍රමය ලබා ගැනීමේ අවාසිය 27 ^ 6 (387,420,489) න් 1 ක් වනු ඇත - එබැවින් එය සිත් ඇදගන්නා සුළු නමුත් මනස අවුල් කරවනසුලු නොවේ!
රසල් බොරොගෝව්

18
Us රුසෙල්බොරොගෝව්: නමුත් එම අන්තරායන් හා හැකි බීජ 2 ^ 64 සමඟ, බීජ අගයන් බිලියන 47.6 ක් අපේක්ෂා කරයි. එය එකක් සොයා ගැනීමේ කාරණයක් පමණි.
dan04

8
0 dan04 - එම ඇස්තමේන්තුව ඉදිරිපත් කිරීමට මම එතරම් කැමැත්තක් දැක්වූයේ නැත; පීආර්එන්ජී ක්‍රියාත්මක කිරීම මත පදනම්ව, බීජ වචනයේ ප්‍රමාණය රාජ්‍යයේ ප්‍රමාණයට සමාන නොවිය හැකි අතර අනුක්‍රමික මාර්ග ඒකාකාරව බෙදා හරිනු නොලැබේ. නමුත් තවමත්, අවාසි නිසැකවම හොඳයි, ඔබට යුගලයක් සොයාගත නොහැකි නම් ඔබට විවිධ ආවරණ ( "Hello" "World") සමඟ නැවත උත්සාහ කළ හැකිය , නැතහොත් 122-kඒ වෙනුවට භාවිතා කළ හැකිය 96+k, හෝ ...
රසල් බොරොගෝව්

8
Or ThorbjørnRavnAndersen ජාවාඩොක් විසින් "අහඹු පංතිය සඳහා විශේෂිත ඇල්ගොරිතම නියම කර ඇත. ජාවා ක්‍රියාත්මක කිරීම ජාවා කේතයේ නිරපේක්ෂ අතේ ගෙන යා හැකි පහසුව සඳහා, අහඹු පංතිය සඳහා මෙහි පෙන්වා ඇති සියලුම ඇල්ගොරිතම භාවිතා කළ යුතුය."
FThompson

1139

අනෙක් පිළිතුරු එයට හේතුව පැහැදිලි කරයි, නමුත් මෙන්න කෙසේද.

උදාහරණයක් ලෙස 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
Pedantically, new Random(-229985452).nextInt(27)සෑම විටම 8 ආපසු එයි.
user253751

1
ඇයි ඉමිබිස්? මම අදහස් කළේ සසම්භාවී () සෑම විටම අහඹු අංකය ලබා දිය යුතු අතර, නිවැරදි කරන ලද ඇණවුම් අංකයක් නොවේද?
roottraveller

5
@rootTraveller ආරම්භයක් සඳහා, new Random()කිසිසේත් අංකයක් ලබා නොදේ.
user253751

2
මෙම බීජ ගණනය කිරීමට ක්‍රමයක් තිබේද? යම් තර්කනයක් තිබිය යුතුය ... නැතහොත් එය තිරිසන් බලවේගයක්ද?
සොහිත් ගෝර්

2
O සෝහිත්ගෝර් ජාවා හි පෙරනිමිය Randomගුප්ත විද්‍යාත්මකව ආරක්ෂිත නොවන බව සලකන විට (එය මර්සෙන් ට්විටර් බව මට විශ්වාසයි, නමුත් ඒ ගැන මා උපුටා දක්වන්න එපා), බොහෝ විට "මට මෙම සංඛ්‍යා අවශ්‍යයි" සිට "මෙයයි" බීජ මම භාවිතා කරමි ". මම සම්මත සී රේඛීය සංයුක්ත උත්පාදක යන්ත්‍රයට සමාන දෙයක් කර ඇත්තෙමි.
අරමුදල් මොනිකාගේ නඩුව

281

මම ඒක මෙතන දාලා යන්නම්. කාටවත් (CPU) වැඩි කාලයක් ඉතිරිව තිබේ නම්, අත්හදා බැලීමට නිදහස්ව සිටින්න :) එසේම, ඔබ මේ කාරණය සියලු CPU හරයන් පුළුස්සා දැමීම සඳහා දෙබලක සම්බන්ධ වීමක් ප්‍රගුණ කර ඇත්නම් (නූල් නීරස ය, හරිද?), කරුණාකර බෙදා ගන්න ඔබේ කේතය. මම එය බෙහෙවින් අගය කරමි.

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
OneOneTwoThree nextInt(27)යන්නෙන් අදහස් වන්නේ පරාසය තුළය [0, 26].
Eng.Fouad

30
Ul වුල්කන් බොහෝ බීජ උපරිම අගයට ඉතා ආසන්නයි, ඔබ 1 ත් 1000 ත් අතර අහඹු සංඛ්‍යා තෝරා ගත්තොත්, ඔබ තෝරා ගන්නා බොහෝ සංඛ්‍යා වලට ඉලක්කම් තුනක් ඇත. ඔබ ඒ ගැන සිතන විට එය පුදුමයක් නොවේ :)
තෝමස්

18
Ul වුල්කන් ඇත්ත වශයෙන්ම ඔබ ගණිතය කළහොත් ඒවා ශුන්‍යයට වඩා උපරිම අගයට ආසන්න බව ඔබට පෙනෙනු ඇත (බීජ පරම්පරා කේතයේ අත්සන් නොකළ අයෙකු ලෙස අර්ථකථනය කරනු ඇතැයි මම සිතමි). නමුත් ඉලක්කම් ගණන සත්‍ය අගය සමඟ ල ar ු ගණකයෙන් පමණක් වර්ධනය වන හෙයින්, එය ඇත්ත වශයෙන්ම නොමැති විට එම සංඛ්‍යාව සැබවින්ම සමීපව පෙනේ.
තෝමස්

10
නියම පිළිතුර. ප්‍රසාද ලකුණු සඳහා, අවසාන අහඹු ලෙස ආරම්භ කිරීම සඳහා අවශ්‍ය බීජ 4 ක අනුක්‍රමය නිපදවන අහඹු ලෙස ආරම්භ කරන බීජයක් ඔබට සොයාගත හැකිද?
මාරෙක්

13
@ මාරෙක්: ව්‍යාජ අහඹු දෙවිවරුන් එවැනි හැසිරීම් අනුමත කරනු ඇතැයි මම නොසිතමි.
ඩෙනිස් ටල්ස්කි

254

මෙහි සිටින සෑම කෙනෙක්ම කේතය ක්‍රියාත්මක වන ආකාරය පැහැදිලි කිරීම සහ ඔබේම උදාහරණ ගොඩනඟා ගත හැකි ආකාරය පෙන්වීම සඳහා විශාල කාර්යයක් ඉටු කළහ, නමුත් මෙන්න තොරතුරු න්‍යායාත්මක පිළිතුරක් වන්නේ තිරිසන් බල සෙවීම අවසානයේදී සොයාගත හැකි විසඳුමක් පවතිනු ඇතැයි අපට සාධාරණ ලෙස අපේක්ෂා කළ හැක්කේ මන්ද යන්නයි.

විවිධ කුඩා අකුරු 26 අපගේ හෝඩිය සාදයි Σ. විවිධ දිගින් යුත් වචන උත්පාදනය කිරීමට ඉඩ දීම සඳහා, අපි දිගින් දිගට හෝඩියක් ලබා දීම සඳහා ටර්මිනේටර් සංකේතයක් එකතු කරමු Σ' := Σ ∪ {⊥}.

αසංකේතයක් සහ X ඒකාකාරව බෙදා හරින අහඹු විචල්‍යයක් වේවා Σ'. එම සංකේතය ලබා ගැනීමේ සම්භාවිතාව P(X = α)සහ එහි තොරතුරු අන්තර්ගතය I(α)පහත පරිදි වේ:

පී (X = α) = 1 / | Σ '| = 1/27

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

වචනයක් ω ∈ Σ*සහ එහි ⊥-අවසන් වූ ප්‍රතිවිරුද්ධ පාර්ශවය සඳහා ω' := ω · ⊥ ∈ (Σ')*, අපට තිබේ

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

ව්‍යාජ සංඛ්‍යා උත්පාදක යන්ත්රය (පීආර්එන්ජී) බිට් 32 බීජයකින් ආරම්භ කර ඇති හෙයින්, අපට බොහෝ වචන බලාපොරොත්තු විය හැකිය

Floor = මහල [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


මගේ තොරතුරු න්‍යාය යම් ආකාරයක දුර්වල නමුත් මම මෙම සාක්ෂියට කැමතියි. යමෙකුට ලැම්බඩා රේඛාව මට පැහැදිලි කළ හැකිද, පැහැදිලිවම අපි එකක තොරතුරු අන්තර්ගතය අනෙකා සමඟ බෙදා ගනිමු, නමුත් මෙය අපගේ වචන දිග ලබා දෙන්නේ ඇයි? මම පැහැදිලි ඉල්ලා සඳහා ටිකක් කොළ එසේ සමාව ඉල්ලා (සැ.යු එය ෂැනොන් සීමාව -from කේතය ප්රතිදානය යමක් මිල) ඉන්නේ කී පරිදි
මයික් මානව සම්පත්

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.


36

මට මේ ගැන කුතුහලයක් ඇති විය, මම මෙම අහඹු වචන උත්පාදක යන්ත්රය ශබ්ද කෝෂ වචන ලැයිස්තුවක් මත ධාවනය කළෙමි. පරාසය: Integer.MIN_VALUE සිට Integer.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 පීටර් -4611686018403334185 පීටර් -9223372036830722089 පීටර් -461168601790624887762089696 4611686017645756173 පීටර් 781631731 පීටර් 4611686019209019635 පීටර් -9223372036073144077 පීටර් -4611686017420317288 පීටර් 1007070616 පීටර් -9223372035847705192)
මාර්සෙල්

25

බොහෝ අහඹු සංඛ්‍යා උත්පාදක යන්ත්‍ර ඇත්ත වශයෙන්ම "ව්‍යාජ අහඹු" වේ. ඒවා රේඛීය සංයුක්ත ජනක යන්ත්‍ර හෝ LCGs ( http://en.wikipedia.org/wiki/Linear_congruential_generator )

ස්ථාවර බීජයක් ලබා දෙන විට LCGs තරමක් පුරෝකථනය කළ හැකිය. මූලික වශයෙන්, ඔබේ පළමු ලිපිය ලබා දෙන බීජයක් භාවිතා කරන්න, ඉන්පසු ඔබේ ඉලක්කගත නූලෙහි ඊළඟ අකුරට පහර දෙන තෙක් ඊළඟ int (char) ජනනය කරන යෙදුමක් ලියන්න සහ ඔබට LCG ආයාචනා කිරීමට කී වතාවක් ලියා ඇත්දැයි ලියන්න. ඔබ සෑම අකුරක්ම ජනනය කරන තෙක් ඉදිරියට යන්න.


3
ව්‍යාජ නොවන සසම්භාවී සංඛ්‍යා උත්පාදක යන්ත්‍රයක
උදාහරණය කුමක්ද

1
generachiliNUT එවැනි ජනක යන්ත්‍ර බාහිර උපකරණ වේ. සමහර විද්‍යුත් ලාම්පු. 0 හෝ 1 කියවන ලද නරක ලෙස ලියා ඇති බිට් ඔබට අහඹු සංඛ්‍යා වල පිරිසිදු ඩිජිටල් උත්පාදක යන්ත්‍රයක් කළ නොහැක, ඩිජිටල් ඇල්ගොරිතම අහඹු නොවේ, ඒවා නිරවද්‍ය ය.
ගන්ග්නස්

ilichiliNUT බොහෝ මෙහෙයුම් පද්ධති එන්ට්‍රොපිය එකතු කරයි. උදා: ලිනක්ස් හි ඔබට /dev/urandomඅහඹු දත්ත කියවීමට උපාංගය භාවිතා කළ හැකිය . කෙසේ වෙතත් මෙය හිඟ සම්පතකි. එබැවින්, එවැනි අහඹු දත්ත සාමාන්‍යයෙන් PRNGs බීජ සඳහා යොදා ගනී.
ඒඩ්‍රියන් ඩබ්ලිව්

D ඒඩ්‍රියන් ඩබ්ලිව් විකිපීඩියාව පවසන්නේ urandomතවමත් ව්‍යාජ අහඹු en.wikipedia.org/wiki//dev/random
chiliNUT

1
ඔව්, නමුත් එය ගුප්ත විද්‍යාත්මකව ආරක්ෂිතයි, එයින් අදහස් කරන්නේ අහඹු අනුපිළිවෙලින් නිර්මාණය කළ කෙනෙකුට තිරිසන් බලවේග ප්‍රහාර එල්ල කළ නොහැකි බවයි (“අහඹු” අනුක්‍රමය “හෙලෝ වර්ල්ඩ්” සඳහා බීජය සොයා ගැනීමට වැනි) /dev/random. මා ඉහත සඳහන් කළ ලිපියේ සඳහන් වන්නේ ලිනක්ස් කර්නලය යතුරුපුවරු වේලාවන්, මූසික චලනයන් සහ IDE වේලාවන්ගෙන් එන්ට්‍රොපිය ජනනය කරන අතර අහඹු අක්ෂර දත්ත වෙනත් මෙහෙයුම් පද්ධති ක්‍රියාවලීන් සඳහා විශේෂ ලිපිගොනු / dev / random සහ / dev / urandom හරහා ලබා ගත හැකි බවයි. එය මට අහඹු ලෙස විශ්වාස කිරීමට ඉඩ දෙයි. එය සම්පූර්ණයෙන්ම නිවැරදි නොවිය හැකිය. නමුත් /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

සසම්භාවී සෑම විටම එකම අනුක්රමය නැවත ලබා දෙයි. එය ප්‍රේරක ලෙස අරා සහ වෙනත් මෙහෙයුම් මාරු කිරීම සඳහා භාවිතා කරයි.

විවිධ අනුක්‍රම ලබා ගැනීම සඳහා, “බීජ” ලෙස හැඳින්වෙන අනුපිළිවෙල යම් ස්ථානයක ආරම්භ කිරීම අවශ්‍ය වේ.

සසම්භාවී ස්තරයට "අහඹු" අනුක්‍රමයේ i ස්ථානයේ (බීජ = -229985452) අහඹු අංකය ලැබේ. මෙම අගය 0 ට සමාන වන තෙක් බීජ පිහිටීමෙන් පසු අනුපිළිවෙලෙහි ඊළඟ අක්ෂර 27 සඳහා ASCII කේතය භාවිතා කරන්න. මෙය "හෙලෝ" ආපසු එවන්න. එකම මෙහෙයුම "ලෝකය" සඳහා සිදු කෙරේ.

කේතය වෙනත් වචන සඳහා ක්‍රියා නොකළ බව මම සිතමි. ක්‍රමලේඛනය කළ පුද්ගලයා අහඹු අනුක්‍රමය හොඳින් දනී.

එය ඉතා හොඳ ගීක් කේතයකි!


10
ඔහු "අහඹු අනුක්‍රමය හොඳින් දනී" දැයි මට සැකයි. වැඩියෙන් සොයා ගන්නා තෙක් ඔහු බීජ බිලියන ගණනක් උත්සාහ කළේය.
dan04

24
program 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 ). වත්මන් ක්‍රියාත්මක කිරීමේදී මෙය වර්තමාන කාලය හා කවුන්ටරයේ එකතුවකි.
මාර්ටින්

ඇත්ත වශයෙන්ම. ආරම්භක බීජ අගය නියම කිරීම සඳහා ප්‍රායෝගික භාවිත අවස්ථා තිබේ. මම හිතන්නේ ඔබට ලබා ගත හැකි ව්‍යාජ යතුරුපුවරුවල (RSA
ඒවාද

4
ed 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

ඒ සියල්ල ආදාන බීජ ගැන ය . එකම බීජ සෑම විටම එකම ප්රති results ල ලබා දෙයි. ඔබ පවා ඔබේ වැඩසටහන නැවත නැවතත් ක්‍රියාත්මක කරන්නේ එය එකම ප්‍රතිදානයයි.

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.