중첩 된 목록 정렬


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에 무언가가있는 경우 중첩 목록 정렬 내장은 허용되지 않습니다. 정기적 인 정렬 기능 허용됩니다.

  • I / O는 임의의 합리적인 형식 일 수 있습니다.

  • 모든 하위 목록에는 하나 이상의 숫자 또는 목록이 포함됩니다. 또한 하위 목록은 여러 수준으로 중첩 될 수 있습니다. 예를 들어에 (1, 2, (((3))))(((3)))하위 목록 만 있기 때문에의 우선 순위는 0입니다.

  • 유효하지 않은 목록 (일치하지 않는 괄호, 숫자가 아닌, 대괄호 유형, 음수 등)은 정의되지 않은 동작을 초래합니다.

테스트 I / O :

(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 (falsy)를하지만, 자체 비어 있지 않은 목록을 비교하는 목록을 얻을 수 0 , 그래서의 (truthy)을 <목록에서 번호를 구분하는 데 사용할 수 있습니다.


0은 False이지만 0의 상자는 True이지만 빈 상자는 False입니다. 파이썬의 작동 방식에 흥미가 있습니다. : P
고양이

25 바이트 (UTF-8로 인코딩 된 경우)처럼 보입니다.
Rotsor

@Rotsor 맞습니다. 그러나 Jelly는 단일 바이트로 이해하는 256자를 모두 인코딩 하는 사용자 지정 코드 페이지 를 사용 합니다.
Dennis

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를 가져옵니다 . 그런 다음 조건부에서 반복하는 목록을 정렬합니다! 그런 다음이 키로 외부 목록을 정렬하고 [6, [1, 5]]를 얻습니다. "타이가있는 경우 원래 목록과 동일한 순서를 유지해야합니다. " 흥미로운 점은 sort두 목록을 두 번 호출 하므로 동일한 키에서만 발생한다는 것입니다.
Orez

잘 잡았습니다. 반복이 현재 정렬 된 목록으로 계속되는 것이 재미 있습니다. 의 None출력 을 유지하는 더 짧은 방법이 여전히 있어야한다고 생각 t.sort(key=k)하지만 보이지 않습니다.
xnor

False+확장 목적으로 0입니다 sum. 그래도 바이트를 절약하는 방법을 생각할 수 없습니다.
CalculatorFeline

@CatsAreFluffy의 list.sort반환 None하지 False.
Dennis

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)문자열을 반환하는 방법을 좋아합니다
cat

마지막으로 루아를 사용한 답변.
Leaky Nun

3

수학, 50 바이트

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

를 사용하는 간단한 재귀 방법 SortBy. 메시지를 무시하십시오.


3

하스켈, 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하면 존재하지 않아도되므로 많은 문자를 절약 할 수 있습니다. 오 잘!

편집 : 실제로 여러 의견 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

@nimi 어디에 sortOn정의되어 있습니까? 나는 항상 알고 싶었다 ...
MathematicalOrchid


2
당신은 여전히 목록 이해 트릭 일부 16 바이트를 면도 할 수 p(T t)=sum[x|N x<-t]data T=N Int|T[T]deriving Show. :)
Will Ness

1
카운트에 개행마다 2 바이트를 포함 시켰습니까? 우리는 그것들을 싱글계산할 수 있다고 생각 합니다 . 또한, 필요가 없습니다 $에가 sum$[x|N x<-t]. 따라서 135-5-1 = 129입니다. :)
Will Ness

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를 호출하십시오.

나는 lisp 멍청한 놈입니다, 제발 죽이지 마세요 ^^


하하, 나는 누군가가 lisp에서 그것을하기를 바랐다!
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

자바, 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;
}

실제로 바이트 수를 쌓는 캐스팅이 많이 있습니다. :피

정수 값은 Comparator에 공급되고 중첩 된 목록은 정수 값의 합계가 Comparator에 제공되기 전에 먼저 정렬됩니다. 이러한 값은 목록을 정렬 할 때 비교기가 목록 내 위치를 결정하는 방법입니다.

여기에서 시도 하십시오 .


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

짜야 할 것이 더 많다고 생각합니다.
Andreas

명시 적으로 변환 할 수 없습니다 :하지만 거기에 몇 가지 문제가있다 Object하는 int것을 좋아하고, 도전리스트를 출력해야 할 것 같다.
TNT

실제로 Integer 대신 List를 확인하도록 instanceof를 변경하여 1 바이트를 저장합니다. 정수는 중괄호없이 7 바이트이지만 List는 6 바이트입니다.
Blue

@TNT Java 1.7 이상의 객체를 프리미티브에 캐스트 할 수 있습니다. 물론 Object가 null이면 NPE를 얻습니다. 목록을 정렬하는 데 아무런 문제가 보이지 않지만 문제는 직접 문제에 대해 이야기하지 않는 것 같습니다.
Andreas

0

자바 스크립트 (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
고양이
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.