Bir tel içinde zıplayan elektronlar


46

nBoşlukları olan bir "tel" düşünün . Ayrıca, bu telde "elektronlar" olduğunu hayal edin. Bu elektronlar sadece bir süre yaşarlar. Teldeki tam olarak bir elektrona bitişik olan boşluklar elektron haline gelir. Hayat Oyunu terminolojisinde budur B1/S.

Örneğin, bu, periyodu 62 olan, uzunluğu 10 olan bir teldir.

görüntü tanımını buraya girin

kurallar

  • Girdi,, ntek, pozitif bir tamsayıdır.
  • Çıktı, n uzunluğunda bir telin süresini gösteren tek bir tamsayı olmalıdır.
  • Başlangıç ​​durumu, telin bir ucundaki tek bir elektrondur.
  • Dönem mutlaka başlangıç ​​durumunu içermez. Bazı uzunluklar hiçbir zaman başlangıç ​​durumuna geri dönmez, ancak tümü periyodiktir.
  • Statik bir telin (yani elektronsuz olanın) periyodu 1'dir.
  • Sınır şartları periyodik değildir . Yani, tel hiçbir şekilde toroidal değildir.

Test durumları

Bu listeyi hazırladığınız için teşekkür ederiz. (N = 27'ye kadar doğruladım.)

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

Hayat Oyunu esque simülatörüm: Yaşam Çeşitleri ile burada n = 2'den 21'e kadar olan test durumlarını görebilirsiniz .


EDIT: Buradaki sekans A268754 olarak yayınlandı !


hepsi periyodiktir ve dönem üst sınırlıdır 2^n-1, çünkü bu "tel" in sıfır olmayan durumlarının sayısıdır
Luis Mendo

@LuisMendo: Aslında, üst sınır daha azdır, çünkü elektronlar asla bitişik değildir. Tam olarak ne kadar az, bilmiyorum.
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.Bir örnek var mı
edc65

@ edc65: 5 uzunluğunda bir tel en küçük örnektir.
El'endia Starman

1
Daha kuvvetli olarak, elektronlar tek ve çift konumlar arasında geçiş yaparlar, bu nedenle bu süre en fazla 2 ^ (n / 2 + 1) olur.
xnor

Yanıtlar:


10

Python 2, 148 142 87 bayt

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

Brent'in döngü algılama algoritmasını kullanır ve böylece gerçekten hızlı çalışır.


Ayrıca Python'da bir animasyon yazdım (her ikisi de 2 ve 3). Koşması gerekiyor pyglet. Animasyonu çalıştırarak görüntüleyebilirsiniz:

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

(Çalıştırmadan önce özeti indirmekten ve kodu kontrol etmekten çekinmeyin.) Görselleştirilen n sayısını artırmak / azaltmak için + ve - tuşlarına basabilirsiniz .


Ve son olarak, bu sayı sırasını daha fazla araştırmak isteyenler için, işte okunabilir bir versiyon (yukarıdaki test vakalarını oluşturmak için kullanıldı):

# 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

Bir yıldan fazla geçtiğini biliyorum, ama HashLife kullanmanın bunu hızlandıracağını mı merak ediyorum
sadece ASCII-

7

Mathematica, 127 bayt

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

açıklama

Kural 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

Test durumları

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

7

Python 2,68 bayt

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

Döngü tespiti daha iyi olabilirdi, ancak yinelemeli adım çok güzel.

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

Diziyi bir ikili sayı olarak temsil ederek k, güncelleme, kbir sola /2ve bir sağa kaydırılan XOR'yu alarak *2, sonra da nbayt olarak keserek yapılabilir %2**n.


4

Python 3 2, 134 121 118 bayt

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)

Temelde Pyth cevabımla aynı , ancak Python'daki bazı yerleşik fonksiyonların bulunmamasından dolayı biraz uyarladı.

Ungolfed versiyonu:

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 adet 36 bayt

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

Bir yapılandırma tekrarlanana kadar yinelemek için "kümülatif sabit nokta" işlevini kullanır ve tüm ara yapılandırmaları bir liste listesi olarak döndürür. Bu işe yarıyor, çünkü kurallar deterministik ve yeni neslin konfigürasyonu mevcut konfigürasyonun bir fonksiyonu. Bu, aynı konfigürasyon tekrar göründüğünde, otomatların bir çevrimi tamamladığı anlamına gelir.

Buna (döngünün son yinelemesi) ulaştıktan sonra, bir sonraki yapılandırmayı (bir döngünün başlangıç ​​yapılandırması olan) elde etmek için "tarihçe" listesinin son elemanı üzerinde bir sonraki gen işlevini çağırır ve endeksini tarihte bulmak. Şimdi periyodun uzunluğu (1 + döngü sonu endeksi) eksi döngü başlama endeksidir.

Pythonic sözde kodunda:

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

Test paketi sunucunun onu öldürmesi için çok zaman alıyor, bu yüzden normal programı kullanmanız ve tek tek test etmeniz veya Pyth (eğer yapmadıysanız) kurmanız ve test etmek için bir komut dosyası kullanmanız gerekecek.


4

Jöle, 19 18 17 bayt

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

Bu kod ilk 2 n durumunu hesaplar , bu yüzden özellikle hızlı veya hafızada verimli değildir ...

Çevrimiçi deneyin! veya ilk 16 test senaryosunu doğrulayın .

Alternatif sürüm, 13 bayt (yarışmaz)

Bu zorluğun ardından gelen Jelly sürümlerinde yerleşik döngü algılaması vardır, bu da hem daha kısa hem de daha verimli bir çözümü sağlar.

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

Bu son test vakasını kolaylıkla idare eder. Çevrimiçi deneyin!

Nasıl çalışır

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

Yardımcı bağlantının, geçerli bir durumu kodlamayan ilk yinelemede 2 n'ye uygulandığını unutmayın . Ancak, ((2 n ÷ 2) ^ (2 n × 2))% 2 n = (2 n - 1 + 2 n + 1 )% 2 n = 2 n - 1 , muhtemel başlangıç ​​durumlarından biridir.

Biz döngü yana 2 n + 1 kez, biz döngü algılama başarılı kılacak iki kez bir devlet karşılaşmaya garantilidir.


3

CJam, 41 34 31 27 25 bayt

Dennis'e 3 byte kaydettiğin için teşekkürler. Jelly cevabından bir fikir ödünç almak başka bir 4 kurtardı.

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

Burada test et.

açıklama

Gerçek bir bit listesi kullanmak yerine, teli basitçe bir tamsayı olarak temsil ediyorum (bitleri elektronların pozisyonlarını gösterir). Devlet oldukça basit bitsel hesaplamalar ile güncellenir.

Yığındaki tüm ara sonuçları topladığımız süreyi bulmak için, 2 n-1 + 1 adım için simülasyonu çalıştırın ve daha sonra, son durumun son oluşumundan itibaren (artı 1) öğelerin sayısı olarak süreyi belirleyin.

İşte kod bir dökümü:

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

JavaScript (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]")

Ölçek

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

Haskell, 170 bayt

x!psınırlarda ise p indeksindeki öğeyi verir, aksi halde 0 nsonraki adımı hesaplar. th adım g iverir i. c xile başlarsa dönemi verir x. fhepsini birlikte sarar.

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]

(Not: sarılmamış tercümana sahip, tam özellikli olmayan, bu nedenle yazım hataları olabilir.


2

MATL , 38 37 36 35 bayt

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

Bu, yeni durum öncekilerden herhangi birine eşit olana kadar yeni durumları hesaplamaya devam eden bir döngü kullanır. Her durum bir sıfır ve bir vektördür. Bu vektörler büyüyen bir 2D dizisinin satırları olarak saklanır.

Her yeni durumun hesaplanması, şu anki durumun sıra ile sarılması, [1,0,1]sadece merkezi kısmı tutulması ve 0olmayan herhangi bir girişe ayarlanması ile yapılır 1.

EDIT (13 Mayıs 2016) Aşağıdaki bağlantıdaki kod, bu cevap yazıldıktan sonra dilde yapılan değişikliklere göre hafifçe değiştirildi.

Çevrimiçi deneyin!

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

Perl 6, 81 bayt

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

Biraz genişledi ve unungolfed

-> $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)
}

Biraz açıklama:

  • [op]op kullanarak listeyi azaltır. Örneğin [+] @listtoplayacak@list
  • Rbir op'a verilen argümanları tersine çeviren bir meta-op'tur. Örneğin 1 R- 32 ile sonuçlanacaktır.

1

C ++, 211 bayt

golfed

#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);}

Okunabilirlik için eklenen boşluk ile

#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 ++ 'ın bit seti için iyi uygulama; ve Brent'in döngü algılama algoritmasını (@orlp tarafından kullanıldığı gibi) öğrenen harika bir eğitim


0

Pyth, 95 bayt

J.[ZQ[1)K_1=bYW<K0=NY aN?hJZ?htJ1ZFTr1tlJ aN?@JTZ?x@JhT@JtT1Z) aN?eJZ?@J_2 1Z=JN=KxbJ abJ;-tlbK

Burada deneyebilirsiniz .



0

Ruby, 72 bayt

Anonim işlev

->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}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.