Сортування вкладеного списку


23

Ви повинні написати програму або функцію, яка сортує вкладений список. Ось правила сортування вкладеного списку:

Візьмемо цей список як приклад:

((5, 2), 2, 7, (2, 1, (3, 4)), 9)

Кожен елемент цього списку має "пріоритет". Елемент вважається числом або підсписком. Спочатку отримайте пріоритет кожного елемента на однаковій глибині. Якщо елементом є лише число, його пріоритет такий же, як і саме число. Якщо елемент є підспілом, його пріоритетом є сума всіх чисел у ньому, не враховуючи жодних підсписок.

Отже, пріоритети всіх елементів глибини 1 :

 (  7 )  2  7  (    3       )  9
((5, 2), 2, 7, (2, 1, (3, 4)), 9)

Сортуйте кожен елемент за пріоритетністю. Якщо є краватка, ви повинні зберігати той самий порядок, що і у вихідному списку.

 2  (     3      )  (  7 )  7  9
(2, (2, 1, (3, 4)), (5, 2), 7, 9) 

Повторіть для кожного списку. Тож у цьому підсписі

(2, 1, (3, 4))

Наші пріоритети виглядають так:

 2  1  (  7  )
(2, 1, (3, 4))

Так відсортовано, це виглядає так:

(1, 2, (3, 4))

(3, 4)вже відсортовано, тому ми закінчили. Повторіть, для (5, 2)чого результат, (2, 5)і ми готові! Наш остаточний список:

(2, (1, 2, (3, 4)), (2, 5), 7, 9) 

Правила:

  • Дуже сумнівно, але про всяк випадок, якщо у Mathematica є щось для цього, вкладений список впорядкованих вбудованих файлів не допускається. Регулярні функції сортування будуть дозволені.

  • Введення / виведення може бути в будь-якому розумному форматі.

  • Кожен підспис містить мінімум одне число чи список. Крім того, до списків можна вкласти декілька рівнів. Наприклад, в має пріоритет 0, так як вона має тільки підсписки ньому. (1, 2, (((3))))(((3)))

  • Недійсні списки (не збігаються круглі дужки, не числа, неправильні типи дужок, негативні числа тощо) призводять до не визначеної поведінки.

Тест вводу / виводу:

(1, 2, 3) ---> (1, 2, 3)

(1, 2, 6, 3, 9, 8) ---> (1, 2, 3, 6, 8, 9)

(4, 3, (2), (1)) ---> ((1), (2), 3, 4)

(4, 3, (2), ((1))) ---> (((1)), (2), 3, 4)

(5, (1, 2, (9, 8))) ---> ((1, 2, (8, 9)), 5)

(3, (1, 2), (2, 1)) ---> (3, (1, 2), (1, 2))

(3, (1, 2, (99)), (2, 1, (34))) ---> (3, (1, 2, (99)), (1, 2, (34)))

(7, 2, (1, (9, 12)), (4, 3, 2, (1, 2))) ---> ((1, (9, 12)), 2, 7, (2, 3, (1, 2), 4))

Найкоротша відповідь у байтах виграє.


Чи можна вважати, що числа є цілими числами?
isaacg

@isaacg Так, можна.
DJMcMayhem

Відповіді:


5

Желе, 13 байт

fFSµ€Ụị߀µ¹<?

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

Як це працює

fFSµ€Ụị߀µ¹<?  Main link. Input: A (list)

   µ€          Apply the chain to the left to each item B in A.
 F             Flatten B.
f              Filter; intersect B with flattened B, yielding a list.
               This returns the numbers in B if B is a list, [B] if B is a number.
  S            Compute the sum of the resulting list.
     Ụ         Sort the indices of A according to the computed sums.
       ߀      Recursively apply the main link to each B in A.
      ị        Retrieve the items of the list (right) at those indices (left).
         µ     Convert the preceding chain into a single link.
            ?  If:
           <     A compared with itself is truthy:
                   Execute the link to the left.
          ¹      Else, apply the identity function to A.

Якщо порівнювати число ( <) з самим собою, то виходить 0 (хибний), але порівнюючи не порожній список із самим собою, виходить список 0 (s), тому <його можна використовувати для відрізнення чисел від списків.


0 - помилково, але поле 0s - це True, але порожнє поле - False. Цікаво, як працює Python. : P
кіт

Виглядає мені як 25 байт (коли закодовано в UTF-8).
Ротсор

@Rotsor Це звучить правильно. Однак Jelly використовує користувацьку кодову сторінку, що кодує всі 256 символів, які вона розуміє як окремі байти.
Денніс

17

Пітон 2, 114 101 78 73 62 байт

k=lambda t:t*(t<[])or t.sort(key=k)or sum(z for z in t if[]>z)

Я знав, що є кращий спосіб відфільтрувати списки.

Сортування списку пітонів (та його підспісів) на місці.

https://eval.in/540457 дякує @tac за те, що повідомив про місцеві рішення, є прийнятними, а @xnor + @feersum - для подальших оптимізацій!


1
Деякі більш оптимізації: k=lambda t:t*(t<[])or sum(z for z in t if[t.sort(key=k)]>z).
xnor

@xnor Я думаю, що рішення не зовсім правильне: eval.in/540447 . У цьому прикладі ми повторюємось до першого підспису і захоплюємо початковий zз нього 5. Потім в умовному порядку сортуємо список, який ми повторюємо (!), Тож коли ми захопимо наступний z, це ТАКОЖ 5, що приводить до суми 10. Потім сортуємо зовнішній список за допомогою цих клавіш і отримуємо [6, [1, 5]], що неправильно як "Якщо є краватка, ви повинні зберегти той самий порядок, що і вихідний список. " Цікавим є те, що ми sortобидва списки викликаємо два рази, тому це відбувається лише на рівних клавішах: якби підпис був меншим, він би відновлювався.
Орез

Хороший улов. Смішно, що ітерація триває за відсортованим зараз списком. Я відчуваю, що все-таки повинен бути коротший спосіб дотримуватися Noneрезультатів t.sort(key=k), але я цього не бачу.
xnor

False0 для цілей +і розширенням, sum. Не можу придумати, як це економить байти.
CalculatorFeline

@CatsAreFluffy list.sortповертається None, ні False.
Денніс

4

Луа, 172 байти

function p(a)if type(a)~="table"then return a end s(a)local t=0 for i,v in next,a do t=t+p(v)end return t end
function s(t)table.sort(t,function(a,b)return p(a)<p(b)end)end

Функція sсортує таблицю Lua (структуру даних, яка служить списком серед іншого в Lua) за місцем відповідно до правил.


Мені подобається, як type(a)повертає струну
кіт

Нарешті відповідь, використовуючи Lua.
Лина монашка

3

Математика, 50 байт

#0/@SortBy[#,Tr@Cases[#,_Integer,{0,1}]&]~Check~#&

Простий рекурсивний метод, який використовує SortBy. Ігноруйте повідомлення.


3

Haskell, 160 151 135 байт

import Data.List
data T=N Int|T[T]deriving Show
p(N x)=x
p(T t)=sum$[x|N x<-t]
f(N x)=N x
f(T t)=T$sortBy((.p).compare.p)$map f$t

Перша проблема - це вкладені списки. Haskell вимагає, щоб усі елементи списку були одного типу; зокрема ціле число та список цілих чисел не є одним типом. Іншими словами, список змінних вкладених не список, це дерево троянд!

Отже, спочатку ми повинні визначити тип даних для троянди:

data T = N Int | T [T]

(Строго, deriving Showце потрібно лише в тому випадку, якщо ви хочете побачити результати. Але це технічність.) Маючи таке визначення, ми можемо написати список, наприклад (1, 2, (3, 4)),

T [N 1, N 2, T [N 3, N 4]]

що значно менш читабельно. Але що б там не було; це тривіальний, механічний переклад. Префікс кожного числа з Nі кожного піддіречка T.

Тепер нам потрібно обчислити пріоритети. Це було б легко, якби пріоритет піддерева був простою сумою всіх елементів, які він містить. Це був би тривіальний рекурсивний цикл. Але оскільки це не так, нам потрібно визначити дві функції: таку, яка повторюється, і таку, яка ні.

p (N x) = x
p (T t) = sum $ map q t

q (N x) = x
q _     = 0

Якби ми підсумовували всі субелементи, тоді qне було б потреби існувати, зберігаючи величезну кількість символів. Ну добре!

Edit: На насправді, кілька commentors вказують на те , що ви можете уникнути з qдопомогою списку розуміння: [ x | N x <- t]. Гарний дзвінок, хлопці!

(Насправді, pне потрібно було б і існувати; у нас може бути компілятор, який автоматично генерує Ordекземпляр для нас у жмені символів, і ця реалізація за замовчуванням відповідала б специфікації.)

Нарешті, нам потрібно рекурсивно зазначити всі під деревами та сортувати їх:

f (N x) = N x
f (T t) = T $ sortBy (\ x y -> compare (p x) (p y)) $ map f $ t

Тобто fсортує дерево, рекурсивно застосовуючи себе до всіх елементів ( map f), а потім викликаючи sortByфункцію для сортування верхнього рівня. Перший рядок говорить про те, що сортування числа не робить нічого, і це необхідно для припинення рекурсії.


2
sortBy (\ x y -> compare (p x) (p y))просто sortOn p. Використовуйте версію інфіксной карт в p: sum$q<$>t.
німі

@nimi Де sortOnвизначено? Я завжди хотів знати ...
MathematicalOrchid


2
ви можете все-таки обрізати 16 байт за допомогою трюку розуміння списку p(T t)=sum[x|N x<-t]та data T=N Int|T[T]deriving Show. :)
Буде Несс

1
Ви включили 2 байти для кожного нового рядка у свій рахунок? Я думаю, нам дозволено вважати їх синглами . Крім того, немає необхідності $в sum$[x|N x<-t]. Отже, 135-5-1 = 129. :)
Буде Несс

2

CLISP, 380 байт

(defun q(L)(if(null L)L(append(append(q(car(s(cdr L)(car L))))(list(car L)))(q(cadr(s(cdr L)(car L))))))))(defun s(L E)(if(not(atom(car L)))(setq L(cons(q(car L))(cdr L))))(cond((null L)'(nil nil))((<(v(car L))E)(list(cons(car L)(car(s(cdr L)E)))(cadr(s(cdr L)E))))(T(list(car(s(cdr L)E))(cons(car L)(cadr(s(cdr L)E)))))))(defun v(L)(if(atom L)L(apply'+(remove-if-not #'atom L))))

Викличте функцію q зі списком.

Я пізній ноб, будь ласка, не вбивайте мене ^^


Ха-ха, я сподівався, що хтось зробить це в ліс!
DJMcMayhem

1

Pyth, 15 байт

L?sIbbossI#NyMb

Тестовий набір

Рекурсивна функція, яка працює наступним чином:

L?sIbbossI#NyMb
L                  define y(b):
 ?sIb              If b is an integer:          (invariant under the s function)
     b             Return it.
            yMb    Else, apply y recursively to all of the elements of b,
      o            Then sort b by
        sI#N       For each element, the elements of that list that are integers.
                   This is luckily a nop on integers.
       s           Summed.

1

Java, 219 байт

import java.util.*;List f(List l){l.sort(Comparator.comparing(o->{if(o instanceof Integer)return(Integer)o;f((List)o);return((List) o).stream().filter(i->i instanceof Integer).mapToInt(i->(Integer)i).sum();}));return l;}

З розривами рядків:

import java.util.*;
List f(List l){
    l.sort(Comparator.comparing(o -> {
        if (o instanceof Integer)
            return (Integer) o;
        f((List) o);
        return ((List) o).stream().filter(i -> i instanceof Integer).mapToInt(i -> (Integer) i).sum();
    }));
    return l;
}

Йде багато кастингу, який дійсно набирає кількість байтів. : P

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

Спробуйте тут .


1
Ось така сама техніка в 154 байтахint f(List l){l.sort(Comparator.comparing(o->o instanceof Integer?(int)o:f((List)o)));return l.stream().mapToInt(o->o instanceof Integer?(int)o:0).sum();}
Андреас

Я думаю, що є ще багато чого, щоб вичавити.
Андреас

Але є кілька проблем: ви не можете явно конвертувати подібне Objectдо intцього, а виклик, схоже, вимагає виведення списку.
ТНТ

Ви фактично зберігаєте 1 байт, змінюючи instanceof, щоб перевірити список замість Integer. Ціле число - 7 байт без фігурних фігурних дужок, але список - 6 байт.
Синій

@TNT Ви можете кинути об'єкт примітиву в Java 1.7 або вище. Звичайно, якщо об’єкт недійсний, ви отримаєте npe. Я не бачу жодних проблем із сортуванням списку на місці, проблема, схоже, не відповідає безпосередньо цьому питанню.
Андреас

0

JavaScript (ES6), 86 байт

f=a=>a.map?a.map(f).sort((a,b)=>p(a)-p(b),p=a=>a.map?a.map(a=>t+=a.map?0:a,t=0)|t:a):a

Весь цей масив перевіряє :-(


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