Сортировка элементов на основе зависимости

12

Цель

Сортируйте список элементов, убедившись, что каждый элемент указан после указанных зависимостей.

вход

Массив массивов целых чисел, где каждое целое число указывает на индекс 0 или 1 другого элемента, за которым должен следовать этот элемент. Входные данные могут быть массивом или строкой или чем-либо еще, удобочитаемым человеком.

Например, ввод на основе 0:

[
  [ 2 ],    // item 0 comes after item 2
  [ 0, 3 ], // item 1 comes after item 0 and 3
  [ ],      // item 2 comes anywhere
  [ 2 ]     // item 3 comes after item 2
]

Предположим, что нет циклических зависимостей, всегда есть хотя бы один действительный порядок.

Выход

Числа в порядке зависимости. Неоднозначный порядок не должен быть детерминированным. Вывод может быть массивом или текстом или чем-либо еще, удобочитаемым для человека.

На выходе должен быть указан только один заказ, даже если существует несколько действительных заказов.

Возможные выходы для вышеуказанного ввода включают в себя:

[ 2, 3, 0, 1 ]
[ 2, 0, 3, 1 ]

счет

Функция или программа, которая завершает это за наименьшее количество байтов, завоевывает славу принятия. Срок - 6 дней.

Hand-E-Food
источник
4
Это называется топологическая сортировка для любопытных.
Роберт Фрейзер,
Входные данные могут быть массивом или строкой или чем-либо еще, удобочитаемым человеком. Просто чтобы убедиться: это может быть двумерный массив с нулями и единицами, где один указывает на зависимость, а ноль указывает на отсутствие зависимости?
Луис Мендо
@DonMuesli, извините за поздний ответ, но нет. Идея пришла из кодовых зависимостей. Если вы добавили другой модуль кода, было бы безответственно изменять модули нерелевантного кода, чтобы объявить, что они не зависят от этого нового модуля.
Hand-E-Food
Это полностью имеет смысл. Разве Деннис не должен быть победителем?
Луис Мендо
Да, он. Извините, поздняя стрессовая ночь и стремительный ход, основанный на предположениях.
Hand-E-Food

Ответы:

3

Желе, 8 байт

ịÐL³ŒḊ€Ụ

Это основано на (не реализованном) подходе глубины из ответа Python @ xnor .

Попробуйте онлайн!

Как это устроено

ịÐL³ŒḊ€Ụ  Main link. Input: A (list of dependencies)

 ÐL       Apply the atom to the left until a loop is reached, updating the left
          argument with the last result, and the right argument with the previous
          left argument.
ị         For each number in the left argument, replace it with the item at that
          index in the right argument.
   ³      Call the loop with left arg. A (implicit) and right arg. A (³).
    ŒḊ€   Compute the depth of each resulting, nested list.
       Ụ  Sort the indices of the list according to their values.
Деннис
источник
Будут ли эти 8 символов на самом деле 19 байтов?
Hand-E-Food
@ Hand-E-Food Jelly использует пользовательскую кодировку (не UTF 8), поэтому каждый символ является байтом
Луис Мендо,
@ Hand-E-Food Дон Мюсли правильно. Jelly использует эту кодовую страницу по умолчанию, которая кодирует все символы, которые она понимает, как один байт каждый.
Денис
7

Pyth, 21 байт

hf.A.e!f>xYTxkTbQ.plQ
                    Q  input
                   l   length of input array
                 .p    all permutations of [0, 1, ..., lQ-2, lQ-1]
hf                     find the first permutation for which...
    .e          Q        map over the input array with indices...
       f       b           find all elements in each input subarray where...
        >xYT                 index of dependency is greater than...
            xkT              index of item
      !                    check whether resulting array is falsy (empty)
  .A                     is the not-found check true for [.A]ll elements?

Тестовое задание:

llama@llama:~$ echo '[[2],[0,3],[],[2]]' | pyth -c 'hf.A.e!f>xYTxkTbQ.plQ' 
[2, 0, 3, 1]
Дверная ручка
источник
7

Python 2, 73 байта

l=input()
f=lambda n:1+sum(map(f,l[n]))
print sorted(range(len(l)),key=f)

Сортирует вершины по их количеству потомков, которое fвычисляется рекурсивно. Если вершина указывает на другую вершину, ее потомки включают остроконечную вершину и всех потомков этой вершины, поэтому у нее строго больше потомков. Таким образом, он размещается позже, чем указанная вершина в порядке, по желанию.

Счетчик потомков вершины один для себя, плюс счетчик потомков каждого из его дочерних элементов. Обратите внимание, что потомок может быть подсчитан несколько раз, если к нему ведут несколько путей.

Это также помогло бы использовать глубину, а не счетчик потомков.

f=lambda n:1+max(map(f,l[n]))

кроме того max, нужно будет дать 0пустой список.

XNOR
источник
2
Прекрасный алгоритм. Это даст 12 байтов в Pyth и Jelly.
Деннис
4

Pyth, 19 байт

hf!s-V@LQT+k._T.plQ

Попробуйте онлайн: демонстрация

Объяснение:

hf!s-V@LQT+k._T.plQ   implicit: Q = input list
               .plQ   all permutations of [0, 1, ..., len(Q)-1]
 f                    filter for permutations T, which satisfy:
      @LQT               apply the permutation T to Q
                         (this are the dependencies)
            ._T          prefixes of T
          +k             insert a dummy object at the beginning
                         (these are the already used elements)
    -V                   vectorized subtraction of these lists
   s                     take all dependencies that survived
  !                      and check if none of them survived
h                    print the first filtered permutation
Jakube
источник
4

Баш, 35 байт

perl -pe's/^$/ /;s/\s/ $. /g'|tsort

Пример запуска

Ввод / вывод 1-индексирован. Каждый массив идет в отдельной строке с пробелами в качестве разделителя элементов.

$ echo $'4\n1\n\n3\n1 3 2' # [[4], [1], [], [3], [1, 3, 2]]
4
1

3
1 3 2
$ bash tsort <<< $'4\n1\n\n3\n1 3 2'
3
4
1
2
5

Как это устроено

tsort- о котором я узнал в ответе @ DigitalTrauma - читает пары токенов, разделенные пробелами, которые указывают на частичное упорядочение, и печатает общее упорядочение (в виде отсортированного списка всех уникальных токенов), которое расширяет вышеупомянутый частичный упорядочивание.

Все числа в определенной строке сопровождаются либо пробелом, либо переводом строки. s/\s/ $. /gЧасть команды Perl заменяет пробельные символы с пробелом, номер строки и другое пространство, таким образом , убедившись , что каждый п на линии к предшествует к .

Наконец, если строка пустая (то есть состоит только из перевода строки), s/^$/ /к ней добавляется пробел. Таким образом, вторая подстановка превращает пустую строку k в k k, гарантируя, что каждое целое число встречается хотя бы один раз в строке, по которой передается tsort.

Деннис
источник
Хорошо, хорошо Я думаю, что ты заиграл tsortлучше / быстрее, чем я :) Спасибо за дополнительное объяснение.
Цифровая травма
3

Bash + coreutils, 20 80

nl -v0 -ba|sed -r ':;s/(\S+\s+)(\S+) /\1\2\n\1 /;t;s/^\s*\S+\s*$/& &/'|tsort|tac

Ввод в виде разделенных пробелами строк, например:

2
0 3

2
  • nl добавляет нулевые индексы ко всем строкам
  • sed разбивает списки зависимостей на простые пары зависимостей и делает незавершенные зависимости зависимыми от самих себя.
  • tsort делает необходимый топологический вид
  • tac ставит вывод в обратном порядке

Ideone. Ideone с тестовым набором @Dennis

Цифровая травма
источник
2

Python 2, 143 118 116 байт

Немного более случайный подход.

from random import*
l=input()
R=range(len(l))
a=R[:]
while any(set(l[a[i]])-set(a[:i])for i in R):shuffle(a)
print a

Редактирование:

  • исправил это и фактически сохранил несколько байтов.
  • Сохранено 2 байта (спасибо @Dennis)
Ханнес Карппила
источник