철사에 튀는 전자


46

n공백 이있는 "와이어"를 상상해보십시오 . 그 와이어에 "전자"가 있다고 상상해보십시오. 이 전자들은 한 시간 동안 만 산다. 정확히 하나의 전자에 인접한 전선의 공간은 전자가됩니다. Life of Life 용어에서 이것은입니다 B1/S.

예를 들어, 이것은 길이가 62이고 기간이 10 인 와이어입니다.

여기에 이미지 설명을 입력하십시오

규칙

  • 입력 n은 단일 양의 정수입니다.
  • 출력은 길이가 n 인 와이어의주기를 나타내는 단일 정수 여야합니다.
  • 시작 상태는 와이어의 한쪽 끝에서 단일 전자입니다.
  • 기간 에는 시작 상태가 반드시 포함되는 것은 아닙니다 . 일부 길이는 시작 상태로 돌아 가지 않지만 모두 주기적입니다.
  • 정적 와이어 (즉, 전자가없는 와이어)는주기 1을 갖습니다.
  • 경계 조건은 주기적 이지 않습니다 . 즉, 와이어는 어떤 식 으로든 환상적이지 않습니다.

테스트 사례

이 목록을 제작 해 주신 orlp에게 감사드립니다. (최대 n = 27까지 확인했습니다.)

1 1
2 2
3 1
4 6
5 4
6 14
7 1
8 14
9 12
10 62
11 8
12 126
13 28
14 30
15 1
16 30
17 28
18 1022
19 24
20 126
21 124
22 4094
23 16
24 2046
25 252
26 1022
27 56
28 32766
29 60
30 62
31 1
32 62
33 60
34 8190
35 56
36 174762
37 2044
38 8190
39 48
40 2046
41 252
42 254
43 248
44 8190
45 8188

내 인생의 게임 시뮬레이터 : Variations of Life 에서 n = 2에서 21까지의 테스트 사례를 볼 수 있습니다 .


편집 : 여기의 순서는 A268754 로 게시되었습니다 !


그들 모두는 주기적 있습니다 그리고 기간에 의해 상위 경계입니다 2^n-1즉 "선"의 수 제로가 아닌 상태의 수이기 때문에,
루이스 Mendo

@LuisMendo : 실제로 전자가 절대 인접하지 않기 때문에 상한은 더 적습니다. 정확히 얼마나 적은지 모르겠습니다.
El'endia Starman

The period does not necessarily include the starting state. Some lengths never return to the starting state, but all of them are periodic.예가 있습니까?
edc65

@ edc65 : 길이 5의 와이어가 가장 작은 예입니다.
El'endia Starman

1
더 강하게, 전자는 홀수 위치와 짝수 위치 사이에서 교번하므로주기는 최대 2 ^ (n / 2 + 1)입니다.
xnor

답변:


10

파이썬 (2), 148 (142) 87 바이트

n=input()
p=l=1
t=1
h=2
while t!=h:
 if p==l:t,l,p=h,0,p*2
 h=h/2^h*2%2**n;l+=1
print l

브렌트의 사이클 감지 알고리즘을 사용 하므로 실제로 빠르게 실행됩니다.


또한 Python으로 애니메이션을 작성했습니다 (2 및 3 작품 모두). pyglet실행 해야 합니다. 다음을 실행하여 애니메이션을 볼 수 있습니다.

python -m pip install --user pyglet
curl -s https://gist.githubusercontent.com/orlp/f32d158130259cbae0b0/raw/ | python

(실행하기 전에 요점을 다운로드하고 코드를 검사하지 않아도됩니다.) + 및-키를 눌러 시각화중인 n 을 증가 / 감소시킬 수 있습니다.


마지막으로,이 숫자 시퀀스를 더 자세히 살펴 보려는 사람들을 위해 읽을 수있는 버전이 있습니다 (위의 테스트 사례를 생성하는 데 사용됨).

# Brent's cycle detection, modified from wikipedia.
def electron_period(n):
    wire_mask = (1 << n) - 1
    power = lam = 1
    tortoise, hare = 1, 2
    while tortoise != hare:
        if power == lam:
            tortoise = hare
            power *= 2
            lam = 0
        hare = ((hare << 1) ^ (hare >> 1)) & wire_mask
        lam += 1
    return lam

1 년이 지났다는 것을 알고 있지만 HashLife를 사용하면 속도가 빨라질 지 궁금합니다.
ASCII 전용

7

Mathematica, 127 바이트

p@n_:=Tr[#2-#]&@@Position[#,Last@#]&@NestWhileList[1~Table~n~ArrayPad~1*18~CellularAutomaton~#&,{1}~ArrayPad~{1,n},Unequal,All]

설명

규칙 18 :

{0,0,0} -> 0
{0,0,1} -> 1
{0,1,0} -> 0
{0,1,1} -> 0
{1,0,0} -> 1
{1,0,1} -> 0
{1,1,0} -> 0
{1,1,1} -> 0

테스트 사례

p/@Range[10]
(* {1,2,1,6,4,14,1,14,12,62} *)

7

파이썬 2, 68 바이트

f=lambda n,k=1,l=[]:k in l and-~l.index(k)or f(n,k/2^k*2%2**n,[k]+l)

사이클 감지는 더 나을 수 있지만 반복 단계는 좋습니다.

k -> k/2^k*2%2**n

이진수로 어레이를 대표하여 k업데이트가의 XOR 취함으로써 수행 될 수 k시프트 왼쪽 하나 /2하나 개를 우측으로 *2그 다음에 절단 n등의 바이트 %2**n.


4

파이썬 3 2 134 121 118 바이트

Q=input()
h=[]
n=[0,1]+Q*[0]
while n not in h:h+=[n];n=[0]+[n[d]^n[d+2] for d in range(Q)]+[0]
print len(h)-h.index(n)

기본적으로 내 Pyth answer 와 동일 하지만 Python에 특정 내장 함수가 없기 때문에 약간 수정했습니다.

언 골프 버전 :

length = input()
history = []
new = [0] + [1] + length*[0]
while new not in history:
    history += [new]
    new = [0] + [new[cell]^new[cell+2] for cell in range(length)] + [0]
print len(history) - history.index(new)

4

Pyth, 39 36 바이트

L++Zmx@bd@bhhdQZ-lJ.uyN.[,Z1ZQ)xJyeJ

"누적 고정 소수점"기능을 사용하여 구성이 반복되기 직전까지 반복하고 모든 중간 구성을 목록 목록으로 리턴합니다. 규칙이 결정적이며 차세대 구성이 현재 구성의 기능이기 때문에 작동합니다. 이는 동일한 구성이 다시 나타나면 오토마타가 사이클을 완료했음을 의미합니다.

(사이클의 마지막 반복)에 도달 한 후 "기록"목록의 마지막 요소에서 마지막으로 한 번에 다음 함수를 호출하여 다음 구성 (사이클의 시작 구성)을 얻습니다. 역사에서 색인을 찾으십시오. 이제주기는 단순히 길이 (1 +주기 종료 색인)에서주기 시작 지수를 뺀 값입니다.

파이썬 의사 코드에서 :

                  Z = 0
                  Q = eval(input())
L                 def y(b):                # generates next-gen from current(param)
  ++Zm                return [Z] + map(    # adds head zero padding
    x@bd@bhhd             lambda d: b[d] ^ b[1+ 1+ d],  # xor the states of adjacent cells
    Q                     range(Q))        # implicit range in map
    Z                     + [Z]            # adds end zero padding
-lJ.uyN.[,Z1ZQ)   J = repeatTilRecur(lambda N,Y:y(N), padRight([Z,1],Z,Q)); print( len(J) -
                  # N:value; Y:iteration count
  JxJyeJ              J.index( y( J[-1] ) ) )

테스트 스위트는 서버가 서버를 종료하는 데 너무 많은 시간이 걸리므로 일반 프로그램 을 사용하여 하나씩 테스트하거나 Pyth를 설치하지 않은 경우 설치하고 스크립트를 사용하여 테스트해야합니다.


4

젤리, 19 18 17 바이트

H^Ḥ%®
2*©Ç‘СUµiḢ

이 코드는 최초의 계산 이 개 N 그렇지 특히 빠른 또는 메모리 효율적인, 그래서 상태를 ...

온라인으로 사용해보십시오! 또는 처음 16 개의 테스트 사례를 확인하십시오 .

대체 버전, 13 바이트 (비경쟁)

이 문제를 해결 한 Jelly 버전에는 루프 감지 기능이 내장되어있어 더 짧고 효율적인 솔루션을 구현할 수 있습니다.

H^Ḥ%®
2*©ÇÐḶL

이것은 마지막 테스트 케이스를 쉽게 처리합니다. 온라인으로 사용해보십시오!

작동 원리

2*©Ç‘СUµiḢ    Main link. Input: n (integer)

2*             Compute 2 ** n.
  ©            Store the result in the register.
     С        Do the following:
   Ç             Apply the helper link, which updates the state, ...
    ‘            2 ** n + 1 times.
               Collect all 2 ** n + 2 intermediate results in a list.
       U       Upend; reverse the list of results.

        µ      Begin a new, monadic chain. Argument: R (list of results)
          Ḣ    Yield and remove the first element of R (final state).
         i     Find its first index in the remainder or R.
               This is the length of the loop.

H^Ḥ%®        Helper link. Argument: s (state, integer)

H            Halve s. This yields a float, but ^ will cast to integer.
  Ḥ          Double s.
 ^           Compute (s ÷ 2) ^ (s × 2).
    ®        Retrieve the value stored in the register (2 ** n).
   %         Compute ((s ÷ 2) ^ (s × 2)) % (2 ** n).

헬퍼 링크가 적용되어 있습니다 2 N 유효 상태를 인코딩하지 않는 첫 번째 반복에서. 그러나 ((2 n ÷ 2) ^ (2 n × 2)) % 2 n = (2 n -1 + 2 n + 1 ) % 2 n = 2 n-1 은 가능한 시작 상태 중 하나입니다.

우리는 루프 때문에 2 N + 1 번, 우리는 루프 감지 성공하고, 두 번 상태가 발생할 보장됩니다.


3

CJam, 41 34 31 27 25 바이트

3 바이트를 절약 해 준 Dennis에게 감사합니다. 그의 젤리 답변에서 아이디어를 빌리면 또 다른 4.

2ri#_){__4*^2/W$%}*]W%(#)

여기에서 테스트하십시오.

설명

나는 실제 비트 목록을 사용하는 대신 와이어를 단순히 정수 (이 비트는 전자의 위치를 ​​나타냄)로 나타냅니다. 상태는 매우 간단한 비트 계산을 통해 업데이트됩니다.

스택에서 모든 중간 결과를 수집하는 기간을 찾으려면 2 n-1 +1 단계에 대한 시뮬레이션을 실행 한 다음 마지막 상태 (더하기 1)가 발생한 이후의 원소 수로주기를 결정하십시오.

코드는 다음과 같습니다.

2ri#   e# Compute 2^n. This has a 1 in the n+1-th bit and zeroes below it. This is
       e# itself not a valid state but will be turned into 2^(n-1) by the first
       e# update.
_)     e# Duplicate and increment to get number of steps to simulate.
{      e# Repeat that many times...
  __   e#   Duplicate the last state twice.
  4*   e#   Multiply by 4, shifting all bits to the left by two positions.
  ^    e#   XOR - we only keep keep those cells where we have exactly one 1-bit
       e#   between both copies, i.e. those that neighboured a single electron
       e#   but shifted up by one position. We don't need handle the survival rule
       e#   explicitly, since electrons can never be adjacent in the first place.
  2/   e#   Divide by 2 shifting all bits back to the right again.
  W$   e#   Copy the initial number 2^n.
  %    e#   Modulo - this simply sets the first bit to 0.
}*
]      e# Wrap all states in an array.
W%     e# Reverse it.
(      e# Pull off the latest state.
#      e# Find its position in the remainder of the array.
)      e# Increment.

2

자바 스크립트 (ES6) 99 (104)

n=>eval("a=[...Array(n)];k={};for(a[0]=i=1;!k[a=a.map((v,i)=>v?0:a[i-1]^a[i+1])];k[a]=i++);i-k[a]")

테스트

f = n=>eval("a=[...Array(n)];k={};for(a[0]=i=1;!k[a=a.map((v,i)=>v?0:a[i-1]^a[i+1])];k[a]=i++);i-k[a]")

console.log = x => O.textContent += x + '\n';

;[...Array(45)].map((_, i) => console.log(++i + ' ' + f(i)))
<pre id=O></pre>


2

하스켈, 170 바이트

x!p범위 내에 있으면 인덱스 p에 요소를 제공하고, 그렇지 않으면 0 n은 다음 단계를 계산합니다. 단계를 g i제공합니다 i. c x로 시작하는 경우 마침표를 제공합니다 x. f모두 함께 포장합니다.

n x|l<-length x-1=[mod(x!(p-1)+x!(p+1))2|p<-[0..l],let y!q|q<0=0|q>=l=0|1<2=y!!p]
c x=[i-j|i<-[1..],j<-[0..i-1],let g k=iterate n x!!k,g i==g j]!!0
f n=c$1:map(*0)[2..n]

(참고 : 전체 기능이 아니므로 포옹 통역사가있는 전화에서 게시되었으므로 오타가있을 수 있습니다.)


2

MATL , 38 37 36 35 바이트

1Oi(`t0Y)5BX+8L)1=vt6#Xut0)=fdt?w}A

이것은 새로운 상태가 앞의 상태와 같아 질 때까지 새로운 상태를 계산하는 루프를 사용합니다. 각 상태는 0과 1로 구성된 벡터입니다. 이 벡터는 점점 늘어나는 2D 배열의 행으로 저장됩니다.

각 새로운 상태의 계산은 현재 상태를 시퀀스와 통합 [1,0,1]하고 중앙 부분 만 유지하며 0그렇지 않은 항목으로 설정하여 수행 1됩니다.

편집 (2016 년 5 월 13 일) 다음 링크의 코드는이 답변이 작성된 후 언어에 도입 된 변경 사항에 따라 약간 수정되었습니다.

온라인으로 사용해보십시오!

1Oi(            % create initial vector [1,0,0,...,0], with size equal to input
`               % do...while loop
  t0Y)          %   duplicate. Get last row of array: most recent vector
  5BX+8L)       %   compute new vector by convolving the most recent one
                %   with [1,0,1] and keeping only the central part
  1=            %   set ones to 1, rest to 0
  v             %   append to 2D array
  t6#Xu         %   compute vector of unique numeric labels, so that equal rows
  t0)=f         %   indices of entries whose value equals that of the last entry.
                %   This will contain the index of the last entry and possibly
                %   another index, in which case we've found a repetition
  d             %   this will either be empty (which is falsy) or contain the
                %   period, which is a nonzero number (and thus truthy)
  t?            %   duplicate. If non-empty (and nonzero)
    w           %     swap to put the 2D-array at the top of the stack. This is
                %     falsy, because it contains at least one zero, even in the
                %     n=1 case (the array is initiallized to 0 in that case)
                %     So the loop will terminate, with the period left on the stack
  }             %   else
    A           %     this transforms the empty array at the top of the stack
                %     into a true value, so that the loop will continue
                %   implicitly end if
                % implicitly end loop
                % implicitly display stack contents (period)

1

펄 6, 81 바이트

{my@h=my$w=2;@h.push($w=$w/2+^$w*2%2**$_)while 2>@h.grep($w);[R-] @h.grep($w,:k)}

약간 확장 및 언 골프

-> $n {
    my @history = my $wire = 2;
    while 2 > @history.grep($wire) {
        @history.push($wire = $wire/2 +^ $wire*2 % 2**$n)
    }
    [R-] @history.grep($wire,:k)
}

약간의 설명 :

  • [op]op를 사용하여 목록을 줄입니다. 예를 들어 [+] @list요약한다@list
  • Rop에 제공된 인수를 반대로 바꾸는 meta-op입니다. 예를 들어 1 R- 32가됩니다.

1

C ++, 211 바이트

골프

#include <bitset>
#include <cstdio>
#define B std::bitset<1<<10>
B m,t(1),h(2);int main() {int p,l;for(scanf("%d",&p);p--;m.set(p));
for(p=l=1;t!=h;h=(h>>1^h<<1)&m,l++)p==l?t=h,p*=2,l=0:0;return !printf("%d",l);}

가독성을 위해 추가 된 공백

#include <bitset>
#include <cstdio>
#define B std::bitset<1<<10>
B m,t(1),h(2);
int main() {    
    int p,l;
    for(scanf("%d",&p);p--;m.set(p));
    for(p=l=1;t!=h;h=(h>>1^h<<1)&m,l++)p==l?t=h,p*=2,l=0:0;    
    return !printf("%d",l);
}

C ++의 비트 셋에 대한 좋은 연습; 브렌트의 사이클 감지 알고리즘에 대한 훌륭한 교육 학습 (@orlp에서 사용)




0

루비, 72 바이트

익명의 기능.

->n{s=[w=1];c=p
(j=s.index w=w*2%2**n^w/2
j ?c=s.size-j:s<<w)while !c
c}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.