Metoda środkowego kwadratu

19

Wprowadzenie

Środkowy kwadrat metoda służy do generowania liczb pseudolosowych o. Nie jest to jednak dobra metoda w praktyce, ponieważ okres ten jest zwykle bardzo krótki i ma poważne słabości. Jak to działa? Weźmy przykład:

Jako nasiona wybieramy 123456:

Seed     123456

Kwadrat nasion (ziarno × ziarno) jest równy:

Seed²  15241383936

Zaczęliśmy od 6-cyfrowego numeru. Oznacza to, że ziarno do kwadratu powinno dostarczyć 12-cyfrową liczbę. Jeśli tak nie jest, dodawane są zera wiodące w celu skompensowania:

Seed²  015241383936

Następnie bierzemy środkową część liczby o tym samym rozmiarze co ziarno:

Seed²  015241383936
          ^^^^^^

Jest to nasz nowy materiał siewny : 241383. Powtarzamy ten sam proces, jak pokazano powyżej. Otrzymujemy następujące:

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

I to trwa przez jakiś czas ... Teraz wiemy, co to jest metoda średniego kwadratu, przejdźmy do wyzwania:


Zadanie

Każde ziarno ma się okres . Okres nasion n- cyfrowych nie może być dłuższy niż 8 n . Na przykład ziarno 82. To dałoby następującą sekwencję:

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

Widać, że okres jest równy 5 , zanim ponownie zawiera tę samą cyfrę. Twoim zadaniem jest, jeśli otrzyma ziarno większe niż 0, nie zawierające zer wiodących, wypisz okres nasion . W takim przypadku musisz wygenerować dane wyjściowe 5.

Innym przykładem jest 24:, który daje:

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

Jak widać, nie wszystkie sekwencje kończą się na 0. Ten cykl ma okres 1 .


Przypadki testowe

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

Pastebiny z sekwencjami dla 123456 , 8989 , 789987

To jest , więc wygrywanie z najmniejszą ilością bajtów wygrywa!

Możesz założyć, że dane wejściowe nigdy nie będą miały nieparzystej liczby cyfr.

Adnan
źródło
10
Nit pick: To nie jest okres. Okres oznacza, że ​​sekwencja ostatecznie przywraca jej stan początkowy. 24jest okresowy (z okresem 2, powiedziałbym), 82jest w końcu okresowy (z okresem 1).
Dennis
1
Czyli „kropka” to indeks 0 ostatniego stanu, który różni się od wszystkich poprzednich stanów?
Luis Mendo
@LuisMendo Tak, to prawda. Moja wiedza matematyczna nie jest najlepsza: str.
Adnan
Byłoby to bardziej jak „liczba iteracji przed ustabilizowaniem się”
tylko ASCII
1
@WashingtonGuedes Zobacz ten pastebin . Czy to wyjaśnia?
Adnan

Odpowiedzi:

3

Galaretka, 26 24 18 bajtów

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

Wypróbuj online!

Jak to działa

³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.
Dennis
źródło
5

Pure Bash, 162 131 116 113 107

Zapisano 3 bajty, używając $c...

Dzięki @Dennis za pomoc w oszczędzeniu 6 dodatkowych bajtów.

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

Formowany kwadrat, 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

Stare, ale z fantazyjną produkcją, 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
F. Hauri
źródło
3

JavaScript (ES7), 82 bajty

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)

Akceptuje dane wejściowe w postaci ciągu, np. „82”, i zwraca liczbę całkowitą. Prosta technika rekurencyjna ogona, aby sprawdzić kolejno każde ziarno z hasłem nasion, które już widzieliśmy. Dodam 100 ** l do kwadratu, aby zapewnić stałą długość.

Neil
źródło
@Downgoat Akceptuje dane wejściowe w postaci ciągu .
Neil
1
o tak, chyba nie umiem czytać: |
Downgoat
@WashingtonGuedes Nie, to nie działa, gdy wartość pośrednia zaczyna się od wystarczającej liczby zer. (Dlatego „zmarnowałem” 7 bajtów, dodając 100 ** l.)
Neil
1
@WashingtonGuedes Są przypadki, w których to nie działa, na przykład spróbuj śledzić łańcuch od 5288.
Neil
3

Python 3 2, 139 114 97 bajtów

Dzięki Seeq za grę w golfa z 25 bajtów i dzięki Dennisowi za grę w golfa z 17 bajtów! Kod:

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)

Zdecydowanie można dalej grać w golfa. Był to również kod użyty do wykonania przypadków testowych: P.

Adnan
źródło
2

Pyth, 21 bajtów

tl.us_<>_`^N2/lz2lzsz

Wypróbuj online: pakiet demonstracyjny lub testowy

edycja: Znaleziono przypadek krawędzi 1000, który nie działał z moim poprzednim kodem. Naprawiono to dla 1 bajtu.

Wyjaśnienie:

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
Jakube
źródło
jakiś powód, aby użyć szzamiast Q?
Ven
@ user1737909 Jeśli użyję Q, muszę wymienić wszystkich lzz l`Qs.
Jakube
Wydaje się zaskakujące, że Pyth się nie udostępnia input. Wydaje mi się, że to naprawdę ma na celu powtórzenie standardowego odczytu…?
Ven
@ user1737909 Tak. Jedyną możliwością dzielenia się danymi wejściowymi jest .zi .Q, chociaż czytają wiele wierszy danych wejściowych i przechowują je na listach. Ale tak naprawdę nie widziałem, żeby ktoś korzystał z tej funkcji. Jest to tylko 1 bajt, aby ocenić ciąg lub skreślić liczbę.
Jakube
Ok, więc można odczytać stdin co najwyżej 4 razy w Pyth, Qz.Q.z?
Ven
2

MATL , 33 35 40 bajtów

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

Wypróbuj online!

`           % 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
Luis Mendo
źródło
2

Oracle SQL 11.2, 184 bajty

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;

Nie grał w golfa

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;

Wykorzystuje wbudowane wykrywanie cyklu, aby zatrzymać rekurencyjność.

Jeto
źródło
2

Julia, 64 bajty

f(n,A=[],p=10^endof(dec(n)))=n∈A?-1:f(n^2÷√p%p,[A...n],p)+1

Wypróbuj z Coding Ground .

Dennis
źródło
1

Mathematica, 80 bajtów

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

CJam, 37 bajtów

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

Natknąłem się na irytujący problem z kolejnością stosów, którego nie mogę od razu zobaczyć, jak rozwiązać. Jest także niesamowicie wolny.

Jak to działa: każda iteracja wypycha nową wartość na stos, następnie zawijamy stos do tablicy i sprawdzamy, czy jest on taki sam jak jego połączenie ze sobą (aby sprawdzić, czy ma zduplikowane elementy). Gdy ma zduplikowane elementy, zatrzymaj się i sprawdź, ile elementów jest na stosie.

Simmons
źródło
1

Python 2, 82 bajty

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)

Wypróbuj na Ideone .

Dennis
źródło
1

Python, 124 bajty

def f(s,p=-1,n=0,m=[]):
 x=len(str(s))*2
 while n not in m:m+=[s];y=str(s*s).zfill(x);n=int(y[x/4:x*3/4]);p+=1;s=n
 return p
Argenis García
źródło
1

VBSCRIPT, 131 bajtów

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

Najlepsze, co mogłem zrobić z vbscript, plakat po raz pierwszy, więc spokojnie!

Traceur
źródło
Witamy w Programowaniu łamigłówek i wymianie stosów kodów golfowych! Świetny pierwszy post! Zmodyfikowałem nieco formatowanie Twojego postu, aby był bardziej czytelny i bardziej zgodny z naszymi standardami. Miłej gry w golfa!
GamrCorps