2D 인쇄 된 물체의 용량 찾기


23

가상의 2D 세계에서 객체에 대한 일련의 2D 인쇄 명령은 다음과 같이 정수 목록으로 표시 될 수 있습니다.

1 4 2 1 1 2 5 3 4

각 숫자는 특정 지점에서 객체의 높이를 나타냅니다. 위의 목록은 인쇄시 다음 개체로 변환됩니다.

      #
 #    # #
 #    ###
 ##  ####
#########

그런 다음 가능한 한 많은 양의 물로 채우십시오.

      #
 #~~~~#~#
 #~~~~###
 ##~~####
#########

우리 는 물체가 완전히 채워 졌을 때 물체가 수용 할 수있는 물의 단위가되도록 물체 의 용량 을 정의합니다 . 이 경우 11입니다.

엄밀히 말하면, 물의 ~단위 ( #)는 동일한 행에서 두 개의 단단한 블록 ( )으로 둘러싸인 경우에만 한 위치에 존재할 수 있습니다 .

도전

양의 정수 목록을 임의의 형식으로 입력으로 가져 와서 목록이 명령으로 사용될 때 인쇄 된 오브젝트의 용량을 출력하십시오.

목록에 하나 이상의 요소가 있고 모든 요소가 1-255 사이라고 가정 할 수 있습니다.

테스트 사례

+-----------------+--------+
|      Input      | Output |
+-----------------+--------+
| 1               |      0 |
| 1 3 255 1       |      0 |
| 6 2 1 1 2 6     |     18 |
| 2 1 3 1 5 1 7 1 |      7 |
| 2 1 3 1 7 1 7 1 |      9 |
| 5 2 1 3 1 2 5   |     16 |
| 80 80 67 71     |      4 |
+-----------------+--------+

답변:


15

하스켈, 54 바이트

f l=(sum$zipWith min(scanl1 max l)$scanr1 max l)-sum l

식은 scanl1 max lscanr1 max l물이 한 방향으로 흘러 갈 것인지, 즉 물을 더한 땅의 프로필 앞뒤로 읽기 목록의 실행 최대를 계산한다.

오리지널 :

      #
 #    # #
 #    ###
 ##  ####
#########

왼쪽:

      #~~
 #~~~~#~#
 #~~~~###
 ##~~####
#########

권리:

~~~~~~#
~#~~~~#~#
~#~~~~###
~##~~####
#########

그런 다음 전체 그림의 프로파일이 최소값이며, 이는 물이 어느 방향으로도 누출되지 않는 위치에 해당합니다.

최저한의:

      #
 #~~~~#~#
 #~~~~###
 ##~~####
#########

마지막으로 물의 양은 물과 땅을 모두 포함하는이 목록의 합계에서 토지 만 포함하는 원래 목록의 합계를 뺀 것입니다.


9

젤리, 10 바이트

U»\U«»\S_S

APL에는 여러 괄호와 J 두 문자 기호가 필요하지만 Jelly에서는 알고리즘이 아름답습니다.

     »\          Scan maximums left to right
U»\U             Scan maximums right to left
    «            Vectorized minimum
       S_S       Sum, subtract sum of input.

여기에서 시도 하십시오 .


4

MATL , 14

Matlab 답변이 MATL로 번역되었습니다. xnor의 알고리즘.

Y>GPY>P2$X<G-s

설명

Y>: cummax()(입력이 스택에 암시 적으로 푸시 됨)

G: 푸시 입력 (다시)

P: flip()

Y>: cummax()

P: flip()

2$X<: min([],[])(최소한의 2 인수)

G: 푸시 입력 (다시)

-: -

s: sum()


MATL은 Matlab의 대체 언어입니까? 헤더에 링크를 제공 할 수 있습니까?
애디슨 크럼

1
@FlagAsSpam 나는 그것이 그 이상이라고 생각합니다 : esolangs.org/wiki/MATL
Martin Ender

@ MartinBüttner 이것에 대한 의사 코드가 Matlab 의사 코드와 동일합니까? 그것이 기반이 아닌 직접 번역 일인지 궁금합니다.
애디슨 크럼

1
@FlagAsSpam MATL은 스택 기반이므로 분명한 대체물이 아닙니다.
Martin Ender

예, 직접 번역입니다. MATLMATLAB 연산자 및 기능을 위해 1 ~ 3 개의 문자 속기가있는 스택 기반 (역 광택 표기법)입니다 . [ github.com/lmendo/MATL/blob/master/doc/MATL_spec.pdf]를 참조하십시오 .
Rainer P.

3

Dyalog APL, 17 바이트

+/⊢-⍨⌈\⌊⌽∘(⌈\⌽)

이것은 오른쪽에 입력 배열을 취하는 모나 딕 열차입니다.

알고리즘은 xnor와 거의 동일하지만 독립적으로 찾았습니다. 배열을 반대로하고, 다시 스캔하고 다시 뒤집어서 양방향으로 최대 값을 검색하고 벡터화 된 최소값을 찾습니다. 그런 다음 원래 배열을 빼고 합계합니다.

이를 수행하는 다른 방법은 각 위치에서 배열을 분할하는 것이지만 더 길다.

여기에서 시도 하십시오 .


1
정확히 내가 여기에 썼다. :-) 이중 (일명 under) 연산자를 받으면을 사용하여 3 바이트를 절약 할 수 있습니다 +/⊢-⍨⌈\⌊⌈\⍢⌽.
Adám

2

MATLAB, 47

또한 xnor의 알고리즘을 사용합니다.

@(x)sum(min(cummax(x),flip(cummax(flip(x))))-x)

1

MATLAB, 116 113 109 106 바이트

n=input('');s=0;v=0;l=nnz(n);for i=1:l-1;a=n(i);w=min([s max(n(i+1:l))]);if a<w;v=v+w-a;else s=a;end;end;v

이것은 왼쪽에 높은 지점을 저장하여 작동하며 다음 각 지점을 반복하면서 오른쪽에서 가장 높은 지점을 찾습니다. 현재 지점이 두 개의 높은 지점보다 작 으면 누적 볼륨에 최소 차이를 더합니다.

Ungolfed 코드 :

inputArray = input('');
leftHighPoint = inputArray(1);
volume = 0;
numPoints = nnz(inputArray);

for i = 1:numPoints-1
    currentPoint = inputArray(i); % Current value
    lowestHigh = min([max(inputArray(i+1:numPoints)) leftHighPoint]);

    if currentPoint < lowestHigh
        volume = volume + lowestHigh - currentPoint;
    else 
        leftHighPoint = currentPoint;
    end
end
volume

내가 골프를 처음 시도했을 때, MATLAB은 최선을 다하지 않습니다 ....


0

ES6, 101 바이트

a=>(b=[],a.reduceRight((m,x,i)=>b[i]=m>x?m:x,0),r=m=0,a.map((x,i)=>r+=((m=x>m?x:m)<b[i]?m:b[i])-x),r)

@xnor의 alghorithm의 또 다른 포트.



0

-l , 19 바이트

$+J(ST0XgZD1`0.*0`)

입력 번호를 명령 행 인수로 사용합니다. 또는 -r플래그를 추가하여 stdin 라인으로 가져 옵니다 . 온라인으로 사용해보십시오!

설명

다른 모든 답변과 달리 Pip에서는 ASCII 아트를 구성하고 수정 한 물 단위를 계산하는 것이 실제로 더 짧았습니다.

우리 g는 인수 목록으로 시작 합니다.

[1 4 2 1 5 2 3]

0Xg문자열의 목록을 생성하는 n 개의 각각의 제로 N 하여 g.

[0 0000 00 0 00000 00 000]

ZD1그런 다음 1결과 사각형 중첩 목록의 간격을 채우는 데 사용하여 이러한 문자열을 압축 합니다.

[[0 0 0 0 0 0 0] [1 0 0 1 0 0 0] [1 0 1 1 0 1 0] [1 0 1 1 0 1 1] [1 1 1 1 0 1 1]]

ST이리스트를 캐릭터 라인으로 변환합니다. -l마다 중첩리스트가 구분없이 함께 결합되고, 최상위에 세퍼레이터 개행이다리스트의 형식이되도록 지정 플래그는 다음과 같다. 따라서 우리는이 멀티 라인 문자열을 얻습니다. 본질적으로 객체의 다이어그램이지만 거꾸로되어 있습니다.

0000000
1001000
1011010
1011011
1111011

그런 다음 정규식과 일치하는 모든 항목을 찾습니다 `0.*0`. 이것은 두 개의 가장 바깥 쪽 벽과 각 선 사이의 모든 벽과 일치합니다.

[0000000 001000 011010 0110]

J함께 하나의 큰 문자열로 이러한 문자열을 조인하고, $+수 제공 금액을 1객체에 저장할 수있는 물의 양 같다 -들.

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