Стрибки вказівника


21

Припустимо, у нас є масив довжини із вказівниками, що вказують на якесь місце в масиві: Процес " стрибки вказівника " встановить кожен вказівник на місце, на яке вказує вказівник.псн

Для цієї задачі покажчик - це (нульовий) індекс елемента масиву, це означає, що кожен елемент масиву буде більшим або рівним і менше . За допомогою цього позначення процес можна сформулювати так:0н

for i = 0..(n-1) {
  ps[i] = ps[ps[i]]
}

Це означає (для цього виклику), що покажчики оновлюються на місці в послідовному порядку (тобто спочатку нижчі індекси).

Приклад

Давайте попрацюємо на прикладі :ps = [2,1,4,1,3,2]

i = 0:елемент у положенні ps [0] = 2 вказує на 4ps = [4,1,4,1,3,2]i = 1:елемент у положенні ps [1] = 1 вказує на 1ps = [4,1,4,1,3,2]i = 2:елемент у положенні ps [2] = 4 вказує на 3ps = [4,1,3,1,3,2]i = 3:елемент у положенні ps [3] = 1 вказує на 1ps = [4,1,3,1,3,2]i = 4:елемент у положенні ps [4] = 3 вказує на 1ps = [4,1,3,1,1,2]i = 5:елемент у положенні ps [5] = 2 вказує на 3ps = [4,1,3,1,1,3]

Отже, після однієї ітерації « стрибка » ми отримуємо масив .[4,1,3,1,1,3]

Виклик

Даний масив з індексами виводить масив, отриманий ітерацією вищеописаного покажчика, стрибаючи, поки масив більше не змінюється.

Правила

Ваша програма / функція буде приймати та повертати / виводити одного типу, список / вектор / масив тощо

  • гарантовано є не порожнім і
  • гарантовано містить лише записи .0p<н

Варіанти: Ви можете вибрати

  • використовувати індексацію на основі 1 або
  • використовувати фактичні покажчики,

однак слід зазначити це у своєму поданні.

Тестові кейси

[0]  [0]
[1,0]  [0,0]
[1,2,3,4,0]  [2,2,2,2,2]
[0,1,1,1,0,3]  [0,1,1,1,0,1]
[4,1,3,0,3,2]  [3,1,3,3,3,3]
[5,1,2,0,4,5,6]  [5,1,2,5,4,5,6]
[9,9,9,2,5,4,4,5,8,1,0,0]  [1,1,1,1,4,4,4,4,8,1,1,1]


Чи дозволяється нам брати довжину nяк додатковий вхід?
Кевін Кройсейсен

2
@KevinCruijssen, дивіться цю мета-дискусію .
Кудлатий

Надто погано записи потрібно оновлювати послідовно; якби вони могли бути оновлені одночасно, у Mathematica було б рішення з 21 символом #[[#]]&~FixedPoint~#&.
Грег Мартін

Відповіді:






5

Свіфт , 68 53 байти

{a in for _ in a{var i=0;a.forEach{a[i]=a[$0];i+=1}}}

Спробуйте в Інтернеті!

-15 завдяки БМО


2
Ласкаво просимо до PPCG! Я не знаю Swift, але для codegolf.SE типовим є прийняття набраних лямбда-функцій, які, напевно, вважатимуть закриттям. Тож це може бути 53 байти (рахувати не потрібно f=). Приємного перебування тут!
ბიმო

Дякую за привітання та поради, які я використав для оновлення своєї відповіді.
Шон

Як щодо використання mapзамість того, forEachщоб скоротити його?
співали jaeyong

4

JavaScript (ES6), 41 байт

f=a=>a+''==a.map((x,i)=>a[i]=a[x])?a:f(a)

Спробуйте в Інтернеті!


Гах! Я чекав, коли цей виклик буде опублікований, щоб я міг опублікувати саме таке рішення: \ Чорт ваші навички ніндзя! : p
Shaggy

2
@shaggy 🐱‍👤 (це повинен бути кіт ніндзя ... але це, мабуть, не підтримується всюди)
Арнольд


4

Japt, 15 13 7 байт

Змінює вихідний вхідний масив.

££hYXgU

Спробуйте (додаткові байти - це записати змінений вхід на консоль)

££hYXgU
£           :Map
 £          :  Map each X at index Y
  hY        :    Replace the element at index Y
    XgU     :    With the element at index X

4

Java 8, 105 54 байти

a->{for(int l=a.length,i=0;i<l*l;)a[i%l]=a[a[i++%l]];}

Змінює вхідний масив замість повернення нового для збереження байтів.

ленгтгод2

Спробуйте в Інтернеті.

Пояснення:

a->{                // Method with integer-array parameter and no return-type
  int l=a.length,   //  Length of the input-array
  i=0;i<l*l;)       //  Loop `i` in the range [0, length squared):
    a[i%l]=         //   Set the (`i` modulo-length)'th item in the array to:
      a[            //    The `p`'th value of the input-array,
        a[i++%l]];} //    where `p` is the (`i` modulo-length)'th value of the array

3

Japt , 17 байт


®
£hYUgX
eV ?U:ß

Спробуйте всі тестові випадки

Це здається, що воно повинно бути коротшим, але, на жаль, моя початкова думка про UmgUце не працює, оскільки кожен gотримує доступ до оригіналу, Uа не змінює його на кожному кроці. Збереження різних компонентів належним чином коштуватиме і кілька байтів.

Пояснення:

           #Blank line preserves input in U long enough for the next line

®          #Copy U into V to preserve its original value

£hY        #Modify U in-place by replacing each element X with...
   UgX     #The value from the current U at the index X

eV ?U      #If the modified U is identical to the copy V, output it
     :ß    #Otherwise start again with the modified U as the new input




2

R , 60 58 байт

-2 байти завдяки @digEmAll за читання правил.

function(x,n=sum(x|1)){for(i in rep(1:n,n))x[i]=x[x[i]];x}

Спробуйте в Інтернеті!

1-індексований.

n - довжина вхідного масиву.

rep(1:n,n)повторення 1:n nразів (наприклад n=3 => 1,2,3,1,2,3,1,2,3)

Проведіть цикл через масив n. Стаціонарний стан буде досягнуто тоді точно, фактично до кінця п ятого разу, я думаю. Доказ залишається читачеві.


1
Я думаю, ви можете видалити +1та просто взяти 1-й вхід, повідомлення повідомляє: Ви можете скористатися індексуванням на основі 1
digEmAll

-4 шляхом переходу на scan()вхід. Я завжди відчуваю , що мої scan()рішення неоптимальним, так що стежте за більш короткий шлях для призначення xі nразом: n=length(x<-scan());for(i in rep(1:n,n))x[i]=x[x[i]];x Спробуйте його в Інтернеті!
Кримінально-



2

Clojure , 136 байт

(defn j[a](let[f(fn[a](loop[i 0 a a](if(= i(count a))a(recur(inc i)(assoc a i(a(a i)))))))](loop[p nil a a](if(= p a)a(recur a(f a))))))

Спробуйте в Інтернеті!


Привіт і ласкаво просимо до PPCG. Чи вдасться вам надати посилання на онлайн-перекладача таким чином, щоб можна було легко перевірити ваше рішення? Крім того, loop [не може стати loop[?
Джонатан Фрех

1
Остання редакція повинна виправити помилки тесту. Вибачте за незручності всім.
Етан МакКью

1

Perl 5, 35 34 26 байт

використовуючи той факт, що конвергенція досягається максимум для величини кількості ітерацій

$_=$F[$_]for@F x@F;$_="@F"

26 байт

$_=$F[$_]for@F;/@F/ or$_="@F",redo

34 байти

$_=$F[$_]for@F;$_="@F",redo if!/@F/

35 байт



1

Вугілля деревне , 16 байт

FθFLθ§≔θκ§θ§θκIθ

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. На жаль, всі звичайні функції відображення функціонують лише на копії масиву, в результаті чого вони просто переймають елементи, а не стрибають їх, тому код повинен робити все вручну. Пояснення:

Fθ

Повторіть внутрішню петлю один раз для кожного елемента. Це просто забезпечує стабілізацію результату.

FLθ

Проведіть петлю над індексами масиву.

§≔θκ§θ§θκ

Отримайте елемент масиву в поточному індексі, використовуйте його для індексації у масиві та замініть поточний елемент цим значенням.

Iθ

Перекиньте елементи на рядок і неявно роздрукуйте кожен у власному рядку.


1

F #, 74 73 байт

fun(c:'a[])->let l=c.Length in(for i in 0..l*l do c.[i%l]<-c.[c.[i%l]]);c

Нічого особливого. Використовує ідею модуля, яку бачите в інших відповідях.


1

К, 27 байт

{{@[x;y;:;x x y]}/[x;!#x]}/
  • {..}/ застосовується лямбда {..} над arg (до конвергенції)

  • всередині зовнішньої лямбда:

    • {..}/[x;y]застосовується лямбда-ітераційно над x (оновлюється при кожній ітерації) та елементом y (y - це список значень, і використовується елемент при кожній ітерації). У цьому випадку arg y є !#x(til count x, тобто індекси масиву)

    • @[x;y;:;x x y] змінити масив x (в індексі y призначити x [x [y]])


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