กระโดดข้ามแถว!


19

ลองเล่นเกมที่ผู้เล่นคนหนึ่งที่เรียกว่ากระโดดอาร์เรย์ ในการเล่นคุณต้องใช้อาร์เรย์ของจำนวนเต็มaเท่านั้น คุณเริ่มที่บางตำแหน่งiและในแต่ละตาคุณจะข้ามไปยังตำแหน่งใหม่ ที่เปิดn,

  • ถ้าnเป็นแม้กระทั่งคุณจะกระโดดไปยังตำแหน่งที่แน่นอนa[i] mod length(a),
  • ถ้าแปลกที่คุณจะกระโดดไปยังตำแหน่งญาติn(i + a[i]) mod length(a)

การจัดทำดัชนีอาร์เรย์เริ่มต้นที่ศูนย์ คุณสามารถนับการกระโดดครั้งแรกเป็นเทิร์น0หรือเทิ1ร์นซึ่งให้เกมอื่น เนื่องจากพื้นที่ของเกมนั้นมี จำกัด (การเคลื่อนไหวของคุณถูกกำหนดโดยตำแหน่งของคุณและความเท่าเทียมกันของจำนวนรอบ) คุณจะต้องเข้าสู่วงที่มีความยาวเท่ากัน แสดงว่าโดยความยาวของวงนี้เมื่อกระโดดครั้งแรกนับเป็นเปิดloop(a, i, b)b

อินพุต

อาร์เรย์aจำนวนเต็มที่ไม่มีข้อ จำกัด ในการเล่นเกมด้วย

เอาท์พุต

จำนวนสูงสุดpดังกล่าวว่าเมื่อเริ่มต้นในบางตำแหน่งiและนับเป็นครั้งแรกที่เปิดอย่างใดอย่างหนึ่ง0หรือคุณที่สุดใส่ห่วงความยาว1 2 * pอีกนัยหนึ่งผลลัพธ์ของคุณคือจำนวน

max { loop(a, i, b)/2 : i in [0 .. length(a)-1], b in [0,1] }

กฎระเบียบ

คุณสามารถให้ฟังก์ชั่นหรือโปรแกรมเต็มรูปแบบ จำนวนไบต์ที่น้อยที่สุดชนะและช่องโหว่มาตรฐานไม่ได้รับอนุญาต

กรณีทดสอบ

[0] -> 1
[-213] -> 1
[1,3,12,-1,7] -> 1
[2,3,5,7,9,11,13,17,19] -> 2
[-2,3,-5,7,-9,11,-13,17,-19,23,-27] -> 3
[0,2,5,4,-9,0,-1,1,-1,1,-6] -> 4

@ kukac67 ใช่มันเป็นตัวเลือกหลังอย่างที่ Martin พูด
Zgarb

ฉันคิดว่าmodมันถูกนิยามว่าเป็นบวกเสมอ ( -1 mod 5 == 4) ไม่เหมือนกับใน C ใช่ไหม?
nutki

@ nutki ใช่ฉันใช้สไตล์ Haskell modซึ่งให้ผลลัพธ์ที่ไม่ใช่ค่าลบเสมอ
Zgarb

หากการเปลี่ยนดัชนีเป็นศูนย์ให้ผลที่แตกต่างจากการทำดัชนีหนึ่งเราควรส่งออกผลลัพธ์อย่างใดอย่างหนึ่งหรืออย่างใดอย่างหนึ่งน้อย
KSFT

@ MartinBüttnerไม่ฉันถูกถามเกี่ยวกับการจัดทำดัชนีการหมุนไม่ใช่อาร์เรย์
KSFT

คำตอบ:


6

Pyth : 28 ตัวอักษร (Python 2: 116 ตัวอักษร)

eSmhxtu+G%@Q+eG@QeGlQUQ]ddUQ

การใช้งาน:

ลองที่นี่: Pyth Compiler / Executor

คาดว่ารายการของจำนวนเต็มเป็นอินพุต [0,2,5,4,-9,0,-1,1,-1,1,-6]

คำอธิบาย:

ฉันสังเกตเห็นคุณสมบัติที่สำคัญอย่างหนึ่งของฟังก์ชั่นloop: สำหรับแต่ละอันiก็มีjเช่นนั้นloop(a,i,0) == loop(a,j,1)และในทางกลับกัน ดังนั้นเราต้องคำนวณค่าloop(a,i,b)สำหรับb=0เท่านั้น

พิสูจน์: ถ้าเป็นวงจรi -> j -> k -> ... -> z -> iที่มีb = 0นั้นมีอยู่รอบด้วยj -> k -> ... -> z -> i -> jb = 1

ดังนั้นสคริปต์แบบง่ายสามารถทำงานได้ด้วยวิธีต่อไปนี้ ทำซ้ำทั้งหมดiและพยายามเข้าถึงiด้วยการคำนวณซ้ำi = a[(i + a[i]) mod len(a)] mod len(a)ๆ เนื่องจากการคำนวณนี้อาจวิ่งเข้าไปในรอบที่ไม่มีiเราจึงยกเลิกการคำนวณหลังจากlen(a)ขั้นตอน จากนั้นเราจะพิมพ์รอบสูงสุด

การใช้งานPython 2มีลักษณะเช่นนี้ ( 125 ตัวอักษร }:

a=input();A=len(a);m=[]
for i in range(A):
 j=i
 for c in range(A):
  j=a[(j+a[j])%A]%A
  if i==j:m+=[c+1];break
print max(m)

สำหรับการดำเนินการ pyth ฉันใช้วิธีที่แตกต่างกันเล็กน้อย สำหรับiฉันแต่ละคนคำนวณรายการของตำแหน่งและมองหาiในรายการนี้

eSmhxtu+G%@Q+eG@QeGlQUQ]ddUQ  
  m                       UQ    for each d in [0, ..., len(input)-1] compute a
      u                ]d         list G (using reduce), 
                                  which is first initialized with G = [d]
                     UQ           for each H in [0, ..., len(input)-1]:
       +G                            append to G the value
         %@Q+eG@QeGlQ                   input[G[-1] +input[G[-1]] % len(input)
                                        (notice that list lookups in pyth work with modular wrapping)
     t                            remove the first value (which is d)
    x                    d        and find the index of d in this shortend list
                                  (it's -1, if d is not in the list)
   h                              add 1
eS                              print the maximum (end of sorted list)  

แก้ไข: Python 2: 116 ตัวอักษร

@proud haskeller 's solution คือฉันมีตัวละครสั้นกว่า Python ของฉันเพียงไม่กี่ตัวอักษรดังนั้นฉันจึงต้องย่อให้สั้นลงเล็กน้อย

a=input();A=len(a);l=lambda j,i,c:c<=A and(c*(i==j)or l(a[(j+a[j])%A]%A,i,c+1));print max(l(i,i,0)for i in range(A))

ความแตกต่างคือฉันคำนวณตัวเลขซ้ำ ๆ ซ้ำ ๆ


8

Python - 157

a=input()
z=len(a)
b=[]
for i in range(z):
    s,c,t=[],"",0
    while(c in s[:-1])-1:j=(i*t+a[i])%z;c=`t`+`i`;s+=[c];t^=1
    b+=[len(s)-s.index(c)-1]
print max(b)/2

1
หากคุณใส่len(a)ตัวแปรและแทนที่len(a)s ทั้งหมดด้วยชื่อของตัวแปรนั้นคุณสามารถบันทึกอักขระบางตัวได้
ProgramFOX

1
แนวคิดบางอย่าง: t+=1;t%=2-> t^=1และ if t: j=(j+a[j])%z else: j=a[j]%z->j=(t*j+a[j])%z
Vectorized

1
ใช้เพียงช่องว่างเดียวในการเยื้อง บันทึก 9 ตัวอักษรที่นี่
PurkkaKoodari

1
ความคิดก็: อาจจะเป็นwhile c not in s[:-1]: while(c in s[:-1])-1:
PurkkaKoodari

1
และอีกหนึ่ง คุณไม่จำเป็นต้องใช้jเนื่องจากการวนซ้ำนี้กำหนดเนื้อหาของrange(z)ถึงiแทนที่จะเป็นการเพิ่ม เพียงแทนที่jด้วยiเพื่อบันทึก 4 ตัวอักษร
PurkkaKoodari

5

Haskell, 120 105

f s|t<-l s=maximum[g$drop t$iterate(\i->s!!mod(i+s!!mod i t)t)i|i<-s]
g(x:s)=l$0:fst(span(/=x)o)
l=length

สิ่งนี้จะสร้างรายการที่ไม่มีที่สิ้นสุดสำหรับแต่ละจุดเริ่มต้น (สำหรับเหตุผลในการเล่นกอล์ฟเราวนซ้ำค่าทั้งหมดแทนที่จะเป็นดัชนีทั้งหมดซึ่งเทียบเท่ากัน) จากนั้นจะคำนวณรอบของแต่ละรายการ (ความยาวของรอบxsคือxs % [])

มันใช้การสังเกตของ @ jakubes เกี่ยวกับรอบ เนื่องจากเป็นขั้นตอน 2 ขั้นในแต่ละครั้งเราไม่จำเป็นต้องหารด้วย 2 ในตอนท้าย

แก้ไข : ตอนนี้ใช้เคล็ดลับของ @ MthViewMark ในการวางnองค์ประกอบแรกเพื่อรับประกันว่าจะมีรอบที่มีองค์ประกอบแรก อย่างไรก็ตามฉันจัดการกอล์ฟอัลกอริทึมของเขากับ112ตัวละคร:

l=length
o(x:y)=1+l(takeWhile(/=x)y)
j a|n<-l a=maximum$map(o.drop n.iterate(\i->mod(a!!mod(i+a!!i)n)n))[0..n-1]

2

Haskell - 139 ตัวอักษร

l=length
o(x:y)=1+l(takeWhile(/=x)y)
j a=maximum$map(o.drop n.iterate(b!!))[0..n-1]
 where b=zipWith(\x y->mod(a!!mod(x+y)n)n)a[0..];n=l a

ตัวอย่าง:

λ: j [0]
1

λ: j [-213]
1

λ: j [1,3,12,-1,7]
1

λ: j [2,3,5,7,9,11,13,17,19]
2

λ: j [-2,3,-5,7,-9,11,-13,17,-19,23,-27]
3

λ: j [0,2,5,4,-9,0,-1,1,-1,1,-6]
4

สิ่งนี้ใช้ประโยชน์จากการสังเกตของ @ jakube ที่คุณต้องการตรวจสอบเพียงครึ่งเดียวของค่าเริ่มต้นในขณะที่ดำเนินการ 2 ขั้นตอนต่อการทำซ้ำ


คุณสามารถ squish ไปก่อนหน้านี้where ]นอกจากนี้คุณลองใช้cycle l!!iแทนl!!mod n(length l)หรือไม่
ภูมิใจ haskeller

นอกจากนี้คุณสามารถ inline bและใช้ยามรูปแบบที่จะกำจัด|n<-l a where
ภูมิใจ haskeller

2

Python, 160

l=lambda a,b,c,d:(b,c)in d and len(d)-d.index((b,c))or l(a,(a[b]+[0,b][c])%len(a),~c,d+[(b,c)])
j=lambda a:max(l(a,b,c,[])for b in range(len(a))for c in(0,1))/2

jฟังก์ชั่นสำหรับคำตอบคือ
ฟังก์ชั่นวนซ้ำlจะส่งกลับค่าความยาวลูปสำหรับอาร์เรย์ที่กำหนดเริ่มต้นและเทิร์นแรกจากนั้นฟังก์ชันjจะค้นหาค่าสูงสุด


lambdaฉันคิดว่าคุณสามารถบันทึกตัวอักษรบางตัวด้วยการกำหนดญกับ
KSFT

1

Mathematica, 189 162 161 ไบต์

หากฟังก์ชั่นที่ไม่ระบุชื่อได้รับอนุญาต - 161 ไบต์:

Max[l=Length;Table[b={};n=p;i=s-1;e:={i,n~Mod~2};While[b~Count~e<2,b~AppendTo~e;h=#[[i+1]];i=If[EvenQ@n++,h,i+h]~Mod~l@#];l@b-b~Position~e+1,{s,l@#},{p,0,1}]/4]&

มิฉะนั้น - 163 ไบต์:

f=Max[l=Length;Table[b={};n=p;i=s-1;e:={i,n~Mod~2};While[b~Count~e<2,b~AppendTo~e;h=#[[i+1]];i=If[EvenQ@n++,h,i+h]~Mod~l@#];l@b-b~Position~e+1,{s,l@#},{p,0,1}]/4]&

ใช้สิ่งนี้ในทุกกรณีทดสอบ:

f /@ {
  {0},
  {-213},
  {1, 3, 12, -1, 7},
  {2, 3, 5, 7, 9, 11, 13, 17, 19},
  {-2, 3, -5, 7, -9, 11, -13, 17, -19, 23, -27},
  {0, 2, 5, 4, -9, 0, -1, 1, -1, 1, -6}
}

ผลลัพธ์ใน:

{1, 1, 1, 2, 3, 4}

Python 2, 202 ไบต์

def l(a,n,i):
 b=[]
 while not[i,n]in b:b.append([i,n]);i=(a[i]if n<1 else i+a[i])%len(a);n+=1;n%=2
 return len(b)-b.index([i,n])
def f(a):print max([l(a,n,i) for n in[0,1]for i in range(len(a))])/2

การสาธิต

นี่เป็นเกือบเป็นคำตอบในวิชาคณิตศาสตร์ของฉัน


มันดูคล้ายกับของฉันมาก ตอนแรกฉันถูกปิดโดยหนึ่ง (ก่อนหารด้วยสอง) ในตอนแรก ฉันยังไม่แน่ใจว่าทำไม แต่ฉันลบหนึ่งก่อนที่จะหาร
KSFT

ฉันไม่รู้ Mathematica ดังนั้นฉันจึงไม่สามารถช่วยได้มากขึ้น
KSFT

@Zarb Oh! นั่นอธิบายทุกอย่าง ฉันไม่ได้คิดอย่างนั้น ขอบคุณ!
kukac67

Forด้วย 3 ข้อโต้แย้งมักจะสั้นกว่าWhile(เนื่องจากคุณสามารถบันทึกอัฒภาคไว้ข้างหน้าFor)
Martin Ender

1

Mathematica, 113 112 ตัวอักษร

l=Length;m=MapIndexed;f=Max[l/@ConnectedComponents@Graph@m[Tr@#2->#&,Part@@Thread@Mod[#+{Tr@#2,1}&~m~#,l@#,1]]]&

ตัวอย่าง:

f /@ {
  {0},
  {-213},
  {1, 3, 12, -1, 7},
  {2, 3, 5, 7, 9, 11, 13, 17, 19},
  {-2, 3, -5, 7, -9, 11, -13, 17, -19, 23, -27},
  {0, 2, 5, 4, -9, 0, -1, 1, -1, 1, -6}
}

{1, 1, 1, 2, 3, 4}


1

มีค่า 82

ised '@1{0,2,5,4,-9,0,-1,1,-1,1,-6};@2{1};' '@{4 5}{(@3{:$1_x++x*@2{1-$2}:}2*#$1)::[#$1]};{1+?{:@5{$3::$5}=$4:}@::[2*#$1]_0}/2'

อาร์กิวเมนต์แรกไม่นับเป็นความยาว (การกำหนดค่าเริ่มต้นของอาร์เรย์เป็น$1และbเริ่มต้นใน$2- เลือก "เกม")

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