Ermitteln Sie die Kapazität von 2D-Druckobjekten

23

In einer fiktiven 2D-Welt kann ein Satz von 2D-Druckanweisungen für ein Objekt durch eine Liste von Ganzzahlen wie folgt dargestellt werden:

1 4 2 1 1 2 5 3 4

Jede Zahl steht für die Höhe des Objekts an diesem bestimmten Punkt. Die obige Liste wird beim Drucken in das folgende Objekt übersetzt:

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

Wir füllen es dann mit so viel Wasser wie wir können, was dazu führt:

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

Wir definieren die Kapazität des Objekts als die Wassereinheiten, die das Objekt halten kann, wenn es vollständig gefüllt ist. in diesem Fall 11.

Genau genommen kann eine Wassereinheit ( ~) genau dann an einem Ort existieren, wenn sie von zwei festen Blöcken ( #) in derselben Reihe umgeben ist.

Herausforderung

Nehmen Sie eine Liste positiver Ganzzahlen als Eingabe (in einem beliebigen Format) und geben Sie die Kapazität des Objekts aus, das gedruckt wird, wenn die Liste als Anweisung verwendet wird.

Sie können davon ausgehen, dass die Liste mindestens ein Element enthält und alle Elemente zwischen 1 und 255 liegen.

Testfälle

+-----------------+--------+
|      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 |
+-----------------+--------+
Sisyphus
quelle

Antworten:

15

Haskell, 54 Bytes

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

Die Ausdrücke scanl1 max lund scanr1 max lberechnen das laufende Maximum der Liste vorwärts und rückwärts, dh das Profil des Wassers plus Land, wenn Wasser in eine Richtung fließen würde.

Herkunft:

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

Links:

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

Recht:

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

Dann ist das Profil des Gesamtbildes das Minimum von diesen, was dort entspricht, wo das Wasser in keiner Richtung austritt.

Minimum:

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

Schließlich ist die Wassermenge die Summe dieser Liste, die sowohl Wasser als auch Land enthält, abzüglich der Summe der ursprünglichen Liste, die nur Land enthält.

xnor
quelle
9

Gelee, 10 Bytes

U»\U«»\S_S

Während APL mehrere Klammern und J zwei Zeichen erfordert, ist der Algorithmus in Jelly wunderschön.

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

Probieren Sie es hier aus .

Lirtosiast
quelle
4

MATL , 14

Meine Matlab-Antwort wurde in MATL übersetzt. xnors Algorithmus.

Y>GPY>P2$X<G-s

Erläuterung

Y>: cummax()(Eingabe wird implizit auf den Stack gepusht)

G: Eingang drücken (erneut)

P: flip()

Y>: cummax()

P: flip()

2$X<: min([],[])(mindestens zwei Argumente)

G: Eingang drücken (erneut)

-: -

s: sum()

Rainer P.
quelle
Ist MATL eine Substitutionssprache von Matlab? Können Sie einen Link in der Kopfzeile angeben?
Addison Crump
1
@FlagAsSpam Ich denke, es ist ein bisschen mehr als das: esolangs.org/wiki/MATL
Martin Ender
@ MartinBüttner Wäre der Pseudocode dafür identisch mit dem Matlab-Pseudocode? Ich frage mich, ob es sich eher um eine direkte Übersetzung als um eine auf etwas basierende handelt.
Addison Crump
1
@FlagAsSpam MATL ist stapelbasiert, es handelt sich also definitiv nicht um eine einfache Substitution.
Martin Ender
Ja, es ist eine direkte Übersetzung. MATL ist stapelbasiert (umgekehrte polnische Notation) mit ein bis drei Kurzzeichen für MATLAB- Operatoren und -Funktionen. Siehe [ github.com/lmendo/MATL/blob/master/doc/MATL_spec.pdf] .
Rainer P.
3

Dyalog APL, 17 Bytes

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

Dies ist ein monadischer Zug, der das Eingabe-Array auf der rechten Seite übernimmt.

Der Algorithmus ist so ziemlich der gleiche wie der von xnor, obwohl ich ihn unabhängig gefunden habe. Es sucht nach dem Maximum in beiden Richtungen (rückwärts durch Umkehren des Arrays, Scannen und erneutes Umkehren) und findet das vektorisierte Minimum von diesen. Dann subtrahiert es das ursprüngliche Array und summiert.

Die andere Möglichkeit wäre, das Array an jedem Ort zu teilen, aber das ist länger.

Probieren Sie es hier aus .

Lirtosiast
quelle
1
Genau so bin ich hierher gekommen, um zu schreiben. :-) Wenn wir den dualen Operator (aka under) bekommen, können Sie mit 3 Bytes sparen +/⊢-⍨⌈\⌊⌈\⍢⌽.
Adám
2

Matlab, 47

Auch unter Verwendung von xnors Algorithmus.

@(x)sum(min(cummax(x),flip(cummax(flip(x))))-x)
Rainer P.
quelle
1

MATLAB, 116 113 109 106 Bytes

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

Dies funktioniert, indem der höchste Punkt links gespeichert und beim Durchlaufen des nächsten Punkts der höchste Punkt rechts gefunden wird. Wenn der aktuelle Punkt kleiner als die beiden höchsten Punkte ist, wird die minimale Differenz zum kumulierten Volumen hinzugefügt.

Ungolfed-Code:

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

Das erste Mal, dass ich versucht habe, irgendetwas zu golfen, scheint MATLAB nicht das Beste zu sein, um es zu tun.

Lui
quelle
0

ES6, 101 Bytes

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)

Ein weiterer Hafen von @ xnors Alghorithmus.

Neil
quelle
0

Pip -l , 19 Bytes

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

Nimmt Eingabenummern als Befehlszeilenargumente. Oder fügen Sie die -rFlagge hinzu, um sie als Standardzeilen zu verwenden: Probieren Sie es online aus!

Erläuterung

Im Gegensatz zu allen anderen Antworten war es in Pip tatsächlich kürzer, die ASCII-Kunst zu konstruieren (eine modifizierte Version davon) und die Wassereinheiten zu zählen.

Wir beginnen mit gder Liste der Argumente.

[1 4 2 1 5 2 3]

0XgErzeugt eine Liste von Strings mit n Nullen für jedes n in g.

[0 0000 00 0 00000 00 000]

ZD1Zippen Sie dann diese Zeichenfolgen zusammen, indem Sie 1Lücken in der resultierenden rechteckigen verschachtelten Liste ausfüllen:

[[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]]

STkonvertiert diese Liste in einen String. Das -lFlag gibt an, dass Listen wie folgt formatiert sind: Jede verschachtelte Liste wird ohne Trennzeichen zusammengefügt, und auf der obersten Ebene ist das Trennzeichen Newline. So erhalten wir diese mehrzeilige Zeichenfolge - im Wesentlichen das Diagramm des Objekts, aber verkehrt herum:

0000000
1001000
1011010
1011011
1111011

Wir finden dann alle Übereinstimmungen des regulären Ausdrucks `0.*0`. Dies passt zu den beiden äußersten Wänden und zu allem dazwischen in jeder Zeile.

[0000000 001000 011010 0110]

JFügt diese Zeichenfolgen zu einer großen Zeichenfolge zusammen und $+summiert sie. Dabei wird die Anzahl 1s angegeben, die der Menge an Wasser entspricht, die das Objekt aufnehmen kann.

6
DLosc
quelle