0x5*_*94E 1733 java string random
以下print语句将打印"hello world".有人能解释一下吗?
System.out.println(randomString(-229985452) + " " + randomString(-147909649));
Run Code Online (Sandbox Code Playgroud)
而且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();
}
Run Code Online (Sandbox Code Playgroud)
Eng*_*uad 1126
其他答案解释了原因,但这里是如何.
给出一个例子Random:
Random r = new Random(-229985452)
Run Code Online (Sandbox Code Playgroud)
r.nextInt(27)生成的前6个数字是:
8
5
12
12
15
0
Run Code Online (Sandbox Code Playgroud)
并且r.nextInt(27)生成给定的前6个数字Random r = new Random(-147909649)是:
23
15
18
12
4
0
Run Code Online (Sandbox Code Playgroud)
然后只需将这些数字添加到字符的整数表示`(即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
Run Code Online (Sandbox Code Playgroud)
FTh*_*son 904
当java.util.Random使用特定种子参数(在这种情况下-229985452或-147909649)构造实例时,它遵循以该种子值开始的随机数生成算法.
每个Random使用相同种子构建的每个都将每次生成相同的数字模式.
Den*_*kiy 276
我会把它留在这里.谁有很多(CPU)的时间,请随意尝试:)另外,如果你已经掌握了一些fork-join-fu来使这个东西烧掉所有的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();
}
Run Code Online (Sandbox Code Playgroud)
输出:
-9223372036808280701
Using base: 'Z'
stack
-9223372036853943469
Using base: 'b'
over
-9223372036852834412
Using base: 'e'
flow
-9223372036838149518
Using base: 'd'
rulez
Took 7087 ms
Run Code Online (Sandbox Code Playgroud)
xDD*_*xDD 253
这里的每个人都很好地解释了代码是如何工作的,并展示了如何构建自己的示例,但这里有一个信息理论答案,说明为什么我们可以合理地期望蛮力搜索最终会找到解决方案.
26个不同的小写字母构成了我们的字母表?.为了生成不同长度的单词,我们进一步添加终止符号?以产生扩展字母表?' := ? ? {?}.
我们?是一个符号和X均匀分布的随机变量了?'.获得该符号P(X = ?)及其信息内容的概率I(?)由下式给出:
P(X =α)= 1/|Σ'| = 1/27
I(α)= -log 2 [P(X =α)] = -log 2(1/27)= log 2(27)
对于一个词? ? ?*及其?-终止的对应词?' := ? · ? ? (?')*,我们有
I(ω):= I(ω')= |ω'|*log 2(27)=(|ω| + 1)*log 2(27)
由于伪随机数发生器(PRNG)是用32位种子初始化的,我们可以期待大多数单词的长度达到
λ= floor [32/log 2(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;
}
}
Run Code Online (Sandbox Code Playgroud)
请参阅输出:http://ideone.com/JRGb3l
Ilm*_*nen 66
我写了一个快速程序来找到这些种子:
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);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我现在在后台运行它,但它已经找到了足够的经典pangram字:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
PS.-727295876, -128911, -1611659, -235516779.
Pur*_*u-- 35
我对此很感兴趣,我在字典单词列表上运行了这个随机单词生成器.范围: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) + " ");
}
Run Code Online (Sandbox Code Playgroud)
打印
the quick browny fox jumps over a lazy dog
Run Code Online (Sandbox Code Playgroud)
小智 25
事实上,大多数随机数生成器都是"伪随机数".它们是线性同余生成器或LCG(http://en.wikipedia.org/wiki/Linear_congruential_generator)
鉴于固定种子,LCG是可预测的.基本上,使用为您提供第一个字母的种子,然后编写一个继续生成下一个int(char)的应用程序,直到您点击目标字符串中的下一个字母并记下您必须调用LCG的次数.继续,直到你生成每一个字母.
Two*_*The 23
由于使用Java可以轻松实现多线程,因此以下是使用所有可用内核搜索种子的变体: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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
Arn*_*jar 21
随机总是返回相同的序列.它用于改组数组和其他操作作为排列.
要获得不同的序列,必须在某个位置初始化序列,称为"种子".
randomSting获得"随机"序列的i位置(seed = -229985452)中的随机数.然后在种子位置之后的序列中使用ASCII代码作为接下来的27个字符,直到此值等于0.这将返回"hello".对"世界"进行相同的操作.
我认为代码不适用于任何其他单词.编程的人非常了解随机序列.
这是非常棒的极客代码!
sul*_*lai 12
根据Denis Tulskiy的回答,这种方法可以生成种子.
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 :/");
}
Run Code Online (Sandbox Code Playgroud)
dee*_*392 10
从Java文档中,在为Random类指定种子值时,这是一个有意的功能.
如果使用相同的种子创建两个Random实例,并且对每个实例都进行相同的方法调用序列,则它们将生成并返回相同的数字序列.为了保证此属性,为Random类指定了特定的算法.为了Java代码的绝对可移植性,Java实现必须使用此处显示的所有算法用于Random类.
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html
但奇怪的是,你会认为有可预测的"随机"数字存在隐含的安全问题.
这是 Denis 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 :/");
}
Run Code Online (Sandbox Code Playgroud)