Encuentre la capacidad de los objetos impresos en 2D

23

En un mundo ficticio en 2D, un conjunto de instrucciones de impresión en 2D para un objeto se puede representar mediante una lista de enteros de la siguiente manera:

1 4 2 1 1 2 5 3 4

Cada número representa la altura del objeto en ese punto en particular. La lista anterior se traduce en el siguiente objeto cuando se imprime:

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

Luego lo llenamos con la mayor cantidad de agua posible, lo que resulta en esto:

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

Definimos la capacidad del objeto para ser las unidades de agua que el objeto puede contener cuando está completamente lleno; en este caso, 11.

Estrictamente hablando, una unidad de agua ( ~) puede existir en una ubicación si y solo está rodeada por dos bloques sólidos ( #) en la misma fila.

Reto

Tome una lista de enteros positivos como entrada (en cualquier formato) y genere la capacidad del objeto impreso cuando la lista se usa como instrucciones.

Puede suponer que la lista contiene al menos un elemento y todos los elementos están entre 1 y 255.

Casos de prueba

+-----------------+--------+
|      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 |
+-----------------+--------+
Sísifo
fuente

Respuestas:

15

Haskell, 54 bytes

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

Las expresiones scanl1 max ly scanr1 max lcalculan el máximo de lectura de la lista hacia adelante y hacia atrás, es decir, el perfil del agua más la tierra si el agua fluye en una dirección.

Orig:

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

Izquierda:

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

Correcto:

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

Entonces, el perfil de la imagen general es el mínimo de estos, que corresponde a donde el agua no se escapa en ninguna dirección.

Mínimo:

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

Finalmente, la cantidad de agua es la suma de esta lista, que contiene agua y tierra, menos la suma de la lista original, que contiene solo tierra.

xnor
fuente
9

Jalea, 10 bytes

U»\U«»\S_S

Si bien APL requiere varios paréntesis y J símbolos de dos caracteres, el algoritmo es hermoso en Jelly.

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

Probarlo aquí .

lirtosiast
fuente
4

MATL , 14

Mi respuesta de Matlab traducida a MATL. Algoritmo de xnor.

Y>GPY>P2$X<G-s

Explicación

Y>: cummax()(la entrada se empuja implícitamente en la pila)

G: entrada de empuje (nuevamente)

P: flip()

Y>: cummax()

P: flip()

2$X<: min([],[])(mínimo de dos argumentos)

G: entrada de empuje (nuevamente)

-: -

s: sum()

Rainer P.
fuente
¿Es MATL un lenguaje de sustitución de Matlab? ¿Puedes proporcionar un enlace en el encabezado?
Addison Crump
1
@FlagAsSpam Creo que es un poco más que eso: esolangs.org/wiki/MATL
Martin Ender
@ MartinBüttner ¿Sería el pseudocódigo para esto idéntico al pseudocódigo de Matlab? Me pregunto si es una cosa de traducción directa, en lugar de una cosa basada en algo.
Addison Crump
1
@FlagAsSpam MATL está basado en la pila, por lo que definitivamente no es una sustitución simple.
Martin Ender
Sí, es una traducción directa. MATL está basado en pila (notación de pulido inverso) con una o tres letras cortas para los operadores y funciones de MATLAB . Ver [ github.com/lmendo/MATL/blob/master/doc/MATL_spec.pdf] .
Rainer P.
3

Dyalog APL, 17 bytes

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

Este es un tren monádico que toma la matriz de entrada a la derecha.

El algoritmo es prácticamente el mismo que el de xnor, aunque lo encontré de forma independiente. Busca el máximo en ambas direcciones (hacia atrás invirtiendo la matriz, escaneando e invirtiendo nuevamente), y encuentra el mínimo vectorizado de esos. Luego resta la matriz original y las sumas.

La otra forma de hacerlo sería dividir la matriz en cada ubicación, pero eso es más largo.

Probarlo aquí .

lirtosiast
fuente
1
Exactamente lo mismo que vine a escribir aquí. :-) Cuando obtenemos el operador dual (también conocido como bajo), puede guardar 3 bytes con +/⊢-⍨⌈\⌊⌈\⍢⌽.
Adám
2

Matlab, 47

También usando el algoritmo de xnor.

@(x)sum(min(cummax(x),flip(cummax(flip(x))))-x)
Rainer P.
fuente
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

Esto funciona almacenando el punto más alto a la izquierda, y mientras recorre cada punto siguiente, encuentra el punto más alto a la derecha. Si el punto actual es menor que ambos puntos altos, entonces agrega la diferencia mínima al volumen acumulado.

Código sin golf:

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 primera vez que he intentado jugar al golf, MATLAB no parece ser el mejor para hacerlo ...

Lui
fuente
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)

Otro puerto del algoritmo de @xnor.

Neil
fuente
0

Pip -l , 19 bytes

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

Toma los números de entrada como argumentos de línea de comandos. O bien, agregue la -rbandera para tomarlos como líneas de stdin: ¡ Pruébelo en línea!

Explicación

A diferencia de todas las otras respuestas, en Pip en realidad fue más corto construir (una versión modificada de) el arte ASCII y contar las unidades de agua.

Comenzamos con gla lista de argumentos.

[1 4 2 1 5 2 3]

0Xgproduce una lista de cadenas de n ceros para cada n en g.

[0 0000 00 0 00000 00 000]

ZD1luego comprime estas cadenas juntas, usando 1para llenar cualquier espacio en la lista anidada rectangular resultante:

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

STConvierte esta lista en una cadena. La -lbandera especifica que las listas tienen el siguiente formato: cada lista anidada se une sin un separador, y en el nivel superior el separador es una nueva línea. Entonces obtenemos esta cadena multilínea, esencialmente, el diagrama del objeto, pero al revés:

0000000
1001000
1011010
1011011
1111011

Luego encontramos todas las coincidencias de la expresión regular `0.*0`. Esto coincide con las dos paredes exteriores y todo lo que hay entre ellas en cada línea.

[0000000 001000 011010 0110]

June estas cadenas en una sola cadena grande y la $+suma, dando el número de 1s, que es igual a la cantidad de agua que puede contener el objeto.

6
DLosc
fuente