Trova la capacità degli oggetti stampati 2D


23

In un mondo 2D immaginario, un insieme di istruzioni di stampa 2D per un oggetto può essere rappresentato da un elenco di numeri interi come segue:

1 4 2 1 1 2 5 3 4

Ogni numero rappresenta l'altezza dell'oggetto in quel particolare punto. L'elenco sopra si traduce nel seguente oggetto quando stampato:

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

Lo riempiamo quindi con quanta più acqua possibile, ottenendo così:

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

Definiamo la capacità dell'oggetto di essere le unità di acqua che l'oggetto può contenere quando è completamente pieno; in questo caso, 11.

A rigor di termini, un'unità di acqua ( ~) può esistere in una posizione se e solo se è circondata da due blocchi solidi ( #) nella stessa fila.

Sfida

Prendi un elenco di numeri interi positivi come input (in qualsiasi formato) e genera la capacità dell'oggetto stampato quando l'elenco viene utilizzato come istruzioni.

Puoi presumere che l'elenco contenga almeno un elemento e tutti gli elementi siano compresi tra 1 e 255.

Casi test

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

Risposte:


15

Haskell, 54 byte

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

Le espressioni scanl1 max le scanr1 max lcalcolano il massimo corrente dell'elenco leggendo avanti e indietro, ovvero il profilo dell'acqua più terra se l'acqua andasse in una direzione.

orig:

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

Sinistra:

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

Destra:

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

Quindi, il profilo dell'immagine complessiva è il minimo di questi, che corrisponde a dove l'acqua non perde in nessuna direzione.

Minimo:

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

Infine, la quantità di acqua è la somma di questo elenco, che contiene sia acqua che terra, meno la somma dell'elenco originale, che contiene solo terra.


9

Gelatina, 10 byte

U»\U«»\S_S

Mentre APL richiede più parentesi e simboli J a due caratteri, l'algoritmo è bellissimo in Jelly.

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

Provalo qui .


4

MATL , 14

La mia risposta Matlab tradotta in MATL. l'algoritmo di xnor.

Y>GPY>P2$X<G-s

Spiegazione

Y>: cummax()(l'input è implicitamente inserito nello stack)

G: push input (di nuovo)

P: flip()

Y>: cummax()

P: flip()

2$X<: min([],[])(minimo due argomenti)

G: push input (di nuovo)

-: -

s: sum()


MATL è una lingua sostitutiva di Matlab? Puoi fornire un link nell'intestazione?
Addison Crump,

1
@FlagAsSpam Penso che sia un po 'più di questo: esolangs.org/wiki/MATL
Martin Ender

@ MartinBüttner Lo pseudocodice per questo sarebbe identico allo pseudocodice Matlab? Mi chiedo se sia una cosa di traduzione diretta, piuttosto che basata su una cosa.
Addison Crump,

1
@FlagAsSpam MATL è basato su stack, quindi sicuramente non è una semplice sostituzione.
Martin Ender,

Sì, è una traduzione diretta. MATL è basato su stack (notazione polacca inversa) con uno o tre caratteri brevi per gli operatori e le funzioni MATLAB . Vedi [ github.com/lmendo/MATL/blob/master/doc/MATL_spec.pdf] .
Rainer P.

3

Dyalog APL, 17 byte

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

Questo è un treno monadico che prende l'array di input sulla destra.

L'algoritmo è praticamente lo stesso di xnor, anche se l'ho trovato in modo indipendente. Esegue la ricerca del massimo in entrambe le direzioni (all'indietro invertendo l'array, scansionando e invertendo di nuovo) e trova il minimo vettoriale di quelli. Quindi sottrae l'array originale e le somme.

L'altro modo per farlo sarebbe quello di dividere l'array in ogni posizione, ma è più lungo.

Provalo qui .


1
Esattamente lo stesso che sono venuto qui per scrivere. :-) Quando otteniamo l'operatore dual (aka under), puoi salvare 3 byte con +/⊢-⍨⌈\⌊⌈\⍢⌽.
Adám,

2

Matlab, 47

Anche usando l'algoritmo di xnor.

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

1

MATLAB, 116 113 109 106 106 byte

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

Funziona memorizzando il punto più alto a sinistra e, ripetendo ogni punto successivo, trova il punto più alto a destra. Se il punto corrente è inferiore a entrambi i punti alti, aggiunge la differenza minima al volume cumulativo.

Codice non golfato:

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

La prima volta che ho provato a giocare a golf, MATLAB non sembra il migliore per farlo in ....


0

ES6, 101 byte

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)

Un'altra porta dell'algoritmo di @ xnor.



0

Pip -l , 19 byte

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

Accetta i numeri di input come argomenti della riga di comando. Oppure aggiungi la -rbandiera per prenderli come linee di stdin: provalo online!

Spiegazione

A differenza di tutte le altre risposte, in Pip era in realtà più breve costruire (una versione modificata di) l'arte ASCII e contare le unità idriche.

Iniziamo con gl'elenco degli argomenti.

[1 4 2 1 5 2 3]

0Xgproduce un elenco di stringhe di n zeri per ogni n in g.

[0 0000 00 0 00000 00 000]

ZD1quindi comprime insieme queste stringhe, usando 1per riempire eventuali spazi vuoti nell'elenco risultante rettangolare annidato:

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

STconverte questo elenco in una stringa. Il -lflag specifica che gli elenchi sono formattati come segue: ogni elenco nidificato viene unito senza un separatore e, al livello superiore, il separatore è newline. Quindi otteniamo questa stringa multilinea - essenzialmente, il diagramma dell'oggetto, ma sottosopra:

0000000
1001000
1011010
1011011
1111011

Troviamo quindi tutte le partite della regex `0.*0`. Questo corrisponde ai due muri più esterni e tutto ciò che li separa su ogni linea.

[0000000 001000 011010 0110]

Junisce queste stringhe in un'unica grande stringa e la $+somma, dando il numero di 1s - che è uguale alla quantità di acqua che l'oggetto può contenere.

6
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.