자기 조각


14

이것은 그래프 구성에 대한 나의 이전의 도전 의 느슨한 연속이다 .

배경

편심 한 예술가가 그의 조각품의 구조적 무결성을 평가하기 위해 당신을 고용했습니다. 그는 입방체 모양의 자석을 가져다가 거대한 더미에 하나씩 떨어 뜨려 예술 작품을 만듭니다. 그의 방법을 더 잘 분석하기 위해 다음과 같은 2 차원 모델을 사용합니다. 빈 바닥에서 시작하여 #정수 좌표에 자석 을 놓습니다 0.

       |
       v
       #
===============
       0

에 다른 자석을 떨어 뜨리면 0이전 자석 위에 놓입니다.

       |
       v
       #
       #
===============
       0

이제에 자석을 하나 더 떨어 뜨린 0다음에 하나를 떨어 뜨립니다 1.

        |
       #v
       ##
       #
===============
       0

위에서 볼 수 있듯이, 떨어지는 자석 은 통과 하는 두 번째 자석에 달라 붙습니다 (첫 번째 자석은 단지 느리게합니다). 두 번째 자석은 첫 번째 자석 바로 아래에있을 필요는 없으며 양쪽 자석은 여전히 ​​하나의 자석으로 간주됩니다.

      #   #
      ##|##
      # v #
      ### #
      #   #
===============
       0

아티스트는 최종 조각에서 최대 수직 간격, 즉 같은 기둥에있는 두 자석 사이의 최대 빈 공간 수 또는 자석과 그 아래지면을 계산하려고합니다. 위 그림에서이 숫자는 3 (열 2)입니다.

입력

아티스트가 자석을 떨어 뜨리는 좌표를 나타내는 정수 목록은 왼쪽에서 오른쪽으로 읽습니다. 좌표가 만족스럽고 -1024 <= i < 1024목록의 길이 가 최대라고 생각할 수 있습니다 1024.

산출

최종 조각에서 최대 수직 간격. 빈 조각품에는 틈 -1이 있으며이 조각가는 조각가이기 때문에 포함되어야합니다.

추가 규칙

기능이나 전체 프로그램을 제공 할 수 있습니다. 가장 짧은 바이트 수가 이기고 표준 허점은 허용되지 않습니다. 설명이있는 코드가 선호됩니다.

테스트 사례

[] -> -1
[0,2,1] -> 0
[0,0,0,0,0,1,-1] -> 3
[0,0,0,0,0,1,1,1,2] -> 4
[1,1,2,2,2,2,2,2,1] -> 2
[1,1,2,2,2,2,2,2,1,0,1,0] -> 2
[1,2,1,2,1,2,1,2,2,2,2,1,0] -> 3
[-1,-1,-1,1,1,1,0] -> 1
[-1,-1,-1,-1,2,2,1,1,2,2,2,1,0] -> 2
[-2,-2,-2,-1,-1,-1,0,0,0,1,1,1,2,2,2,3,3,4,4,5,5,5,6] -> 6

답변:


1

Dyalog APL, 73 70 자

{y←⍬⋄⌈/¯1,,¯1-2-/0,x⊢⌸{y,←⌈/(1+y/⍨0=⍵),Y⊃⍨2⊃⍒Y←1 1,∪y/⍨1=⍵}¨|x-¯1↓¨,\x←⍵}

{y←⍬⋄¯1⌈⌈/,¯1-2-/¯1,⍵⊢⌸{y,←⌈/(1+y/⍨0=⍵),⊃1↓{⍵[⍒⍵]}∪y/⍨1=⍵}¨|⍵-¯1↓¨,\⍵}

First statement:
       y←⍬  initialize semi-global variable y with an empty vector
Second statement, from right to left:
         ⍵  the vector of x coordinates
       ,\⍵  concat-scan: all prefixes of ⍵ of length 1, 2, ..., ≢⍵
   ¯1↓¨,\⍵  drop the last element of each prefix, lengths are 0, 1, ..., (≢⍵)-1
|⍵-¯1↓¨,\⍵  for each x: magnitudes of differences between x and its predecessors
 {...}¨...  execute the code in parens for each item of the argument
         ⍵  is now a single vector of differences from those described above
       1=⍵  boolean mask, where are our neighbouring xs?
    y/⍨1=⍵  select the ys corresponding to our neighbouring xs
   ∪y/⍨1=⍵  unique ys
   {⍵[⍒⍵]}  sort descending
       ⊃1↓  first of one-drop, i.e. get the second element if it exists, otherwise 0
       0=⍵  which previous xs are the same as our x?
  1+y/⍨0=⍵  select the corresponding ys and add 1 to them
        ⌈/  maximum of all the ys described so far
       y,←  append to the semi-global y
            the result from {} will be identical to y
  ⍵⊢⌸{...}  a matrix of ys, grouped in rows by x (which is now in ⍵) and zero-padded
       ¯1,  prepend ¯1 to the left of each row
       2-/  differences between consecutive horizontal elements, result is a matrix
       ¯1-  negative one minus each element of the matrix
         ,  ravel the matrix (linearize it to a vector)
        ⌈/  maximum; if the vector is empty, return ¯1.8e308, a very small number
     ¯1⌈⌈/  greater of ¯1 and the ⌈/  to avoid the very small number

참고 : UTF-8을 가정하면 길이는 122 바이트 (도전은 바이트 단위)입니다.
MtnViewMark


나는 매우 동정심이 많다. 나는 종종 내 골프의 Haskell에서 비 ASCII 캐릭터를 사용하는 데 지쳐왔다. 그 이후로 Q가 문자 또는 바이트 수로 카운트를 지정하면 상당히주의를 기울였습니다.
MtnViewMark

바이트 단위로 @MtnViewMark 점수를 매기는 것이 UTF-8 바이트로 점수를 매기는 것을 의미하지는 않습니다. APL을 위해 그렇게하는 것은 ASCII를 중요한 표준으로 인식하기에는 너무 오래되어서 그것을 처벌하고 있습니다. APL의 문자 세트는 1 바이트 코드 페이지에 쉽게 맞으며 해당 코드 페이지가 존재합니다 . 따라서 해당 코드 페이지를 인코딩으로 사용하면 각 문자 바이트입니다. 반면에 Haskell에서 비 ASCII 문자를 사용하는 경우 ASCII 문자와 비 ASCII 문자를 모두 포함하는 인코딩을 사용해야합니다. 일반적으로 UTF-8입니다.
Martin Ender

@ngn-이제 이것에 대한 대부분의 메타 게시물을 읽은 것은 아아, 여전히 진흙 투성이 인 것 같습니다. 그러나 챌린지가 바이트로 스코어링 될 때 APL을 바이트로 스코어링하는 것이 가장 좋지만, 인코딩이 사용 된 곳을 언급하십시오.
MtnViewMark 2

4

하스켈 - 217 185 182 바이트

import Data.List
r g n m|m==n=max(head(g m)+1)((reverse.(0:).nub.sort$g(m-1)++g(m+1))!!1):g m|1<3=g m
j x=(-1)-minimum(0:(map(foldl r(\_->[0])x)[-1024..1024]>>=(tail>>=zipWith(-))))

용법:

j [1,2,1,2,1,2,1,2,2,2,2,1,0]

이 함수는 주어진 x 위치에 대한 자석 y 위치 목록을 반환하는 다른 함수를 만듭니다. 그것으로 모든 x 위치 -1024 .. 1024의 간격을 계산하고 최대 값을 취합니다 (편집 : 간격이 음수이므로 최소값을 사용합니다. 숫자가 낮을수록 간격이 더 큼).


영리한 접근! 내가 골프를 쳤다는 것을 신경 쓰지 않기를 바랍니다.
MtnViewMark

@MtnViewMark : 전혀 아닙니다. 내가 저장 3 더 바이트를 발견했습니다하지 , 음수로 가서을 . flip-minimum
nimi

내 저장소 에서이 코드, 42997-Magnetic.hs 를 찾을 수 있습니다. 여기에는 테스트 사례에 대한 테스트 하네스와 조각을 표시하는 시각화 프로그램이 포함되어 있습니다.
MtnViewMark

3

자바 스크립트, 201 193

F=P=>{m=[];for(p of P){s=2;c=m[p]=m[p]||[];for(i=1e4;~i&&s;i--){if((m[p-1]||[])[i]||(m[p+1]||[])[i])s--;if(c[i-1]) s=0}c[++i]=1}g=-1;m.map(c=>{ d=0;for(i in c){g=i-d>g?i-d:g;d=++i} });return g}

F ([1,1,2,2,2,2,2,2,1]) === 2

또는 읽을 수있는 버전

F=P=>{
  m=[];  // magnet positions
  for(p of P){ // every dropped magnet
    s=2; // initial speed
    c=m[p]=m[p]||[]; // column where magnet is dropping
    for(i=1e4;~i&&s;i--){ // continue until at floor or zero speed
      if((m[p-1]||[])[i]||(m[p+1]||[])[i])s--;  // magnet on either side, decrease speed
      if(c[i-1]) s=0; // magnet is directly below
    }
    c[++i]=1;
  }
  g=-1; // maximum gap
  m.map(c=>{ 
          d=0;for(i in c){g=i-d>g?i-d:g;d=++i;} 
       });
  return g;
};

2

파이썬 2.7, 327

from itertools import * 
s=input()
if s:m=min(s);l=[[] for _ in range(max(s)-m+3)]
for t in s:
    i=t-m+1;r=l[i];c=[x or y for x,y in izip_longest(l[i-1],l[i+1])][::-1][1:];j=len(c)-c.index(1)-1-len(r) if any(c) else 0;l[i]=r+[0]*j+[1]
print -1 if not s else max([len(list(q)) if b==0 else 0 for k in l for b,q in groupby(k)])

공백 골프 전에 다음과 같이 보입니다.

from itertools import * 
s=input()
if s:
    m=min(s)
    l=[[] for _ in range(max(s)-m+3)]
for t in s:
    i=t-m+1;r=l[i]
    c=[x or y for x,y in izip_longest(l[i-1],l[i+1])][::-1][1:]
    j=len(c)-c.index(1)-1-len(r) if any(c) else 0
    l[i]=r+[0]*j+[1]
print -1 if not s else max([len(list(q)) if b==0 else 0 for k in l for b,q in groupby(k)])

다음은 주로 내 자신의 이익을 위해 더 복잡한 줄에 대한 설명입니다.

l=[[] for _ in range(max(s)-m+3)] 

이것은 길이 max (drops) -min (drops) +1의 빈 목록과 양쪽에 자리 표시 자의 배열을 구성합니다. 빈 목록 배열을 구성하기 위해 항상 [[]] * K를 쓰려고하지만 K는 같은 빈 목록에 대한 포인터를 만듭니다.

c=[x or y for x,y in izip_longest(l[i-1],l[i+1])][::-1][1:] 

itertools의 izip_longest 함수는 zip과 비슷하지만 목록을 함께 압축하기 위해 짧은 목록을 없음으로 채 웁니다. 슬라이싱 [::-1]은 "또는"비교에서 0과 1의 목록을 반대로 바꿉니다. 다음 행에서 index 메소드를 사용하기 위해 목록이 반대로되어 요소의 첫 번째 인스턴스를 찾습니다. 비어 있지 않은 열의 마지막 요소는 1이어야하므로이 목록은 반대 목록의 첫 번째 요소이며 슬라이스 [1 :]을 통해 무시됩니다.

j=len(c)-c.index(1)-1-len(r) if any(c) else 0 
l[i]=r+[0]*j+[1]

먼저 열 i의 길이와 인접한 열에서 두 번째 1의 위치 사이의 차이를 계산하십시오. 차이가 양수이면 1을 추가하기 전에 열 i에 많은 영 (0)을 추가하십시오. 양수가 아닌 숫자 [0]은 빈 목록입니다.

max([len(list(q)) if b==0 else 0 for k in l for b,q in groupby(k)])

itertools의 groupby 함수는 목록을 연속 요소의 하위 시퀀스로 분할합니다. 이 줄은 모든 열에서 0의 모든 하위 시퀀스 길이의 최대 값을 찾습니다. groupby는 당연히 len 메소드를 지원하지 않는 생성기 (모든 itertools 함수와 같은)를 리턴하므로 각 서브 시퀀스 q를 목록으로 캐스트해야합니다.


1

자바-281 바이트

꽤 직설적 인.

먼저 조각을 배열로 구성합니다.

그런 다음 가장 큰 차이를 찾습니다.

int a(int[]b){
        int[][]d=new int[9999][9999];
        int g,r,t,y=-1;
        for(int c:b){
            c+=5000;
            g=0;
            for(r=9998;r>=0;r--){
                if(r==0||d[c][r-1]==1){d[c][r]=1;break;}
                if((d[c-1][r]==1||d[c+1][r]==1)&&++g==2){d[c][r]=1;break;}
            }
        }
        for(int[] k:d){
            t=0;
            for(int i:k){
                if(i==0)t++;
                else{if(t>y)y=t;t=0;}
            }
        }
        return y;
    }

작은-

int a(int[]b){int[][]d=new int[9999][9999];int g,r,t,y=-1;for(int c:b){c+=5000;g=0;for(r=9998;r>=0;r--){if(r==0||d[c][r-1]==1){d[c][r]=1;break;}if((d[c-1][r]==1||d[c+1][r]==1)&&++g==2){d[c][r]=1;break;}}}for(int[] k:d){t=0;for(int i:k){if(i==0)t++;else{if(t>y)y=t;t=0;}}}return y;}

첫 번째 ||를 로 바꾸면 바이트를 저장할 수 있습니다 |. 또한 y인쇄하는 대신 반환 하면 9 바이트가 절약됩니다.
Ypnypn

@Ypnypn, 감사합니다! BTW, 첫 번째 문장은 ArrayIndexOutOfBounds 예외 (-1)를 발생시키는 것으로 보입니다. (비트 연산자에 대한 경험이 많지 않습니다)
Stretch Maniac

약 1.5 년이 지났지 만 더 많이 골프를 칠 수 있습니다 : ( 272 bytes ) : int a(int[]b){int z=9999,d[][]=new int[z][z],g,r,t,y=-1;for(int c:b){c+=z/2;g=0;for(r=z;--r>-2;){if(r==0||d[c][r-1]==1){d[c][r]=1;break;}if((d[c-1][r]==1|d[c+1][r]==1)&&++g==2){d[c][r]=1;break;}}}for(int[]k:d){t=0;for(int i:k){if(i==0)t++;else{if(t>y)y=t;t=0;}}}return y;}. 변경 사항 요약 : z=9999추가 및 사용되었습니다. intint[][]필드 초기화 하나에 병합되었습니다; 두 번째 |||; for(r=9998;r>=0;r--)로 변경되었습니다for(r=z;--r>-2;)
Kevin Cruijssen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.