สลายการเปลี่ยนรูปเป็นวัฏจักร


15

มีทฤษฎีบทที่รู้จักกันดีว่าคือการเปลี่ยนแปลงใด ๆ ที่สามารถย่อยสลายเป็นชุดของรอบ งานของคุณคือการเขียนโปรแกรมที่สั้นที่สุดเท่าที่จะทำได้

การป้อนข้อมูล:

สองเส้น ตัวแรกประกอบด้วยตัวเลขNส่วนที่สองมีNจำนวนเต็มชัดเจนในช่วง[0,N-1]คั่นด้วยช่องว่าง จำนวนเต็มเหล่านี้แสดงถึงการเปลี่ยนแปลงของNองค์ประกอบ

เอาท์พุท:

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

รอบสามารถส่งออกในลำดับใด ๆ และแต่ละรอบสามารถส่งออกเริ่มต้นที่ตำแหน่งใด ๆ

ตัวอย่างที่ 1:

8
2 3 4 5 6 7 0 1

อินพุตนี้เข้ารหัสการเปลี่ยนแปลง 0-> 2, 1-> 3, 2-> 4, 3-> 5, 4-> 6, 5-> 7, 6-> 0, 7-> 1 สิ่งนี้จะสลายตัวเป็นวัฏจักรเช่นนี้:

0 2 4 6
1 3 5 7

ผลลัพธ์ที่ถูกต้องเท่าเทียมกันจะเป็น

5 7 1 3
2 4 6 0

ตัวอย่างที่ 2:

8
0 1 3 4 5 6 7 2

ผลลัพธ์ที่ถูกต้อง:

0
1
4 5 6 7 2 3

@Keith มูลค่าสูงสุดของ N คือเท่าใด
fR0DDY

3
3 chars ใน J:>C.
Eelvex

สมมุติว่า N <1,000
Keith Randall

การเรียงสับเปลี่ยนมักนับจาก 1 ไม่ใช่ 0
ดร. เบลิซา

6
นักคณิตศาสตร์นับจาก 1 นักวิทยาศาสตร์คอมพิวเตอร์นับจาก 0 :)
Keith Randall

คำตอบ:


4

C 145 134 ตัวอักษร

N,A[999],i,j,f;main(){gets(&i);for(;~scanf("%d",A+N);)N++;for(;j<N;j++,f=f&&!puts(""))while(i=A[j]+1)f=printf("%d ",j),A[j]=-1,j=--i;}

http://www.ideone.com/BrWJT


มันถูกกฎหมายหรือไม่ที่จะเรียกใช้ฟังก์ชัน Variadic ที่ประกาศโดยนัย? มันถูกกฎหมายintหรือไม่ที่จะละเว้นเสียก่อน?
6502

มันถูกกฎหมายที่จะทำอะไรตราบใดที่รหัสทำงาน ในขณะที่มันอาจให้คำเตือนตราบใดที่มันไม่ได้ให้ข้อผิดพลาดก็ควรจะตกลง
fR0DDY

ประเด็นสำคัญอยู่ที่ความหมายของ "งาน" อย่างไรก็ตามฉันได้เพิ่มคำตอบ (139 ตัวอักษร) ที่ใช้กฎนี้ (เช่นที่ "งาน" หมายถึง "มีคอมไพเลอร์ C ที่ประกาศตัวเองอย่างน้อยหนึ่งตัวซึ่งเห็นได้ชัดว่ารหัสเครื่องที่สร้างขึ้นใช้งานได้")
6502

+1: ฉันชอบgets(&i)ความคิดที่จะกำจัดบรรทัดแรกที่ไร้ประโยชน์อย่างไรก็ตามสิ่งนี้ไม่สามารถใช้ได้กับระบบ 16 บิตหากผ่านมากกว่า 10 องค์ประกอบ แต่อีกครั้งหากกฎคือ "ค้นหาอย่างน้อยโปรแกรมที่อ้างว่าเป็นคอมไพเลอร์ C ที่สร้างปฏิบัติการที่ในกรณีอย่างน้อยหนึ่งกรณี - อย่างน้อยสำหรับฉัน - เพื่อให้การตอบสนองที่ถูกต้อง" นี่คือการปรับปรุง: - )
6502

2

Python 131 ตัวอักษร

input();d=dict((i,int(x))for i,x in enumerate(raw_input().split()))
while d:
 x=list(d)[0]
 while x in d:print x,;x=d.pop(x)
 print

ไม่จำเป็นต้องขึ้นบรรทัดใหม่


1

Haskell, 131 ตัวอักษร

n%l|all(>n)l=(n:l>>=(++" ").show)++"\n"|1<3=""
c(_:a)=a>>=(\n->n%(takeWhile(/=n)$iterate(a!!)$a!!n))
main=interact$c.map read.words
  • แก้ไข: (135 -> 131) >=กลาย>กำจัดสองtailสายแม้ว่าจับคู่รูปแบบและ a!!pre-ประยุกต์ใช้

1

C (เรียงลำดับ) 139 ตัวอักษร

n,j,t,a[999];main(){scanf("%*i");for(;scanf("%i",a+n)>0;)n++;while(n--)if(a[j=n]+1){for(;t=a[j]+1;a[j]=-1,j=t)printf("%i ",--t);puts("");}}

บรรทัดใหม่สุดท้ายไม่รวม

ฉันพูดว่า "sort-of" เพราะ AFAIK เป็นต้น

  1. มันไม่ถูกต้องที่จะละเว้นการประกาศสำหรับฟังก์ชัน Variadic (ANSI C89: 3.3.2.2)
  2. int ไม่สามารถละเว้นสำหรับการประกาศตัวแปรได้ (ฉันไม่พบที่กล่าวว่าสามารถละเว้นได้และการประกาศประเภทโดยนัยนั้นมีไว้สำหรับฟังก์ชั่นเท่านั้นข้อกำหนดทางไวยากรณ์ในมาตรฐานนั้นไร้ประโยชน์โดยทั่วไปเมื่อยอมรับการประกาศ C ที่ถูกต้องเช่น double double void volatile x; )
  3. ขึ้นบรรทัดใหม่ในตอนท้ายของไฟล์ต้นฉบับที่ไม่ว่างเปล่าเป็นข้อบังคับ (ANSI C89: A.6.2)

แต่โค้ดข้างต้นที่คอมไพล์ด้วยgcc -ocycles cycles.cเห็นได้ชัดว่าทำงานได้อยู่แล้ว


นี่เป็นโปรแกรม C ที่ถูกต้อง แต่นี่ไม่ใช่ C99
Quixotic

@Debanjan: ไม่ไม่ใช่ ANSI C (ไม่ใช่ 89) ตัวอย่างเช่นมาตรฐานบอกว่า (3.3.2.2) ว่าถ้าฟังก์ชั่นใช้จำนวนตัวแปรของการขัดแย้งแล้วมันไม่สามารถประกาศได้โดยปริยายที่ฟังก์ชั่นการโทรเว็บไซต์ (ในคำอื่น ๆ ที่คุณไม่สามารถโทรscanfโดยไม่ต้อง#include <stdio.h>แม้ว่าพารามิเตอร์ถูกต้องและไม่จำเป็นต้องแปลง ):<<If the function is defined with a type that includes a prototype, and the types of the arguments after promotion are not compatible with the types of the parameters, or if the prototype ends with an ellipsis ( ", ..." ), the behavior is undefined.>>
6502

1

J (ระหว่าง 2 ถึง 32)

ฉันไม่ชัดเจนในรูปแบบ i / o แต่ฉันคิดว่าC.จะทำอย่างไรหากผลลัพธ์ต่อไปนี้ได้รับการยอมรับ:

   C. 0 1 3 4 5 6 7 2
┌─┬─┬───────────┐
│0│1│7 2 3 4 5 6│
└─┴─┴───────────┘

(มันดูดีขึ้นในขั้ว J)

หากจำเป็นต้องมีฟังก์ชั่นที่ตั้งชื่อซึ่งเป็นไปตามความเข้าใจที่ดีที่สุดของฉันในรูปแบบ i / o นั่นคือ 32 อักขระซึ่ง 30 สำหรับการแปลงรูปแบบเอาต์พุต ...

g=:>@(":L:0)@(C.@".@}.~>:@i.&LF)

ในการดำเนินการ:

   g=:>@(":L:0)@(C.@".@}.~>:@i.&LF)
   g
>@(":L:0)@(C.@".@}.~ >:@i.&(10{a.))
   t
8
0 1 3 4 5 6 7 2
   g t
0          
1          
7 2 3 4 5 6

คำอธิบาย:

J ถูกดำเนินการจากขวาไปซ้าย (ในทางปฏิบัติ) @เป็น 'ฟังก์ชั่น' (ไม่ใช่ในทางเทคนิคฟังก์ชั่น แต่มันใกล้พอ) เพื่อรวมฟังก์ชั่น

  • i.&LF - หาดัชนีแรกของ LFซึ่งเป็นตัวแปรที่กำหนดไว้ล่วงหน้าซึ่งมีหมายเลขอักขระ ASCII 10 ตัวดึงข้อมูลบรรทัด
  • >: - หาคนแรก LFและเพิ่มค่าดัชนีทีละหนึ่ง เราไม่ต้องการ linefeed เราต้องการอาร์เรย์ที่ตามมา
  • }.~ - เลือกส่วนของอินพุตที่เราต้องการ
  • ".- เนื่องจากรูปแบบอินพุตถูกต้อง J ( * \ õ / * ) เราจึงสามารถใช้evalกริยา (ฉันรู้ว่ามันไม่ได้เรียกจริง ๆ แล้วevalๆ ) เพื่อเปลี่ยนเป็นอาร์เรย์
  • C.- เวทมนต์บริสุทธิ์ ฉันไม่รู้จริงๆว่ามันทำอะไร แต่ดูเหมือนว่าจะใช้ได้!
  • ":L:0- การเป็นตัวแทน เปลี่ยนเอาท์พุตของC.ให้เป็นลำดับของสตริง
  • >- Unbox เอาท์พุทที่เกิดขึ้นจริงเป็นจริงสตริงอาร์เรย์ (มีช่องว่างหลังตัวอย่างแรกของตัวเลข)

0

Clojure, 145

(let[v(vec(repeatedly(read)read))](loop[a(set v)b 0](cond(a(v b))(do(print" "b)(recur(disj a(v b))(v b)))(seq a)(do(prn)(recur a(first a)))1"")))

ค่อนข้าง ungolfed และแยกออกเป็นฟังก์ชั่น (ข้อมูลจะต้องเป็นเวกเตอร์ซึ่งเป็นสิ่งที่ (vec (อ่านซ้ำ ๆ (อ่าน))) จากการผลิตดังกล่าวข้างต้น):

(defn p [v]
  (loop [a (set v) b 0]
    (cond
     (a (v b)) (do (print" "b) (recur (disj a (v b)) (v b)))
     (seq a) (do (prn) (recur a (first a)))
     1 "")))

(ว้าวเพิ่งจะสังเกตเห็นความท้าทายนี้อายุมากกว่า 3 ปีโอ้สบายสนุกกับการทำมันต่อไป!)

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