Code Golf:MSM 随机数生成器

发布于 2024-08-30 05:58:54 字数 2512 浏览 11 评论 0原文

挑战:

按字符数计算的最短代码将使用 中方法

(伪)随机数生成的中方法由 John Von Neumann 于 1946 年首次提出,定义如下:

Rn+1 = mid ((Rn)2, m)

例如:

34562 = 11943936

中(11943936) = 9439

94392 = 89094721

中(89094721) = 0947

9472 = 896809

中(896809) = 9680

96802 = 93702400

中(93702400) = 7024

另一个例子:

8432 = 710649

中(710649)= 106

1062 = 11236

中(11236)= 123

1232 = 15129

中(15129) = 512

5122 = 262144

中(262144) = 621

6212 = 385641

中(385641)= 856

8562 = 732736

中(732736) = 327

3272 = 106929

中(106929) = 069

692 = 4761

中(4761)= 476

4762 = 226576

中(226576) = 265

mid 的定义:

显然对于 mid 的确切定义存在一些混乱。出于本次挑战的目的,假设您正在提取与起始种子相同数量的数字。这意味着,如果起始种子有 4 位数字,您将从中间提取 4 位数字。如果起始种子有 3 位数字,您将从中间提取 3 位数字

关于在无法找到精确中间位置时提取数字的问题,请考虑数字710649。如果要提取中间的 3,则存在一些歧义(106064)。在这种情况下,提取最接近字符串开头的 3。因此,在本例中,您将提取 106

一种简单的思考方法是,如果数字位数不正确,则在数字中填充零。例如,如果将前导零填充到 710649,则会得到 0710649,中间的 3 位数字现在变为 106

测试用例:

不对种子的长度做出任何假设。例如,您不能假设种子始终是 4 位数字

生成 4 位随机数的起始种子 3456 应生成以下序列(前 10 个):

9439、947、9680、7024、3365、3232、4458、8737、3351、2292

生成 4 位随机数的起始种子 8653 应生成以下序列(前 10 个):

8744、4575、9306、6016、1922、6940、1636、6764、7516、4902

生成 3 位随机数的 843 起始种子应生成以下序列(前 10 个):

106、123、512、621、856、327、69、476、265、22

生成 5 位随机数的起始种子 45678 应生成以下序列(前 10 个):

86479、78617、80632、1519、30736、47016、10504、3340、11556、35411

就前导零而言,答案是不应显示前导零:)。

The challenge:

The shortest code by character count that will generate a series of (pseudo)random numbers using the Middle-Square Method.

The Middle-Square Method of (pseudo)random number generation was first suggested by John Von Neumann in 1946 and is defined as follows:

Rn+1 = mid((Rn)2, m)

For example:

34562 = 11943936

mid(11943936) = 9439

94392 = 89094721

mid(89094721) = 0947

9472 = 896809

mid(896809) = 9680

96802 = 93702400

mid(93702400) = 7024

Another example:

8432 = 710649

mid(710649) = 106

1062 = 11236

mid(11236) = 123

1232 = 15129

mid(15129) = 512

5122 = 262144

mid(262144) = 621

6212 = 385641

mid(385641) = 856

8562 = 732736

mid(732736) = 327

3272 = 106929

mid(106929) = 069

692 = 4761

mid(4761) = 476

4762 = 226576

mid(226576) = 265

Definition of mid:

Apparently there is some confusion regarding the exact definition of mid. For the purposes of this challenge, assume that you are extracting the same number of digits as the starting seed. Meaning, if the starting seed had 4 digits, you would extract 4 digits from the middle. If the starting seed had 3 digits, you would extract 3 digits from the middle.

Regarding the extraction of numbers when you can't find the exact middle, consider the number 710649. If you want to extract the middle 3, there is some ambiguity (106 or 064). In that case, extract the 3 that is closest to the beginning of the string. So in this case, you would extract 106.

An easy way to think of it is to pad zeroes to the number if it's not the right number of digits. For example, if you pad leading-zeroes to 710649 you get 0710649 and the middle 3 digits now become 106.

Test cases:

Make no assumptions regarding the length of the seed. For example, you cannot assume that the seed will always be 4-digit number

A starting seed of 3456 that generates 4-digit random-numbers should generate the following series (first 10):

9439, 947, 9680, 7024, 3365, 3232, 4458, 8737, 3351, 2292

A starting seed of 8653 that generates 4-digit random numbers should generate the following series (first 10):

8744, 4575, 9306, 6016, 1922, 6940, 1636, 6764, 7516, 4902

A starting seed of 843 that generates 3-digit random numbers should generate the following series (first 10):

106, 123, 512, 621, 856, 327, 69, 476, 265, 22

A starting seed of 45678 that generates 5-digit ranom numbers should generate the following series (first 10):

86479, 78617, 80632, 1519, 30736, 47016, 10504, 3340, 11556, 35411

As far as leading zeroes are concerned, the answer is no leading zeroes should be displayed :).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

桃酥萝莉 2024-09-06 05:58:55

Google 文档 - 电子表格:42 个字符

=MID(C2^2,LEN(C2^2)/2-LEN(C2)/2+1,LEN(C2))

用法:

  • 将初始种子放入单元格 C2 中,然后拖动所有序列的公式。

测试用例:

屏幕截图:

Code Golf:MSM 随机数生成器 http://img59.imageshack.us/ img59/6830/golfo.png

限制:

  • 此公式保留前导零,但可以使用另一列并对结果应用 INT() 来修剪它们。

Google Docs - Spreadsheet: 42 chars

=MID(C2^2,LEN(C2^2)/2-LEN(C2)/2+1,LEN(C2))

Usage:

  • Put the initial seed in cell C2, and drag the formula for all the sequence.

Test Cases:

Screenshot:

Code Golf: MSM Random Number Generator http://img59.imageshack.us/img59/6830/golfo.png

Limitations:

  • This formula preserves leading zeros, but they could be trimmed using another column and applying INT() on the results.
迷爱 2024-09-06 05:58:55

dc 26/37 chars

26 chars 单个数字的函数:

?dZsl2^dZ1+ll-2/Ar^/All^%p

37 chars 10 个循环循环:

?dZsl[2^dZ1+ll-2/Ar^/All^%pdzB>L]dsLx

函数说明:

?            Input n
dZ           calculate number of digits
sl           store in register l
2^           calculate n^2
dZ           calculate number of digits of square
1+ll-2/Ar^/  n/(10^((squaredigits+1-l)/2)) int division truncates last digits 
All^%        n%(10^l) modulus truncates first digits
p            print the number

测试:

dc msml.dc
45678
86479
78617
80632
1519
30736
47016
10504
3340
11556
35411

dc 26/37 chars

26 chars the function for a single number:

?dZsl2^dZ1+ll-2/Ar^/All^%p

37 chars with a 10 cycles loop:

?dZsl[2^dZ1+ll-2/Ar^/All^%pdzB>L]dsLx

Explanation of the function:

?            Input n
dZ           calculate number of digits
sl           store in register l
2^           calculate n^2
dZ           calculate number of digits of square
1+ll-2/Ar^/  n/(10^((squaredigits+1-l)/2)) int division truncates last digits 
All^%        n%(10^l) modulus truncates first digits
p            print the number

Test:

dc msml.dc
45678
86479
78617
80632
1519
30736
47016
10504
3340
11556
35411
青萝楚歌 2024-09-06 05:58:55

Python(86 个字符)

r=input()
l=len(str(r))
while 1:
 x=str(r*r)
 y=(len(x)-l)/2
 r=int(x[y:y+l])
 print r

在标准输出上生成无限序列。请注意,反引号技巧至少在 long 类型的旧版本上不起作用,因为表示形式中以 L 结尾。 Python 3 print 作为函数会添加 1 个以上的字符来结束括号。

Python (86 chars)

r=input()
l=len(str(r))
while 1:
 x=str(r*r)
 y=(len(x)-l)/2
 r=int(x[y:y+l])
 print r

Produces infinite sequence on stdout. Note that backtick trick won't work at least on older versions with long type because of the ending L in representation. Python 3 print as function would add 1 more char for closing paren.

中二柚 2024-09-06 05:58:55

C#(96 81 79 85 84 个字符)

更改日志

  • 已添加Yuliy 对 81 的建议
  • 删除了 79 的额外括号。
  • 增加计数,因为我最初没有计算必要的空格(仅字符)。
  • 根据 Camerons 的建议,将 1.0 替换为 1d。

我的代码:

    int F(int s, int l)
    {
        var r = "" + 1d*s*s;

        return int.Parse(r.Substring((r.Length - l) / 2, l));
    }

使用示例:

    int s = 8653;
    int l = 4;
    for(int i = 0; i< 10; i++)
    {
        s = F(s, l);
        Console.WriteLine(s);
    }

结果

---8653---
8744
4575
9306
6016
1922
6940
1636
6764
7516
4902

---843---
106
123
512
621
856
327
69
476
265
22

---45678---
86479
78617
80632
1519
30736
47016
10504
3340
11556
35411

C# (96 81 79 85 84 chars)

Change log

  • Added Yuliy's suggestion for 81
  • Removed extra brackets for 79.
  • Incremented count because I did not initially count the necessary spaces (only chars).
  • Replacing 1.0 by 1d as per Camerons suggestion.

My Code:

    int F(int s, int l)
    {
        var r = "" + 1d*s*s;

        return int.Parse(r.Substring((r.Length - l) / 2, l));
    }

Usage Example:

    int s = 8653;
    int l = 4;
    for(int i = 0; i< 10; i++)
    {
        s = F(s, l);
        Console.WriteLine(s);
    }

Results

---8653---
8744
4575
9306
6016
1922
6940
1636
6764
7516
4902

---843---
106
123
512
621
856
327
69
476
265
22

---45678---
86479
78617
80632
1519
30736
47016
10504
3340
11556
35411
笑着哭最痛 2024-09-06 05:58:55

Perl (102 96 95 93 92 79 个字符)

$s =$_;$d=长度$s;map{$s*=$s;print 0+($s=substr$s,($s=~y///c-$d)/2,$d ),$/}0..9

echo -n 3456 | perl -ne '$s=$_;$d=length$s;map{$s*=$s;print 0+($s=substr$s,($s=~y///c-$d)/2,$d),$/}0..9'
9439
947
9680
7024
3365
3232
4458
8737
3351
2292

Perl (102 96 95 93 92 79 chars)

$s=$_;$d=length$s;map{$s*=$s;print 0+($s=substr$s,($s=~y///c-$d)/2,$d),$/}0..9

echo -n 3456 | perl -ne '$s=$_;$d=length$s;map{$s*=$s;print 0+($s=substr$s,($s=~y///c-$d)/2,$d),$/}0..9'
9439
947
9680
7024
3365
3232
4458
8737
3351
2292
怎言笑 2024-09-06 05:58:55

Groovy -

s=args[0]as int;def r(){f=s*s;g=f as String;t=g.size()/2;g=g[t-2..t+1];s=g as int}

使用第一个参数作为种子的 82 个字符,并由 4 个 base10 数字组成的输出,如您的示例中所示。

Groovy - 82 chars

s=args[0]as int;def r(){f=s*s;g=f as String;t=g.size()/2;g=g[t-2..t+1];s=g as int}

using first argument as seed and output made by 4 base10 digits like in your examples..

滿滿的愛 2024-09-06 05:58:55

Perl,80 个字符

(来自命令行)

$n=pop;$l=length$n;map{$n*=$n;print 0+($n=substr$n,(length($n)-$l)/2,$l),$/}0..9

Perl, 80 chars

(from commandline)

$n=pop;$l=length$n;map{$n*=$n;print 0+($n=substr$n,(length($n)-$l)/2,$l),$/}0..9
谎言 2024-09-06 05:58:55

Ruby,85 76 69 个字符(生成并打印 10 个数字)

n=gets
l=n.size
10.times{n=n.to_i;x=(n*n).to_s;p n=x[(x.size-l)/2,l]}

从标准输入读取。

输出

> ruby rand.rb < 3456
9439
947
9680
7024
3365
3232
4458
8737
3351
2292

> ruby rand.rb < 8653
8744
4575
9306
6016
1922
6940
1636
6764
7516
4902

> ruby rand.rb < 843
106
123
512
621
856
327
69
476
265
22

> ruby rand.rb < 45678
86479
78617
80632
1519
30736
47016
10504
3340
11556
35411

Ruby, 85 76 69 chars (generates and prints 10 numbers)

n=gets
l=n.size
10.times{n=n.to_i;x=(n*n).to_s;p n=x[(x.size-l)/2,l]}

Reads from standard input.

Output

> ruby rand.rb < 3456
9439
947
9680
7024
3365
3232
4458
8737
3351
2292

> ruby rand.rb < 8653
8744
4575
9306
6016
1922
6940
1636
6764
7516
4902

> ruby rand.rb < 843
106
123
512
621
856
327
69
476
265
22

> ruby rand.rb < 45678
86479
78617
80632
1519
30736
47016
10504
3340
11556
35411
风柔一江水 2024-09-06 05:58:55

JavaScript:91 个字符

function a(s,n){m=(s+'').length;while(n--)c=''+s*s,s=1*c.substr((c.length-m)/2,m);return s}

用法:

a(3456, 4);     // 4th seed of 3456:   Returns: 7024
a(8653, 2);     // 2nd seed of 8653:   Returns: 4575
a(843, 10);     // 10th seed of 843:   Returns: 22
a(45678, 6);    // 6th seed of 45678:  Returns: 47016

完整测试用例:

var tests = [3456, 8653, 843, 45678];

for (var i = 0; i < tests.length; i++) {
   console.log('-------------');
   console.log('| Seed: ' + tests[i]);
   console.log('-------------');

   for(var j = 1; j <= 10; j++) {
      console.log('| ' +  a(tests[i], j));
   }

   console.log('~~~~~~~~~~~~~');
}

测试结果:

-------------         -------------
| Seed: 3456          | Seed: 8653
-------------         -------------
| 9439                | 8744
| 947                 | 4575
| 9680                | 9306
| 7024                | 6016
| 3365                | 1922
| 3232                | 6940
| 4458                | 1636
| 8737                | 6764
| 3351                | 7516
| 2292                | 4902
~~~~~~~~~~~~~         ~~~~~~~~~~~~~

-------------         -------------
| Seed: 843           | Seed: 45678
-------------         -------------
| 106                 | 86479
| 123                 | 78617
| 512                 | 80632
| 621                 | 1519
| 856                 | 30736
| 327                 | 47016
| 69                  | 10504
| 476                 | 3340
| 265                 | 11556
| 22                  | 35411
~~~~~~~~~~~~~         ~~~~~~~~~~~~~

JavaScript: 91 characters

function a(s,n){m=(s+'').length;while(n--)c=''+s*s,s=1*c.substr((c.length-m)/2,m);return s}

Usage:

a(3456, 4);     // 4th seed of 3456:   Returns: 7024
a(8653, 2);     // 2nd seed of 8653:   Returns: 4575
a(843, 10);     // 10th seed of 843:   Returns: 22
a(45678, 6);    // 6th seed of 45678:  Returns: 47016

Full Test Cases:

var tests = [3456, 8653, 843, 45678];

for (var i = 0; i < tests.length; i++) {
   console.log('-------------');
   console.log('| Seed: ' + tests[i]);
   console.log('-------------');

   for(var j = 1; j <= 10; j++) {
      console.log('| ' +  a(tests[i], j));
   }

   console.log('~~~~~~~~~~~~~');
}

Test Results:

-------------         -------------
| Seed: 3456          | Seed: 8653
-------------         -------------
| 9439                | 8744
| 947                 | 4575
| 9680                | 9306
| 7024                | 6016
| 3365                | 1922
| 3232                | 6940
| 4458                | 1636
| 8737                | 6764
| 3351                | 7516
| 2292                | 4902
~~~~~~~~~~~~~         ~~~~~~~~~~~~~

-------------         -------------
| Seed: 843           | Seed: 45678
-------------         -------------
| 106                 | 86479
| 123                 | 78617
| 512                 | 80632
| 621                 | 1519
| 856                 | 30736
| 327                 | 47016
| 69                  | 10504
| 476                 | 3340
| 265                 | 11556
| 22                  | 35411
~~~~~~~~~~~~~         ~~~~~~~~~~~~~
也只是曾经 2024-09-06 05:58:55

Haskell


注意:生成一个包含 MSM 随机数的无限列表。


函数,81

l=length
m k n=take k$drop(div(l n-k)2)n
r n=iterate(read.m(l$show n).show.(^2))n

用法示例:

r 34562

输出示例:

[34562,94531,36109,3859,48918,92970,...

程序,103

l=length
m k n=take k$drop(div(l n-k)2)n
r n=iterate(read.m(l$show n).show.(^2))n
main=readLn>>=print.r

Haskell


Note: An infinite list is produced containing MSM random numbers.


Function, 81

l=length
m k n=take k$drop(div(l n-k)2)n
r n=iterate(read.m(l$show n).show.(^2))n

Example usage:

r 34562

Example output:

[34562,94531,36109,3859,48918,92970,...

Program, 103

l=length
m k n=take k$drop(div(l n-k)2)n
r n=iterate(read.m(l$show n).show.(^2))n
main=readLn>>=print.r

绝不放开 2024-09-06 05:58:55

Haskell (97 99 chars)

可能仍然可以缩短。产生一个无限序列,或者至少遇到 0,在这种情况下它会崩溃。

i(f:l)x=x:i l(f x)
m n=head.filter((==n).length).i(cycle[init,tail])
b r n=n:b r(read$m r$show$n*n)

用法:b <数字长度>

*Main> b 5 45678
[45678,86479,78617,80632,1519,30736,47016,10504,3340,11556,35411...

解释

该程序不是应用子字符串并使用字符串长度算术,而是在删除最后一个字符 (init) 和删除第一个字符之间进行迭代(tail) 直到达到所需的长度。

正如迭代以及大多数 Haskell 函数一样,假设所使用的函数是常量。由于函数本身发生了变化,因此我们需要实现一个特殊版本的迭代。

Haskell (97 99 chars)

Can probably still be shortened. Produces an infinite sequence, or at least it encounters 0, in which case it crashes.

i(f:l)x=x:i l(f x)
m n=head.filter((==n).length).i(cycle[init,tail])
b r n=n:b r(read$m r$show$n*n)

Usage: b <length of number> <number>

*Main> b 5 45678
[45678,86479,78617,80632,1519,30736,47016,10504,3340,11556,35411...

Explanation

Rather than applying substring and using string length arithmetic, this program iterates between removing the last character (init), and removing the first character (tail) until the desired length is reached.

As iterate as well as most Haskell functions assume that the function used is constant. Since we have the function itself changing, we need to implement a special version of iterate.

稳稳的幸福 2024-09-06 05:58:55

Ruby(66 个字符)

假设整数输入:

def r s,l=s.to_s.size;x=(s*s).to_s;y=x.size;x[(y-l)/2,l].to_i;end

Ruby (66 chars)

Assuming integer inputs:

def r s,l=s.to_s.size;x=(s*s).to_s;y=x.size;x[(y-l)/2,l].to_i;end
哆啦不做梦 2024-09-06 05:58:55

Lua (135 128 114 个字符)

function r(i)
l=string.len
b=i or b
s=i or s
p=s*s..""
e=(l(p)-l(b))/2
s=tonumber(p:sub(e+1,e+l(b)))
return s
end

带有一个参数的种子并返回第一个 MSM 随机整数;不带参数的后续调用将返回下一个 MSM 随机整数。调用另一个整数来重新播种。

测试:

> =r(3456)
9439
> =r()
947
> =r()
9680
> =r()
7024
> =r()
3365
> =r()
3232
> =r()
4458
> =r()
8737
> =r()
3351
> =r()
2292
> =r(8653)
8744
> =r()
4575
> =r()
9306
> =r()
6016
> =r()
1922
> =r()
6940
> =r()
1636
> =r()
6764
> =r()
7516
> =r()
4902
> =r(843)
106
> =r()
123
> =r()
512
> =r()
621
> =r()
856
> =r()
327
> =r()
69
> =r()
476
> =r()
265
> =r()
22
> =r(45678)
86479
> =r()
78617
> =r()
80632
> =r()
1519
> =r()
30736
> =r()
47016
> =r()
10504
> =r()
3340
> =r()
11556
> =r()
35411
> 

Lua (135 128 114 chars)

function r(i)
l=string.len
b=i or b
s=i or s
p=s*s..""
e=(l(p)-l(b))/2
s=tonumber(p:sub(e+1,e+l(b)))
return s
end

Seeds with one argument and returns first MSM random integer; subsequent calls with no arguments return next MSM random integer. Call will another integer to re-seed.

Test:

> =r(3456)
9439
> =r()
947
> =r()
9680
> =r()
7024
> =r()
3365
> =r()
3232
> =r()
4458
> =r()
8737
> =r()
3351
> =r()
2292
> =r(8653)
8744
> =r()
4575
> =r()
9306
> =r()
6016
> =r()
1922
> =r()
6940
> =r()
1636
> =r()
6764
> =r()
7516
> =r()
4902
> =r(843)
106
> =r()
123
> =r()
512
> =r()
621
> =r()
856
> =r()
327
> =r()
69
> =r()
476
> =r()
265
> =r()
22
> =r(45678)
86479
> =r()
78617
> =r()
80632
> =r()
1519
> =r()
30736
> =r()
47016
> =r()
10504
> =r()
3340
> =r()
11556
> =r()
35411
> 
人间不值得 2024-09-06 05:58:55

Perl - 112 - 现在,108 - 现在 95 (感谢 Zaid 的想法) - 字符没有空格,不包括测试驱动程序循环(例如,我只计算了生成 1 的代码) sequence) - foreach 循环体中的代码。

@s=(8653,843,45678,3456);
foreach $s (@s){
    for(0..9){$s*=$s;$l=length($s);$L||=($l+1)/2;$H=($l+$L+1)/2;
        $s=substr($s,-$H,$L)+0;
        print "$s,"
    }
    print "\n";
    $L=0; @S=(); # Reset for next loop
}

输出:

8744,4575,9306,6016,1922,6940,1636,6764,7516,4902,
106,123,512,621,856,327,69,476,265,22,
86479,78617,80632,1519,30736,47016,10504,3340,11556,35411,
9439,947,9680,7024,3365,3232,4458,8737,3351,2292,

压缩后的代码为 112:

for(0..9){$s*=$s;$l=length($s);$L||=($l+1)/2;$H=($l+$L+1)/2;$s=substr($s,-$H,$L)+0;print "$s,"}

Perl - 112 - now, 108 - now 95 (thanks to Zaid's idea) - chars sans white space, excluding test driver loop (e.g. I only counted the code to generate 1 sequence) - the code in the body of foreach loop.

@s=(8653,843,45678,3456);
foreach $s (@s){
    for(0..9){$s*=$s;$l=length($s);$L||=($l+1)/2;$H=($l+$L+1)/2;
        $s=substr($s,-$H,$L)+0;
        print "$s,"
    }
    print "\n";
    $L=0; @S=(); # Reset for next loop
}

Output:

8744,4575,9306,6016,1922,6940,1636,6764,7516,4902,
106,123,512,621,856,327,69,476,265,22,
86479,78617,80632,1519,30736,47016,10504,3340,11556,35411,
9439,947,9680,7024,3365,3232,4458,8737,3351,2292,

Compressed code that was 112:

for(0..9){$s*=$s;$l=length($s);$L||=($l+1)/2;$H=($l+$L+1)/2;$s=substr($s,-$H,$L)+0;print "$s,"}
野稚 2024-09-06 05:58:55

Perl, 100 94 92 91 90 88 个字符

通过标准输入提供的种子。为了可读性而包含换行符:

@n=($n=pop)=~/./g;
for(0..9){
    @s=$n**2=~/./g;
    $n=join$\,splice@s,(@s-@n)/2,@n;
    print$/,$n+0
}

Perl, 100 94 92 91 90 88 chars

Seed provided through standard input. Newlines included for readability:

@n=($n=pop)=~/./g;
for(0..9){
    @s=$n**2=~/./g;
    $n=join$\,splice@s,(@s-@n)/2,@n;
    print$/,$n+0
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文