2D 배열의 주변 0을 제거


40

이것은 이 질문 의 2 차원 버전입니다 .

음이 아닌 정수만 포함하는 비어 있지 않은 2 차원 배열 / 행렬이 주어진 경우 :

[0000000010000010011100000]

주변 0이 제거 된 배열, 즉 주변 0이없는 가장 큰 연속 하위 배열을 출력합니다.

[010001111]

예 :

[0000000010000010011100000][010001111]
Input:
[[0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0]]

Output:
[[0, 1, 0], [0, 0, 1], [1, 1, 1]]

[00000003000005000000][003000500]
Input:
[[0, 0, 0, 0], [0, 0, 0, 3], [0, 0, 0, 0], [0, 5, 0, 0], [0, 0, 0, 0]]

Output:
[[0, 0, 3], [0, 0, 0], [5, 0, 0]]

[123456789][123456789]
Input:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

[000000000000][]
Input:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

Output:
[]

[000011110000][1111]
Input:
[[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]]

Output:
[[1, 1, 1, 1]]

[010001000100][111]
Input:
[[0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]]

Output:
[[1], [1], [1]]

[111112311111][111112311111]
Input:
[[1, 1, 1, 1], [1, 2, 3, 1], [1, 1, 1, 1]]

Output:
[[1, 1, 1, 1], [1, 2, 3, 1], [1, 1, 1, 1]]

3
@MattH 비전 어가 아닌 언어로는 어려운 것이 없습니다. :)짧게 만들기가 어렵습니다.
user202729

1
마지막 테스트 사례에서 빈 행렬 대신 잘못된 결과를 줄 수 있습니까?
sundar

1
또한 출력이 정사각형이 아닌 행렬 일 수있는 경우 테스트 케이스를 추가하십시오.
sundar

1
이전 제출물을 파기 한 테스트 사례 : [[0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]](너비 / 높이가 인 결과 1)
Conor O'Brien

1
이봐, 테스트 케이스를 추가 할 수 있습니다
[111112311111]
베타 붕괴

답변:



39

Wolfram Language (Mathematica) , 42 바이트

#&@@CellularAutomaton[{,{},0{,}},{#,0},0]&

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

셀룰러 오토마타는 실제로 , 우주 , 그리고 모든 것에 대한 해답 입니다. 1

어떻게?

CellularAutomaton입력 배열과 선택적 배경 값을받습니다. 따라서, s {#,0}의 배경을 가정하여 셀룰러 오토 마톤 규칙을 입력에 적용하도록 지정합니다 0.

여기서 깔끔한 것은 CellularAutomaton배경 셀의 경계가 존재하지 않도록 출력 을 자르는 것입니다 (그렇지 않으면 출력이 무한 평면에 있기 때문에).

이 코드는 규칙을 {Null, {}, {0, 0}}적용하여 머리 Null를 각 셀의 0 반경 이웃 (즉, 중심 : 셀 자체)에 정확하게 적용 0합니다. 이것의 결과는 원래 입력이지만 배경이 제거 된 것입니다 (예 : 주변 자르기 0).


1. 내 대답의 바이트 수를 봅니까? ;)


6
좋은 내장 학대 ... 글쎄 Mathematica는 직접 노출되지 않은 내장 기능을 가지고 있습니다.
user202729

3
아니 XKCD (505) 참조?
Esolanging 과일

Cellular Automata 및 Ultimate Answer의 경우 +1
HighRadioactive

14

JavaScript (ES6), 98 바이트

(a,z)=>(g=A=>A.slice(A.map(m=M=(r,i)=>M=(z?a:r).some(n=>z?n[i]:n)?1/m?i:m=i:M)|m,M+1))(a).map(z=g)

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

어떻게?

zip 내장 의 부족을 극복하기 위해 글로벌 플래그 z 의 값에 따라 입력 행렬 a [] 의 행 또는 열에서 작동 할 수 있는 함수 g () 를 정의합니다 .

g () 는비어 있지 않은 행 ( z 가 정의되지 않은 경우) 또는 비어 있지 않은 열 ( z 가 정의 된경우)의 최소 ​​인덱스 m 및 최대 인덱스 M 을찾고 행렬 자체 또는 지정된 행의 해당 슬라이스 를반환합니다.매트릭스의.

요약:

  • 먼저 z가 정의되지 않은 행렬에서 g () 를 호출하여 행을 제거합니다.
  • 그런 다음 z가 정의 된 각 행에서 g () 를 호출하여 열을 제거합니다..map(z=g)

댓글

(a, z) => (               // a[] = input matrix; z is initially undefined
  g = A =>                // g() = function taking A = matrix or row
    A.slice(              //   eventually return A.slice(m, M + 1)
      A.map(m = M =       //     initialize m and M to non-numeric values
        (r, i) =>         //     for each row or cell r at position i in A:
        M = (z ? a : r)   //       iterate on either the matrix or the row
        .some(n =>        //       and test whether there's at least one
          z ? n[i] : n    //       non-zero cell in the corresponding column or row
        ) ?               //       if so:
          1 / m ? i       //         update the maximum index M (last matching index)
                : m = i   //         and minimum index m (first matching index)
        :                 //       otherwise:
          M               //         let M (and m) unchanged
      ) | m,              //     end of map(); use m as the first parameter of slice()
      M + 1               //     use M+1 as the second parameter of slice()
    )                     //   end of slice()
  )(a)                    // invoke g() on the matrix with z undefined
  .map(z = g)             // invoke g() on each row of the matrix with z defined

2
인상적입니다.
잭 헤일 즈

3
@Jek, Arnauld는 완전히 다른 차원에서 살고 있습니다. 당신이 있다면 그러나 매우 운이 좋은, 당신은 때때로 그가 놓친 트릭을 발견하고 짧은 솔루션을 게시 할 수 있습니다. 이 과정에서 JavaScript에 대해 매우 깊이 이해하게됩니다.
Rick Hitchcock

4
@RickHitchcock 저는 코드 패턴 인식에 능숙하지 않으며 이전에 본 적이 있더라도 정기적으로 많은 것을 놓치고 있습니다. 이 특정 예제에서는 g () 의 재사용 가능성에 중점을 두 었으며 mM (-9 바이트) 을 업데이트하는 방법에 대한 명확한 최적화를 놓쳤습니다 . 코드 골프는 언어의 미묘함에 대해 많은 것을 배울 수있는 훌륭한 (그리고 재미있는) 방법이라는 데 전적으로 동의합니다.
Arnauld

7

하스켈 , 62 61 바이트

f.f.f.f
f=reverse.foldr(zipWith(:))e.snd.span(all(<1))
e=[]:e

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

foldr(zipWith(:))e으로는 e=[]:eA는 약간 짧은transpose , 그리고 snd.span(all(<1))목록 목록에서 제로의 주요 목록을 삭제합니다. 2D 목록에서 transpose다음과 같이 reverse90도 회전하면 코드 f.f.f.f0의 선행 목록을 네 번 떨어 뜨리고 회전 합니다.




5

Brachylog , 24 22 20 19 바이트

{s.h+>0∧.t+>0∧}\↰₁\

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

결과 행렬을 배열의 배열로 출력하거나 빈 출력의 경우 false를 출력합니다.

(인라인 술어를 제안하고 1 바이트를 절약 해 준 @Fatalize에게 감사합니다.)

설명

술어 0 (주) :

{...}     Define and call predicate 1 to remove all-zero rows
  \       Transpose the result
   ↰₁     Call pred 1 again, now to remove all-zero columns
     \    Transpose the result to have correct output orientation

술어 1 :

?s.h+>0∧.t+>0∧
  .           output is
 s              a subsequence of the rows of
?              the input (implicit)
   h          also, output's head element (first row)
    +>0        has a sum > 0 (i.e. has at least one non-zero value)
       ∧.t+>0  and similarly the output's tail element (last row)
∧              (don't implicitly unify that 0 with the output)

첫 번째 술어 인라인 작성은 1 바이트 더 짧습니다 {s.h+>0∧.t+>0∧}\↰₁\ . (이것은 거의 모든 Brachylog 답변에 해당되며, 새로운 행의 술어는 실제로 더 읽기 쉬운 것을 작성하려는 경우에만 구현됩니다).
Fatalize

@Fatalize 감사합니다 (최종!). 인라인 술어 구문이 정의와 술어 응용 프로그램 둘 다인 방법에 대해 전혀 생각하지 못했습니다.
sundar

5

R , 96100 97 바이트

function(m)m[~m,~t(m),drop=F]
"~"=function(x,z=seq(r<-rowSums(x)))z>=min(y<-which(r>0))&z<=max(y)

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

~도우미는 음이 아닌 벡터와 수익률 벡터 걸리는 FALSE은 "외부"에 대한 0벡터의 S와 TRUE긍정적하고 "내부"에 대한 0들. 이 함수는 입력 행렬의 행과 열 합계에 적용됩니다.

~! 사업자의 R의 파서 처리를 사용합니다.

@DigEmAll의 의견에 따라 수정되었지만 @ J.Doe에서 약간의 바이트가 반환되었습니다.


1
내가 한 drop=F것처럼 추가해야한다고 생각합니다 . 그렇지 않으면이 두 테스트가 행과 열 대신 벡터를 반환 합니다. 온라인으로 시도하십시오!
digEmAll

97 바이트drop=F. 아직도 톤 아래!
J.Doe

5

R , 89 79 바이트

function(m,y=apply(which(m>0,T),2,range)){y[!1/y]=0;m[y:y[2],y[3]:y[4],drop=F]}

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

테스트 케이스 코드는 @ngm, 10 바이트 절약은 @ J.Doe 덕분입니다!

  • drop=F단일 행 / 열 행렬을 벡터로 변환하는 기본 R 동작으로 인해 매개 변수 를 추가해야했습니다 ...

이전 코드가 모두 0 인 경우에 실패했음을 알지 못했습니다. 불행히도 훨씬 더 많은 바이트로 수정되었습니다. (
digEmAll

1
나는 이것을 +2 할 수 있으면 좋겠다. fivenum을 정말 잘 사용했습니다.
JayCe

range색인 사용 및 조정 79 바이트
J.Doe

1
@ J.Doe : 물론, 범위! 좋은 생각 감사합니다!
digEmAll






2

껍질 , 11 바이트

!5¡(T0mo↔↓¬

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

!5¡부분 을 줄여서 일부 바이트를 줄일 수 있다고 생각합니다 .

작동 원리

!5¡(

5th

mo↔↓¬

현재 버전의 입력을 매핑하고 0으로 구성되는 가장 긴 접두사를 삭제 한 후 각각을 뒤집습니다 (이 접두사를 삭제하면 Husk 's를 사용하여 수행됩니다. 이 기능은 Husk's를 사용하여 수행됩니다 . 함수를 통해 실행될 때 진실한 결과를 산출하는 목록, 즉 ¬논리적이 아닙니다).

T0

조옮김, 누락 된 항목을 0으로 바꿉니다 .


2

레티 나 , 87 바이트

/.\[(?!0,)/^+`\[0, 
[
/(?<! 0)]./^+`, 0]
]
\[(\[0(, 0)*], )+
[
(, \[0(, 0)*])+]|\[0]]
]

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

/.\[(?!0,)/^+`

적어도 하나의 행이 0으로 시작하지 않을 때까지 ...

\[0, 
[

... 각 행에서 선행 0을 제거하십시오.

/(?<! 0)]./^+`

적어도 하나의 행이 0으로 끝나지 않을 때까지 ...

, 0]
]

... 각 행에서 후행 0을 제거하십시오.

\[(\[0(, 0)*], )+
[

선행 행 0을 제거하십시오.

(, \[0(, 0)*])+]|\[0]]
]

후행 0 또는 마지막 남은 0을 제거하십시오.


1
@RickHitchcock 형식에 민감하며 공백을 추가하십시오 : 온라인으로 사용해보십시오!
Neil

2

, 48 바이트

F⁴«W∧θ¬Σ§θ±¹Σ⊟θ¿θ≔⮌E§θ⁰E觧θνλθ»⪫[]⪫Eθ⪫[]⪫ι, ¦, 

온라인으로 사용해보십시오! 링크는 자세한 버전의 코드입니다. 포맷을위한 15 바이트를 포함합니다. 설명:

F⁴«

4 번 반복하십시오.

W∧θ¬Σ§θ±¹

배열이 비어 있지 않지만 마지막 행의 합계가 0 인 동안 반복하십시오.

Σ⊟θ

배열에서 마지막 행을 제거하고 합계 길이의 행을 인쇄하십시오.

¿θ≔⮌E§θ⁰E觧θνλθ»

배열이 비어 있지 않으면 조옮김하십시오.

⪫[]⪫Eθ⪫[]⪫ι, ¦, 

배열을 멋지게 표시하여 표시하십시오. (표준 출력이 Iθ대신 사용됩니다.)


2

자바 스크립트, 144 140 129 127 바이트

w=>(t=w=>(q=(s=w=>w.some((r,j)=>r.find(e=>e,i=j))?w.slice(i).reverse():[[]])(s(w)))[0].map((e,j)=>q.map((e,i)=>q[i][j])))(t(w))

140-> 129 바이트, 감사합니다 @Arnauld

연산

  • 두 번 수행하십시오.
    • 0이 아닌 첫 번째 행 찾기
    • 이전 행을 잘라냅니다.
    • 0이 아닌 첫 번째 행 찾기
    • 이전 행을 잘라냅니다.
    • 바꾸어 놓다

f = w=>(t=w=>(q=(s=w=>w.some((r,j)=>r.find(e=>e,i=j))?w.slice(i).reverse():[[]])(s(w)))[0].map((e,j)=>q.map((e,i)=>q[i][j])))(t(w));

w1 = [[0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0]];
w2 = [[0, 0, 0, 0], [0, 0, 0, 3], [0, 0, 0, 0], [0, 5, 0, 0], [0, 0, 0, 0]];
w3 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
w4 = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];

console.log(f(w1).join("\n"));
console.log(f(w2).join("\n"));
console.log(f(w3).join("\n"));
console.log(f(w4));


도우미 함수 선언 대신을 사용하여 재정렬하여 (현재 단일) 주 함수 인수 주위의 괄호를 제거 하여 7 바이트절약 할 수 있습니다 . some/somefindIndex/find
Arnauld

나는 t 가 작동 할 수 있도록 s를 반환 하여 4 바이트더 절약 할 수 있다고 생각 합니다 . [[]]w[0]
Arnauld


2

PHP (> = 5.4) 200 194 186 184 바이트

( null빈 배열 대신 반환하여 6 바이트 )

( Titus 덕분에 8 바이트 )

( Titus 덕분에 참조로 호출하는 2 바이트 )

function R(&$a){$m=$n=1e9;foreach($a as$r=>$R)foreach($R as$c=>$C)if($C){$m>$r&&$m=$r;$M>$r||$M=$r;$n>$c&&$n=$c;$N>$c||$N=$c;}for(;$m<=$M;)$o[]=array_slice($a[$m++],$n,$N-$n+1);$a=$o;}

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

어떻게?

발견 최소 행 (위한 최대 인덱스 $m$M) 및 열 ( $n$N)에서와 대체하는 서브 어레이 입력을 $m,$n$M,$N(이 참조에 의해 호출이다).


if($C){$m>$r&&$m=$r;$M>$r||$M=$r;$n>$c&&$n=$c;$N>$c||$N=$c;}
Titus

...와 2 바이트while($m<=$M)$o[]=array_slice($a[$m++],$n,$N-$n+1);
Titus

@Titus : 훌륭한 팁을 주셔서 감사합니다. 사용하는 트릭 사랑 &&||나는 확실히 내가 아니라 다른 장소에서 그 트릭을 사용하실 수 있어요.
Night2

1
$a=대신 참조로 호출하여 다른 두 바이트를 저장할 수 있습니다. 대신 return.
Titus



2

J , 24 바이트

(|.@|:@}.~0=+/@{.)^:4^:_

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

설명

(|.@|:@}.~0=+/@{.)^:4^:_
            +/                sum
              @               of
               {.             the first row
          0=                  is zero? (1 = true, 0 = false)
       }.~                    chop off that many rows from the front
 |.@|:@                       rotate by 90 deg (transpose then reverse)
(                )^:4         repeat this process 4 times (rotating a total of 360 deg)
                     ^:_      fixpoint - repeat until no change

2

루비 , 73 63 바이트

->a{4.times{_,*a=a while a[0]&.sum==0;a=a.reverse.transpose};a}

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

편집 : 단순화, 또한 이전 버전의 모든 충돌 0

작동 방식 :

  • 4 회 수행 :
    • 첫 번째 라인이 있지만 첫 번째 줄을 제거하고이 가득 0
    • 배열을 시계 방향으로 90 ° 회전
  • 배열을 돌려줍니다

링크는 정확하지만 코드 블록의 답변은 &.sum<0대신에 라고 말합니다 &.sum<1.
코너 오브라이언

@ ConorO'Brien 나쁜, 새 버전은 빈 배열 (nil <1)에서 작동하지 않았습니다. 어쨌든 주목 해 주셔서 감사합니다
Asone Tuhid

1

옥타브 , 78 74 바이트

function x=f(x)
for k=1:nnz(~x)*4,x=rot90(x);x=x(:,~~cumsum(any(x,1)));end

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

설명

이렇게하면 행렬이 충분한 횟수 90( x=rot90(x)) 만큼 도 ( )만큼 회전합니다 for k=1:... end. 회전 수는의 배수 4이므로 최종 행렬의 원래 방향이 있습니다. 구체적으로, 회전 4수는 매트릭스 (0)에서 0의 수의 곱 nnz(~x)*4이다.

각 회전에 대해 왼쪽에 0으로 만 구성된 하나 이상의 열이 있으면 제거됩니다 ( x=x(:,~~cumsum(any(x,1)))).

이 프로세스 이후에 남아있는 것은 함수 ( function x=f(x))에 의해 출력됩니다 .



1

PHP, 188 바이트

function f(&$a){for($s=array_shift;!max($a[0]);)$s($a);for($p=array_pop;!max(end($a));)$p($a);for($w=array_walk;!max(($m=array_map)(reset,$a));)$w($a,$s);while(!max($m(end,$a)))$w($a,$p);}

참조로 전화하십시오.

고장

// call by reference
function f(&$a)
{
    // while first row is all zeroes, remove it
    while(!max($a[0]))array_shift($a);
    // while last row is all zeroes, remove it
    while(!max(end($a)))array_pop($a);
    // while first column is all zeroes, remove it
    while(!max(array_map(reset,$a)))array_walk($a,array_shift);
    // while last column is all zeroes, remove it
    while(!max(array_map(end,$a)))array_walk($a,array_pop);
}


1

파이썬 2 , 86 바이트

lambda a,l=1:a if l>4else([a.pop()for b in a if sum(a[-1])<1],f(zip(*a[::-1]),l+1))[1]

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

리스트리스트를 가져와 튜플리스트를 반환합니다.

설명

불완전한 이해력을 남용합니다. 이것은 동등한 확장 코드입니다.

def f(a,l=1):
    # after 4 rotations, the list is back in its original orientation, return
    if l > 4:
        return a
    else:
        # helper variable to store return values
        ret = []
        # "trim" all rows from "bottom" of list that only contain 0s
        # since we are always checking le that item in the list, don't need range(len(a))
        # since we are only removing at most one item per iteration, will never try to remove more than len(a) items
        # brackets surrounding generator force it to be consumed make a list, and therefore actually pop() list items
        ret.append([a.pop() for b in a if sum(a[-1]) < 1])
        # rotate the array, increase the number of rotations, and recursively call this function on the new array/counter
        ret.append(f(zip(*a[::-1]), l + 1)))
        # we only put both items in a list in order to stay in the one-line lambda format
        # discard the popped items and return the value from the recursive call
        return ret[1]

1

apt -h , 23 11 바이트

4Æ=sUb_dà z

시도 해봐


설명

                :Implicit input of 2D-array U
4Æ              :Map the range [0,4)
   s            :  Slice U from
    Ub          :   The first index in U where
      _dà      :    Any element is truthy (not zero)
          z     :  Rotate 90 degrees
  =             :  Reassign to U for the next iteration
                :Implicitly output the last element
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.