13

挑战:

按字符计数的最短代码,将使用Middle-Square Method生成一系列(伪)随机数。

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

R n+1 = 中((R n ) 2 , m)

例如:

3456 2 = 11943936

中(11943936)= 9439

9439 2 = 89094721

中(89094721)= 0947

947 2 = 896809

中(896809)= 9680

9680 2 = 93702400

中(93702400)= 7024

另一个例子:

843 2 = 710649

中(710649)= 106

106 2 = 11236

中(11236)= 123

123 2 = 15129

中(15129)= 512

512 2 = 262144

中(262144)= 621

621 2 = 385641

中(385641)= 856

856 2 = 732736

中(732736)= 327

327 2 = 106929

中(106929)= 069

69 2 = 4761

中(4761) = 476

476 2 = 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

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

4

15 回答 15

15

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()结果。
于 2010-04-24T02:46:10.197 回答
10

dc 26/37 字符

26 个字符的单个数字的函数:

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

37个字符,10 个循环:

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

功能说明:

? 输入 n
dZ 计算位数
sl 存储在寄存器 l 中
2^ 计算 n^2
dZ 计算正方形的位数
1+ll-2/Ar^/ n/(10^((squaredigits+1-l)/2)) int 除法截断最后一位
All^% n%(10^l) 模数截断第一个数字
p 打印数字

测试:

直流 msml.dc
45678
86479
78617
80632
1519
30736
47016
10504
3340
11556
35411
于 2010-04-24T17:24:26.860 回答
5

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 3print作为函数将添加 1 个更多的字符来关闭括号。

于 2010-04-23T23:43:48.533 回答
4

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
于 2010-04-24T01:43:22.560 回答
2

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

$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
于 2010-04-24T00:44:59.073 回答
1

Perl,80 个字符

(从命令行)

$n=pop;$l=length$n;map{$n*=$n;print 0+($n=substr$n,(length($n)-$l)/2,$l),$/}0..9
于 2010-04-24T03:16:45.207 回答
1

Haskell(97 99 个字符)

大概还是可以缩短的。产生一个无限序列,或者至少遇到 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 <length of number> <number>

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

解释

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

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

于 2010-04-24T01:48:22.630 回答
1

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
~~~~~~~~~~~~~         ~~~~~~~~~~~~~
于 2010-04-23T23:38:23.650 回答
1

Groovy - 82 个字符

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}

使用第一个参数作为种子,输出由 4 个 base10 数字组成,就像你的例子一样。

于 2010-04-23T23:39:26.253 回答
1

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
于 2010-04-24T16:05:31.533 回答
1

哈斯克尔


注意:生成一个包含 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

于 2010-06-08T23:43:22.987 回答
0

Lua135 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
> 
于 2010-04-24T02:45:59.583 回答
0

Perl - 112 - 现在,108 - 现在 95(感谢 Zaid 的想法) - 没有空格的字符,不包括测试驱动程序循环(例如,我只计算生成 1 个序列的代码) - 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,"}
于 2010-04-24T00:17:19.743 回答
0

红宝石(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
于 2010-04-24T03:42:00.813 回答
0

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
}
于 2010-04-24T12:00:28.040 回答