Code Golf: генератор случайных чисел MSM

Задача:

Самый короткий код по количеству символов, который будет генерировать ряд (псевдо) случайных чисел с помощью Метод Middle-Square.

Метод среднего квадрата генерации (псевдо) случайных чисел был впервые предложен Джоном Фон Нейманом в 1946 году и определяется следующим образом:

R n + 1= mid ((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, есть некоторая двусмысленность (106 или 064). В этом случае извлеките 3, наиболее близкое к началу строки. Поэтому в этом случае вы извлечете 106.

Легкий способ подумать о том, чтобы положить нули в число, если это не правильное количество цифр. Например, если вы набрали начальные нули до 710649, вы получите 0710649, а средние 3 цифры теперь станут 106.

Тестовые примеры:

Не делайте никаких предположений относительно длины семени. Например, вы не можете предположить, что семя всегда будет 4-значным числом

Начальное семя 3456, которое генерирует 4-значные случайные числа, должно генерировать следующие серии (первые 10):

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

Начальное семя 8653, которое генерирует 4-значные случайные числа, должно генерировать следующую серию (первые 10):

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

Начальное семя 843, которое генерирует 3-значные случайные числа, должно генерировать следующие серии (первые 10):

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

Начальное семя 45678, которое генерирует 5-значные числа рядов, должно генерировать следующую серию (первые 10):

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

Что касается ведущих нулей, то ответ не содержит ведущих нулей:).

Ответы

Ответ 1

dc 26/37 символов

26 отображает функцию для одного числа:

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

37 символы с циклом из 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

Ответ 2

Документы 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() к результатам.

Ответ 3

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

Производит бесконечную последовательность на stdout. Обратите внимание, что трюк backtick не будет работать, по крайней мере, в более старых версиях с типом long из-за окончания L в представлении. Python 3 print как функция добавит еще 1 char для закрытия патента.

Ответ 4

С# ( 96 81 79 85 84 символа)


Журнал изменений

  • Добавлено предложение Yuliy для 81
  • Удалены дополнительные скобки для 79.
  • Увеличенный счет, потому что я изначально не подсчитал необходимые пробелы (только символы).
  • Замена 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

Ответ 5

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

Ответ 6

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
~~~~~~~~~~~~~         ~~~~~~~~~~~~~

Ответ 7

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-мя базовыми цифрами 10, как в ваших примерах.

Ответ 8

символы 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) до достижения желаемой длины.

As iterate, а также большинство функций Haskell предполагают, что используемая функция является постоянной. Поскольку мы сами меняем функцию, нам нужно реализовать специальную версию iterate.

Ответ 9

Perl, 80 символов

(из командной строки)

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

Ответ 10

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

Ответ 11

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

Ответ 12

Perl - 112 - теперь 108 - теперь 95 (благодаря идее Заида) - символы без пробелов, исключая цикл тестового драйвера (например, я только подсчитал код для генерации 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,"}

Ответ 13

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
> 

Ответ 14

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

Ответ 15

Perl, 100 94 92 91 90 88 символов

Семя предоставляется через стандартный вход. Новые строки включены для удобства чтения:

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