อิเล็กตรอนที่กระดอนเป็นเส้นลวด


46

ลองนึกภาพ "ลวด" ที่มีnช่องว่าง ลองจินตนาการดูเพิ่มเติมว่ามี "อิเล็กตรอน" ในสายนั้น อิเล็กตรอนเหล่านี้มีชีวิตอยู่เพียงครั้งเดียวเท่านั้น ช่องว่างใด ๆ ในลวดที่อยู่ติดกับอิเล็กตรอนหนึ่งตัวจะกลายเป็นอิเล็กตรอน B1/Sในเกมคำศัพท์ชีวิตนี้เป็น

ตัวอย่างเช่นนี่คือสายของความยาว 10 ที่มีระยะเวลา 62

ป้อนคำอธิบายรูปภาพที่นี่

กฎระเบียบ

  • อินพุต,, nเป็นเลขจำนวนเต็มบวกเดียว
  • เอาต์พุตจะต้องเป็นจำนวนเต็มเดียวที่แสดงถึงช่วงเวลาของเส้นลวดที่มีความยาว n
  • สถานะเริ่มต้นคืออิเล็กตรอนเดี่ยวที่ปลายด้านหนึ่งของเส้นลวด
  • ช่วงเวลาไม่จำเป็นต้องรวมถึงสถานะเริ่มต้น ความยาวบางส่วนไม่เคยกลับสู่สถานะเริ่มต้น แต่ความยาวทั้งหมดเป็นระยะ
  • ลวดแบบคงที่ (เช่นไม่มีอิเล็กตรอน) มีระยะเวลา 1
  • เงื่อนไขของขอบเขตไม่ได้เป็นระยะ นั่นคือลวดไม่ได้ toroidal ในทางใดทางหนึ่ง

กรณีทดสอบ

ขอขอบคุณเป็นพิเศษกับ 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

ท่านสามารถเข้าดูกรณีทดสอบสำหรับ n = 2 ผ่าน 21 ที่นี่กับฉันเกมของชีวิตในรูปแบบจำลอง: การเปลี่ยนแปลงของชีวิต


แก้ไข:ลำดับที่นี่ได้รับการเผยแพร่เป็นA268754 !


ทั้งหมดของพวกเขาเป็นระยะและช่วงเวลาที่ถูกล้อมรอบด้วย2^n-1เพราะนั่นคือจำนวนของรัฐที่เป็นไปได้ที่ไม่ใช่ศูนย์ของ "ลวด"
ลูอิสเมนโด

@ 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

Python 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

ฉันรู้ว่ามันผ่านไปนานกว่าปี แต่ฉันสงสัยว่าถ้าใช้ 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

Python 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ปรับปรุงสามารถทำได้โดยการแฮคเกอร์ของkขยับตัวคนเดียวที่เหลือด้วย/2และหนึ่งที่เหมาะสมกับ*2แล้วตัดทอนเพื่อไบต์n%2**n


4

Python 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 ของฉันแต่ปรับมันค่อนข้างเพราะขาดฟังก์ชั่นบางอย่างใน 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

ใช้ฟังก์ชัน "สะสมคะแนนคงที่" เพื่อทำซ้ำจนกว่าจะถึงก่อนที่การกำหนดค่าจะเกิดขึ้นอีกครั้งและส่งกลับการกำหนดค่าระดับกลางทั้งหมดเป็นรายการของรายการ สิ่งนี้ได้ผลเพราะกฎนั้นถูกกำหนดไว้แล้วและการกำหนดค่าของรุ่นต่อไปคือฟังก์ชั่นของการกำหนดค่าปัจจุบัน ซึ่งหมายความว่าเมื่อการกำหนดค่าเดียวกันปรากฏขึ้นอีกครั้งออโตมาตะครบรอบแล้ว

หลังจากถึงจุดนั้น (การวนซ้ำครั้งสุดท้ายของรอบ) มันเรียกฟังก์ชัน Next-gen หนึ่งครั้งล่าสุดในองค์ประกอบสุดท้ายของรายการ "ประวัติ" เพื่อรับการกำหนดค่าถัดไป (ซึ่งเป็นการกำหนดค่าเริ่มต้นของรอบ) และ ค้นหาดัชนีของมันในประวัติศาสตร์ ตอนนี้ระยะเวลาเป็นเพียงความยาว (1 + ดัชนีของรอบสุดท้าย) ลบด้วยดัชนีของการเริ่มรอบ

ใน pythonic pseudocode:

                  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Ḣ

รหัสนี้คำนวณสถานะ2 nแรกดังนั้นจึงไม่เร็วหรือหน่วยความจำมีประสิทธิภาพ ...

ลองออนไลน์! หรือตรวจสอบกรณีทดสอบ 16 กรณีแรก

รุ่นอื่น 13 ไบต์ (ไม่แข่งขัน)

เจลลี่เวอร์ชันที่โพสต์วันที่ความท้าทายนี้มีการตรวจจับลูปในตัวทำให้สามารถแก้ปัญหาที่สั้นลงและมีประสิทธิภาพมากขึ้น

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 ไบต์ การยืมความคิดจากคำตอบของเจลลี่ของเขาช่วยชีวิตอีก 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

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

ทดสอบ

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 ไบต์

x!pให้องค์ประกอบที่ดัชนี p หากอยู่ในขอบเขตอื่น ๆ 0 nคำนวณขั้นตอนต่อไป g iให้iขั้นตอนที่ ให้ระยะเวลาถ้าเริ่มต้นด้วย c x ล้อมรอบทั้งหมดเข้าด้วยกันxf

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]

(หมายเหตุ: โพสต์จากโทรศัพท์ที่มีล่าม hugs ซึ่งไม่โดดเด่นดังนั้นอาจมีการพิมพ์ผิด)


2

MATL , 38 37 36 35 ไบต์

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

สิ่งนี้ใช้ลูปที่ทำให้การคำนวณสถานะใหม่จนกว่าสถานะใหม่จะเท่ากับสถานะก่อนหน้าใด ๆ แต่ละรัฐเป็นเวกเตอร์ของศูนย์และคน เวกเตอร์เหล่านี้ถูกจัดเก็บเป็นแถวของอาร์เรย์ 2D ที่กำลังเติบโต

การคำนวณของแต่ละรัฐใหม่จะกระทำโดย convolving สถานะปัจจุบันกับลำดับ[1,0,1]การรักษาเฉพาะส่วนกลางและการตั้งค่า0รายการใด ๆ 1ที่ไม่ได้เป็น

แก้ไข (13 พฤษภาคม 2016) รหัสในลิงค์ต่อไปนี้ได้รับการแก้ไขเล็กน้อยตามการเปลี่ยนแปลงที่นำมาใช้ในภาษาหลังจากเขียนคำตอบนี้

ลองออนไลน์!

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 ไบต์

{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
  • Rเป็น meta-op ที่ฝืนอาร์กิวเมนต์ที่ให้กับ op ตัวอย่างเช่น1 R- 3จะส่งผลให้ 2

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

Pyth, 95 ไบต์

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

คุณสามารถลองมันออกมาที่นี่



โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.