Метод середнього квадрату


19

Вступ

Метод середнього квадрату використовується для генерації псевдовипадкових чисел. Однак це не дуже вдалий метод на практиці, оскільки його період, як правило, дуже короткий і має деякі серйозні слабкі місця. Як це працює? Візьмемо приклад:

Для насіння вибираємо 123456:

Seed     123456

Насіння в квадраті (насіння × насіння), дорівнює:

Seed²  15241383936

Ми почали з 6-значного числа. Це означає, що насіння в квадраті має дати 12-значне число. Якщо це не так, для компенсації додаються провідні нулі:

Seed²  015241383936

Потім беремо середню частину числа, того ж розміру , що і насіння:

Seed²  015241383936
          ^^^^^^

Це наше нове насіння : 241383. Повторюємо той самий процес, як показано вище. Ми отримуємо наступне:

0:     123456
    015241383936
       |    |
1:     241383
    058265752689
       |    |
2:     265752
    070624125504
       |    |
3:     624125
    389532015625
       |    |
4:     532015
    283039960225
       |    |
5:     039960
    001596801600
       |    |
6:     596801

І це триває деякий час ... Тепер ми знаємо, що таке метод середнього квадрату, давайте приступимо до виклику:


Завдання

Кожне насіння має в період . Період n- дигідного насіння не може бути більше 8 n . Наприклад, насіння 82. Це дало б таку послідовність:

82 > 72 > 18 > 32 > 02 > 00 > 00 > 00 > 00 > 00
|____|____|____|____|____|____|____|____|____|___...
0    1    2    3    4    5    6    7    8    9

Ви можете бачити, що період дорівнює 5 , перш ніж знову містити ту саму цифру. Ваше завдання полягає в тому, що, якщо насіння насіння більше 0, не містить провідних нулів, виведіть період насіння . Отже, у цьому випадку вам потрібно вивести 5.

Інший приклад:, 24який дає наступне:

24 > 57 > 24
|____|____|___...
0    1    2

Як бачите, не всі послідовності закінчуються 0. Цей цикл має період 1 .


Тестові справи

Input   >   Output
24      >   1
82      >   5
123456  >   146
8989    >   68
789987  >   226

Пастебіни з послідовностями для 123456 , 8989 , 789987

Це , тому подання з найменшою кількістю байтів виграє!

Можна припустити, що вхід ніколи не буде мати неоднакову кількість цифр.


10
Nit pick: Це не період. Період означає, що послідовність зрештою повертає його початковий стан. 24є періодичним (з періодом 2, я б сказав), 82це в кінцевому рахунку , періодична (з періодом 1).
Денніс

1
Отже, "період" - це 0-індекс останнього стану, який відрізняється від усіх попередніх станів?
Луїс Мендо

@LuisMendo Так, це правильно. Мої математичні знання не найкращі: с.
Аднан

Це буде більше схоже на "кількість повторень, перш ніж вона стабілізується"
лише ASCII,

1
@WashingtonGuedes Дивіться цю пастину . Це робить це більш зрозумілим?
Аднан

Відповіді:


3

Желе, 26 24 18 байт

³DL⁵*
²:¢½¤%¢µÐĿL’

Спробуйте в Інтернеті!

Як це працює

³DL⁵*         Helper link. No arguments.

³             Yield the original input.
 D            Convert from integer to base 10.
  L           Get l, the length of the decimal representation.
   ⁵*         Compute 10 ** l.


²:¢½¤%¢µÐĿL’  Main link. Input: n (integer)

²             Square n.
  ¢½¤         Call the helper link and take the square root of the result.
 :            Integer division; divide the left result by the right one.
      ¢       Call the helper link.
     %        Take the left result modulo the right one.
       µ      Convert the previous chain into a link, and begin a new chain.
        ÐĿ    Repeat the previous chain until the results are no longer unique,
              updating n in each iteration. Collect the intermediate results.
          L   Get the length of the list of results.
           ’  Decrement.

5

Чистий баш, 162 131 116 113 107

Збережено 3 байти за допомогою $c...

Дякую @Dennis за допомогу мені зберегти ще 6 байт.

---- begin middleSquare ----

for((b=$1;i[c=10#$b]<2;)){ a=${#b}
printf -v b %0$[a*2]d $[c*c]
b=${b:a/2:a};((i[10#$b]++))
};echo ${#i[@]}

---- end middleSquare ----

for testCase in 24 82 123456 8989 789987 111111;do
    printf "%12s: " $testCase
    bash middleSquare $testCase
  done
          24: 2
          82: 5
      123456: 146
        8989: 68
      789987: 226
      111111: 374

Квадрат форматований, 131

---- begin middleSquare ----

for((b=$1;i[
10#$b]<2;1))
do a="${#b}" 
printf -v b\
 %0$[a*2]d \
$[10#$b**2];
b=${b:a/2:a}
((i[10#$b]++
));done;ech\
o ${#i[@]:0}

---- end middleSquare ----

for testCase in 24 82 123456 8989 789987 111111;do
    printf "%12s: %9d\n" $testCase $(
        bash middleSquare $testCase)
  done
          24:         2
          82:         5
      123456:       146
        8989:        68
      789987:       226
      111111:       374

Старий, але з фантазійним виходом, 162

---- begin middleSquare ----

for((b=$1;i[10#$b
]<2;1))do a=${#b}
printf -v b %0$[a
*2]d  $[10#$b**2]
b=${b:a/2:a};((i[
10#$b]++));print\
f "%9d %s\n" ${#\
i[@]} $b;done;ec\
ho -- ${#i[@]} --

---- end middleSquare ----

bash middleSquare 24
        1 57
        2 24
        2 57
-- 2 --

for testCase in 24 82 123456 8989 789987 111111
    do while read f v f
        do r=$v;done < <(
        bash middleSquare $testCase)
    printf "%12s: %11d\n" $testCase $r
  done
          24:           2
          82:           5
      123456:         146
        8989:          68
      789987:         226
      111111:         374

3

JavaScript (ES7), 82 байти

f=(n,p={},m=-1,l=n.length)=>p[n]?m:f(`${n*n+100**l}`.substr(l/2+1,l,p[n]=1),p,++m)

Приймає введення у вигляді рядка, наприклад "82", і повертає ціле число. Проста рекурсивна техніка хвоста для перевірки кожного насіння по черзі на хеш насіння, який вже був помічений. Я додаю 100 ** л на квадрат, щоб забезпечити послідовну довжину.


@Downgoat Приймає введення у вигляді рядка .
Ніл

1
о так, я думаю, я не можу читати: |
Пуховик

@WashingtonGuedes Ні, це не працює, коли проміжне значення починається з достатньої кількості нулів. (Ось чому я "витратив" 7 байт, додавши 100 ** л.)
Ніл

1
@WashingtonGuedes Є випадки, коли це не працює, наприклад, спробуйте слідувати ланцюжком з 5288.
Ніл

3

Пітон 3 2, 139 114 97 байт

Дякуємо Seeq за те, що ти граєш на 25 байт, а Деннісу - за 17 байт! Код:

s=`input()`;u=[];l=len(s)/2
while not s in u:u+=[s];s=`int(s)**2`.zfill(l*4)[l:3*l]
print~-len(u)

Однозначно можна гольфу далі. Це був також код, який використовується для виготовлення тестових випадків: P.


2

Pyth, 21 байт

tl.us_<>_`^N2/lz2lzsz

Спробуйте в Інтернеті: Демонстрація або Тестовий набір

редагувати: Знайдено крайовий регістр 1000, який не працював із моїм попереднім кодом. Виправлено це на 1 байт.

Пояснення:

tl.us_<>_`^N2/lz2lzsz   implicit: z = input string
  .u               sz   apply the following instructions to N, starting with N = int(z), 
                        until it runs into a loop:
          ^N2              square it
         `                 convert it to a string
        _                  reverse order
       >     /lz2          remove the first len(z)/2
      <          lz        remove everything but the first len(z)  
     _                     reverse order
    s                      convert to int
  .u                   returns the list of all intermediate values
 l                     compute the length of this list
t                      minus 1

будь-яка причина використовувати szзамість Q?
Вен

@ User1737909 Якщо я використовую Q, я повинен замінити всі lzз l`Qс.
Якубе

м, здається, дивно, що Pyth не поділяє input. Я думаю, це дійсно призначено для того, щоб дозволити друге читати stdin ..?
Вен

@ user1737909 Так. Єдина можливість введення акцій є з .zі .Q, хоча вони читають кілька рядків вхідних даних і зберігати їх в списках. Але я насправді не бачив, щоб хтось використовував цю функцію. Це лише 1 байт для оцінювання рядка або для зміщення числа.
Якубе

Гаразд, так що ви можете прочитати stdin максимум 4 рази в Pyth Qz.Q.z,?
Вен

2

MATL , 33 35 40 байт

`t0)2^10GVnXK2/^/k10K^\vtun@>]n2-

Спробуйте в Інтернеті!

`           % do...while
  t         %   duplicate. Take input implicitly on first iteration
  0)        %   pick last value of array
  2^        %   square
  10        %   push 10
  GVn       %   number of digits of input
  XK        %   copy that to clipboard K
  2/        %   divide by 2
  ^         %   power
  /k        %   divide and floor. This removes rightmost digits from the square value
  10K^      %   10 ^ number of digits of input
  \         %   modulo. This takes the central part of the squared number
  v         %   concatenate this new number to array of previous numbers
  tun@>     %   does the number of unique values exceed the iteration index?
]           % if so: next iteration. Else: exit loop
n2-         % desired result is the amount of numbers minus 2. Implicitly display

2

Oracle SQL 11.2, 184 байт

WITH v(v,p,n)AS(SELECT:1,'0',-1 FROM DUAL UNION ALL SELECT SUBSTR(LPAD(POWER(v,2),LENGTH(v)*2,0),LENGTH(v)/2+1,LENGTH(v)),v,n+1 FROM v)CYCLE v SET c TO 1 DEFAULT 0 SELECT MAX(n)FROM v;

Без гольфу

WITH v(v,p,n) AS
(
  SELECT :1,'0',-1 FROM DUAL
  UNION ALL
  SELECT SUBSTR(LPAD(POWER(v,2),LENGTH(v)*2,0), LENGTH(v)/2+1, LENGTH(v)),v,n+1 FROM v
)
CYCLE v SET c TO 1 DEFAULT 0
SELECT MAX(n) FROM v;

Він використовує виявлення вбудованого циклу, щоб зупинити рекурсивність.



1

Математика, 80 байт

(a=10^⌊Log10@#+1⌋;Length@NestWhileList[⌊#^2/a^.5⌋~Mod~a&,#,Unequal,All]-2)&

1

CJam, 37 байт

q{__,W*:D;~_*sD2/<D>]___|=:A;~A}g],((

Натрапив на надокучливу проблему замовлення стека, яку я не можу відразу зрозуміти, як вирішити. Це також неймовірно повільно.

Як це працює: Кожна ітерація висуває нове значення на вершину стека, потім ми загортаємо стек у масив і бачимо, чи є він таким самим, як його об'єднання з собою (щоб побачити, чи є у нього повторювані елементи). Коли у нього є повторювані елементи, зупиніться і подивіться, скільки елементів у стеку.


1

Пітон 2, 82 байти

def f(n,A=[],l=0):l=l or len(`n`)/2;return-(n in A)or-~f(n*n/10**l%100**l,A+[n],l)

Спробуйте це на Ideone .



1

VBSCRIPT, 131 байт

s=inputbox(c):l=len(s):do:t=t&","&s:s=space(l*2-len(s*s))&s*s:s=mid(s,l/2+1,l):i=i+1:loop until instr(t,","&s)>0:msgbox i-1

Найкраще, що я міг зробити з vbscript, перший плакат, так що просто на мене!


Ласкаво просимо до головоломки програмування та обміну стека коду! Чудовий перший пост! Я трохи відредагував форматування вашої публікації, щоб зробити її більш зрозумілою та більше відповідати нашим стандартам. Щасливого гольфу!
GamrCorps
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.