Розкладіть перестановку на цикли


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 символи в J:>C.
Eelvex

Скажімо, N <1000.
Кіт Рендалл

Перестановки зазвичай рахуються від 1, а не до 0.
Доктор Белісарій

6
Математики нараховують від 1, комп'ютерні - від 0 :)
Кіт Рендалл

Відповіді:


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


Чи законно називати неявно оголошені різноманітні функції? Чи законно спочатку пропустити int?
6502

Законно робити що-небудь, поки код працює. Хоча він може давати попередження, якщо він не дає помилок, він повинен бути Ок.
fR0DDY

Сама суть полягає у значенні «твори». У будь-якому випадку я додав відповідь (139 знаків), що використовує це правило (тобто там, де "працює" означає "є принаймні один самодекларований компілятор C, в якому, мабуть, працює створений машинний код")
6502

+1: Мені подобається gets(&i)ідея позбутися цього марного першого рядка, проте це явно не буде працювати в 16-бітових системах, якщо передано більше 10 елементів. Але ще раз, якщо правила "знаходять принаймні програму, яка претендує на компілятор C, який створює виконуваний файл, де хоча б в одному випадку, здається, - принаймні, мені - дати дійсну відповідь", тоді це поліпшення: - )
6502

2

Python 131 chars

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

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("");}}

Остаточний новий рядок не включається.

Я сказав "начебто", тому що AFAIK, наприклад

  1. не допустимо пропускати декларацію для різноманітних функцій (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.
Кіхот

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

Я не зовсім зрозумілий у форматі вводу-виводу, але я думаю, що C.це зробить, якщо буде прийнято наступний вихід:

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

(Це краще виглядає в J-терміналі.)

Якщо це має бути названа функція, яка відповідає моєму найкращому розумінню формату вводу-виводу, це 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, і збільште його на індекс. Ми насправді не хочемо передачі рядків, ми хочемо масив, який слідує за ним.
  • }.~ - Вибирає ту частину введення, яку ми бажаємо.
  • ".- Оскільки формат введення є дійсним J ( * \ õ / * ), ми можемо просто використовувати evalдієслово (я знаю, що його насправді не називають eval.), Щоб перетворити його на масив
  • C.- Чиста магія. Я справді не маю уявлення, що це робить, але, здається, працює!
  • ":L:0- Представництво. Перетворює вихід C.у рамку послідовності рядків
  • >- Відкрити. Фактичний вихід є насправді рядковим масивом (за першими числами прикладу є пробіли).

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

Дещо нерозпущеним і розбитим на функцію (вхід повинен бути вектором, який саме (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-х років. О, добре, весело це робили!)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.