도전 과제 # 2 : 중첩 배열 분리


36

참고 : 이것은 일련의 문제 에서 2 위입니다 . 이전 도전에 대해서는 여기를 클릭하십시오 .

중첩 된 목록 분리

중첩 된 목록에서 값을 분리하려면 값을 병합 한 다음 각 값을 랩핑하여 이전과 동일한 중첩 깊이에있게하십시오.

즉,이 목록은 다음과 같습니다.

[1, [2, 3], [4, 4, [5, 2], 1]]

될 것입니다 :

[1, [2], [3], [4], [4], [[5]], [[2]], [1]]

도전

당신의 임무는 (언어 한계 내에서) 양의 정수의 중첩 목록을 가져 와서이 분리 작업을 수행하는 프로그램을 작성하는 것입니다.

리스트를 인수로 사용하는 함수 또는 I / O를 수행하는 전체 프로그램을 제출할 수 있습니다.

이것이 이므로 가장 짧은 제출 (바이트)이 이깁니다! *

* 표준 골프 허점은 금지되어 있습니다. 당신은 훈련을 알고 있습니다.


테스트 사례

입력 목록에는 언어의 표준 정수 크기의 정수만 포함됩니다. 언어의 제약으로 언어가 경쟁하는 것을 방지하기 위해 10보다 큰 깊이에 값이 중첩되지 않습니다.

입력에 빈 하위 목록이 없다고 가정 할 수 있습니다. 예를 들어- [[5, []]]제공되지 않습니다. 그러나 기본 목록은 비어있을 수 있습니다.

[]            ->  []

[[1, 2]]      ->  [[1], [2]]
[3, [4, 5]]   ->  [3, [4], [5]]
[3, [3, [3]]] ->  [3, [3], [[3]]]
[[6, [[7]]]]  ->  [[6], [[[7]]]]
[[5, 10], 11] ->  [[5], [10], 11]

코너 케이스를 놓친 경우 주저하지 말고 의견을 남겨주십시오.

예를 들어 빠른 (비 굴절) Python 3 솔루션을 함께 던졌습니다 . repl.it에서 테스트 할 수 있습니다 .


문자열 기반 답변을 위해 한 자릿수보다 큰 테스트 케이스를 추가하십시오.
orlp

@orlp 좋은 생각.
FlipTack

2
최대 깊이를 가정 할 수 있습니까? 16 살이라고?
orlp

@orlp 예, 언어의 제약 조건보다 알고리즘 및 메서드 실행에 더 관심이 있기 때문에 최대 중첩 깊이는 10이됩니다. 지금 스레드를 업데이트합니다.
FlipTack

문자열로 출력 할 수 있습니까?
Rohan Jhunjhunwala

답변:


4

Brachylog , 16 바이트

:{##:0&:ga|g}ac|

온라인으로 사용해보십시오!

설명

Example input: [1:[2:3]]

:{          }a     Apply the predicate below to each element of the list: [[1]:[[2]:[3]]]
              c    Concatenate: Output = [1:[2]:[3]]
               |   Or: Input = Output = []

  ##                 Input is a list: e.g. Input = [2:3]
    :0&              Call recursively the main predicate with this input: [2:3]
       :ga           Group each element in a list: Output = [[2]:[3]]
          |          Or (not a list): e.g. Input = 1
           g         Group into a list: Output = [1]

뭐라고합니까 Z인수는 TIO에합니까? 이것이 없으면 true / false로 출력되는 것처럼 보이 Z므로 바이트 수에 필요한 것처럼 보입니다 .
FlipTack

@FlipTack Z은 Brachylog에 출력 인수가 변수 임을 알려줍니다. 결과 출력과 통합되는이 변수입니다. 이를 제거하면 Brachylog에 출력이 익명 변수라고 알려주고 대신 기본 술어의 성공 여부를 인쇄합니다. 이는 변수에 결과가 "입력"되는 Prolog와 동일합니다.
페이탈 라이즈

좋아 :) 좋은 대답!
FlipTack

19

수학, 24 21 바이트

##&@@List/@#0/@#&/@#&

또는이 중 하나 :

##&@@List/@#&/@#0/@#&
##&@@List@*#0/@#&/@#&
##&@@List/@#&@*#0/@#&

설명

이것이 너무 짧은 이유는 기본적으로 명시적인 기본 사례가 필요하지 않은 재귀이기 때문입니다.

여기에 많은 구문 설탕이 있으므로 이것을 풀고 시작합시다. &왼쪽에 이름이없는 함수를 나타내며 인수는로 작성됩니다 #. 이 함수 내부 #0는 함수 자체를 참조하여 이름없는 재귀 함수를 작성할 수 있습니다. 그러나 내부 함수의 이름을 지정하고 꺼내는 것으로 시작하겠습니다.

f[x_] := ##& @@ List /@ f /@ x
f /@ # &

다른 중요한 구문 설탕은 f/@x짧습니다. Map[f, x]즉,의 f모든 요소를 ​​요구 x합니다. f[x_] := ... f /@ x무한 재귀로 이어지지 않는 이유 는 원자 위에 무언가를 매핑하면 실제로 함수를 호출하지 않고 원자를 변경하지 않기 때문 입니다. 따라서 기본 사례 (현재 요소는 정수)를 명시 적으로 확인할 필요가 없습니다.

따라서 함수는 f먼저 내부의 가장 깊은 목록으로 돌아가고이 x시점 f/@에서 no-op가됩니다. 그런 다음 사용 ##& @@ List /@을 요청합니다. List목록을 매핑 하면 각 요소가 별도의 목록으로 래핑되므로으로 변경 {1, 2, 3}됩니다 {{1}, {2}, {3}}. 그런 다음 우리는 적용 ##& 으로 대체됩니다 머리를 (외부 목록을 즉) 즉, 그것 ##&으로이 회전하므로 ##&[{1}, {2}, {3}]. 그러나 ##&단순히 인수의 인수를 Sequence랩핑되지 않은 목록 또는 다른 언어의 "스 플랫"연산자로 생각할 수 있음)을 반환합니다 .

따라서 ##& @@ List /@목록 {1, 2, 3}{1}, {2}, {3}(마지막으로 머리에 싸서 Sequence있지만 어디에서나 값을 사용하자마자 사라집니다)로 바꿉니다 .

그것은 왜 f그 자체가 도전에 대한 해결책이 아닌지에 대한 질문을 남깁니다 . 문제는 가장 바깥 쪽 목록이 다르게 처리되어야한다는 것입니다. 우리가 입력이있는 경우 {{1, 2}, {3, 4}}우리가 원하는 {{1}, {2}, {3}, {4}}없습니다 {{1}}, {{2}}, {{3}}, {{4}} . 내 원래 솔루션은 최종 결과를 Join외부 수준의 목록을 복원하는 인수 목록으로 전달 하여이 문제를 해결 했지만 출력의지도에서 f 자체 를 사용하여 외부 수준을 건너 뜁니다 . 따라서 f가장 바깥 쪽 목록의 개별 요소에만 적용되며 해당 목록을 건드리지 않습니다.

다른 세 가지 솔루션의 경우 첫 번째 솔루션은 외부에서도 마찬가지로 재귀를 적용합니다 f. 다른 두 솔루션 Map은 먼저 두 기능을 구성한 다음 결과를 한 번만 매핑하여 반복되는 작업을 피합니다 .


8

J , 19 18 바이트

(<@]/@,~>)S:0 1{::

이것은 중첩 배열의 J (거대한 번거로운) 버전 인 박스형 배열을 가져오고 반환하는 익명 동사입니다. 모든 테스트 사례를 통과했는지 확인하십시오.

설명

이것은 박스형 배열에서 작동 하는 다소 이국적인 작업 {::( map ) 및 S:( spread )를 사용합니다. {::각 리프를 해당 리프의 상자 경로로 바꿉니다. S:주어진 동사를 주어진 중첩 깊이에 적용한 다음 결과를 배열로 표시합니다.

(<@]/@,~>)S:0 1{::  Input is y.
(        )          Let's look at this verb first.
        >           Open the right argument,
      ,~            append the left argument to it,
    /               then reduce by
 <@]                boxing. This puts the left argument into as many nested boxes
                    as the right argument is long.
                    This verb is applied to y
               {::  and its map
            0 1     at levels 0 and 1.
                    This means that each leaf of y is paired with its path,
                    whose length happens to be the nesting depth of y,
                    and the auxiliary verb is applied to them.
          S:        The results are spread into an array.

3

R, 199 바이트

function(l){y=unlist(l);f=function(x,d=0){lapply(x,function(y){if(class(y)=='list'){f(y,d=d+1)}else{d}})};d=unlist(f(l));lapply(1:length(d),function(w){q=y[w];if(d[w]){for(i in 1:d[w])q=list(q)};q})}

이 질문은 단단했다. R의 목록은 약간 이상하며 하위 목록의 모든 요소를 ​​반복하는 것은 결코 간단하지 않습니다. 그런 다음 해당 목록의 깊이를 결정하는 것도 간단하지 않습니다. 그런 다음 모든 요소를 ​​구분하여 목록을 다시 작성해야하는 문제가 발생하므로 특정 깊이의 목록을 적응 적으로 작성하는 방법도 필요합니다.

솔루션은 두 개의 큰 부분으로 구성됩니다. 모든 목록을 반복하고 깊이를 기록하는 재귀 함수입니다.

  f=function(x,d=0){
    lapply(x,function(y){
      if(class(y)=='list'){
        f(y,d=d+1)
      } else {
        d
      }})
  }

unlist(l)에 저장된 vector의 모든 엔트리의 깊이를 가지면를 d통해 암시 적으로리스트를 생성 lapply하고 다음 함수로 채 웁니다.

  lapply(1:length(d),function(w){
    q=y[w]
    if(d[w]){
      for(i in 1:d[w]){
        q=list(q)
      }
    }
    q
  })

이 apply call에서, 우리 q는리스트에있는 엔트리의 값을 가진 객체 를 생성하고 , 그 깊이를 점검하고 그것이 0이 아닌지 확인합니다. 0이면 숫자 값으로 남겨 둘 수 있습니다. 그것이 0이 아닌 경우, 우리는 그것을 그 목록에 중첩시켜야합니다. 따라서 루프 d시간을 호출하고 반복해서 호출 q=list(q)합니다.

lapply그런 다음이 모든 값을 q목록에 넣고 원하는 출력을 만듭니다.

적절한 간격으로 다음과 같은 완벽한 프로그램 :

function(our.list){
  values <- unlist(our.list)
  f <- function(part.list, depth = 0){
    lapply(part.list, function(y){
      if(class(y)=='list'){
        f(y, depth <- depth + 1)
      } else {
        return(depth)
      }})
  }
  depths <- unlist(f(our.list))
  new.list <- lapply(1:length(depths), function(w){
    q <- values[w]
    if(depths[w] != 0){
      for(i in 1:depths[w]){
        q <- list(q)
      }
    }
    return(q)
  })
  return(new.list)
}

좋은 점은 이것이 테스트 사례를 위해 초기 Python 솔루션과 함께 사용한 방법입니다.
FlipTack

is.list(y)대신에 class(y)=='list'? 실제로 작동하는지 확인할 수 없습니다.
주세페



2

C (gcc), 147 바이트

d=0,l,i;
P(n,c){for(;n--;)putchar(c);}
main(c){for(;~(c=getchar());l=i)i=isdigit(c),P((l<i)*d,91),P(i,c),P((l>i)*d,93),P(l>i,32),d+=(92-c)*(c>90);}

입력 예 :

1 [23 3] [40 4 [5 2] 1]

출력 예 :

1 [23] [3] [40] [4] [[5]] [[2]] [1]

2

스택 된 비경쟁 25 바이트

{e d:e$wrap d 1-*}cellmap

스택의 최상위 멤버를 수정하는 기능입니다. 당신이 선의의 기능을 원하는 경우에, 다만 추가 []시작과 끝. 여기 사용해보십시오!

다음은 읽을 수있는 버전입니다.

{ arr :
  arr { ele depth :
    ele   $wrap depth 1- * (* execute wrap n times, according to the depth *)
  } cellmap (* apply to each cell, then collect the results in an array *)
} @:a2
(1 (2 3) (4 4 (5 2) 1)) a2 out

테스트 사례 :

(1 (2 3) (4 4 (5 2) 1))    (* arg on TOS *)
{e d:e$wrap d 1-*}cellmap
out                        (* display TOS *)

줄 바꿈없이 출력 :

(1 (2) (3) (4) (4) ((5)) ((2)) (1))

*코드 블록에 인수처럼?
Downgoat

이 경우 @Downgoat는 인수 d-1시간을 래핑합니다 . $func조작 할 수있는 기능입니다.
Conor O'Brien

2

PHP, 101 94 바이트

@Christoph 덕분에 1 바이트를 절약하고 6에서 영감을 얻었습니다.

function s($a){foreach($a as$b)if($b[0])foreach(s($b)as$c)$r[]=[$c];else$r[]=$b;return$r?:[];}

재귀 함수, 꽤 직진

고장

function s($a)
{
    foreach($a as$b)                // loop through array
        if($b[0])                       // if element is array
            foreach(s($b)as$c)$r[]=[$c];    // append separated elements to result
        else$r[]=$b;                    // else append element to result
    return$r?:[];                   // return result, empty array for empty input
}

결과는 어디에서 초기화됩니까?
Neil

@Neil : PHP는 명시적인 초기화가 필요하지 않습니다. 어느 $r루프의 요소를 가져 오거나 함수는 빈 배열을 반환합니다. 알림이 표시 될 수 있지만 기본 구성으로 인쇄되지는 않습니다.
Titus

그것은 당신이 한 번만 전화를 할 수 있다는 것을 의미하지 않습니까?
Neil

1
당신은 또한 미쳤을지도 모른다 : !cos(). 모든 배열에 대해 cos()반환 null하고 모든 positiv 정수에 대해 float! = 0을 반환합니다. 누가 경고를 신경 쓰나요?
Christoph

1
@Christoph : 경고가 인쇄되고 알림이 표시되지 않습니다 (기본 구성). 그러나 좋은 생각입니다! 켜기 is_int: 조건을 되 돌리면 아무 것도 저장되지 않습니다. else와 사이에 공백이 필요합니다 foreach. 그러나 $b[0]정수는 NULL입니다.
Titus

2

파이썬 2, 122106 바이트

꽤 끔찍한 점수, 간단한 구현.

16 바이트 절약에 도움을 주신 @Zachary T에게 감사드립니다!

def x(l,a=[],d=0):
 n=lambda b:b and[n(b-1)]or l
 if'['in`l`:[x(e,a,d+1)for e in l];return a
 else:a+=n(d)

x하나의 인수로 호출 하여 실행하십시오. 어떤 이유로 든 한 번만 실행할 수 있습니다.


당신은 변경할 수 있습니다 a+=[n(l,d)]a+=n(l,d),(후행 쉼표 주)
FlipTack

에 할당해야 t합니까?
Zacharý

두 번 이상 호출 할 때 작동합니까?
Zacharý

n항상이므로 함수 로 이동 하고 첫 번째 인수를 제거 할 수 있습니다 l.
Zacharý


2

자바 스크립트 (Firefox 30-57), 53 바이트

f=a=>[for(e of a)for(d of e.map?f(e):[e])e.map?[d]:d]

내가 지금까지 가지고있는 최고의 ES6 답변은 76 바이트입니다.

f=(a,r=[],d=0)=>a.map(e=>e.map?f(e,r,d+1):r.push((n=d=>d?[n(d-1)]:e)(d)))&&r

2
두 코드 블록 모두에서 선행을 생략했다고 생각합니다 f=.
Conor O'Brien

@ ConorO'Brien Yet again ...
Neil


1

펄 6 , 60 47 바이트

sub f{[$_~~List??|([$_] for .&f)!!$_ for |$^a]}

( 온라인으로 시도하십시오. )

설명:

  1. [... for |$^a]: 입력 배열을 반복하고 새 배열을 구성합니다.
  2. $_ ~~ List ?? ... !! ...: 각 요소에 대해 배열 자체인지 확인하십시오.
  3. |([$_] for .&f): 요소가 배열이면 재귀 적으로 함수를 적용하고 해당 재귀 호출에서 반환 된 새 배열의 요소를 반복하고 각 요소를 자체 배열로 감싸서 외부 목록에 넣습니다.
  4. $_: 요소가 배열이 아닌 경우 그대로 전달하십시오.

1

하스켈, 71 바이트

data L=N Int|C[L] 
d#C l=((C .pure.d)#)=<<l
d#n=[d n]
f(C l)=C$(id#)=<<l

Haskell의 원주민 목록은 임의로 중첩 될 수 없으므로 자체 목록 유형을 정의해야합니다. 이 새로운 유형 L은 함수에서 반환 될 수 있지만 기본적으로 인쇄되지 않으므로 결과를 보려면 show인스턴스를 정의합니다 L.

instance Show L where
  show (N n)=show n
  show (C l)=show l

이제 REPL에서 몇 가지 테스트를 수행 할 수 있습니다.

*Main> f $ C[N 1, C[N 2, N 3], C[N 4, N 4, C[N 5, N 2], N 1]]
[1,[2],[3],[4],[4],[[5]],[[2]],[1]]

*Main> f $ C[C[N 6, C[C[N 7]]]]
[[6],[[[7]]]]

작동 방식 : C생성자 의 함수로 중첩 수준을 전달하는 간단한 재귀 . identity 함수로 시작 id하고리스트 (-> pattern match d#C l=)가 있을 때마다리스트의 모든 요소에 대한 재귀 호출에 C(-> C .pure.d) 레이어를 추가 #합니다. 우리가 숫자를 만나면 단순히 중첩 수준 함수 d를 숫자에 적용합니다 .


0

APL (Dyalog) , 44 바이트 *

익명의 암묵적 접두사 기능. 중첩 된 APL 목록을 인수로 사용하고 중첩 된 APL 배열을 반환합니다.

∊{⊃⊂⍣⍵,⍺}¨{⊃¨(j∊⎕D)⊆+\-'[]'∘.=j←⎕JSON⍵}

온라인으로 사용해보십시오!

{} 인수가 다음과 같은 경우에 명시적인 함수를 적용하십시오 .

⎕JSON⍵ 인수를 JSON으로 변환

j← 에 저장 j

'[]'∘.=j열기 (맨 위 행) 및 닫기 (맨 아래) 대괄호  가 같은 테이블

-⌿ 맨 위 행-맨 아래 행 (수직 차이 감소)

+\ 누적 합계 (각 문자의 중첩 수준을 제공함)

()⊆ 파티션, 1 앞에 1이 붙지 않을 때마다 새 파티션을 시작하는 파티션…

  j∊⎕D 여기서, 각각의 캐릭터 j세트의 구성원 D에 igits은

⊃¨ 각각의 첫 번째를 선택하십시오 (이것은 여러 자리 수 당 중첩 수준을 제공합니다)

∊{...  각 중첩 단계 (다음 함수를 적용 로부터 해당 요소 사용) ε nlisted (왼쪽 인수 인수 (평탄화) ) :

,⍺ 스칼라를 묶을 수 없기 때문에 숫자를 깎아 내다

⊂⍣⍵시간을  동봉하다

 공개 (가장 안쪽 목록 자체가 엔클로저이기 때문에)


*로 Dyalog 클래식을 사용하여 ⎕ML←3대체 (많은 시스템에서 기본), 위해 위해 . 티오!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.