Temukan kapasitas objek cetakan 2D

23

Dalam dunia 2D fiksi, satu set instruksi pencetakan 2D untuk objek dapat diwakili oleh daftar bilangan bulat sebagai berikut:

1 4 2 1 1 2 5 3 4

Setiap angka mewakili ketinggian objek pada titik tertentu. Daftar di atas diterjemahkan ke objek berikut saat dicetak:

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

Kami kemudian mengisinya dengan air sebanyak yang kami bisa, menghasilkan ini:

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

Kami mendefinisikan kapasitas objek untuk menjadi unit air yang dapat dipegang benda saat sepenuhnya penuh; dalam hal ini, 11.

Sebenarnya, satu unit air ( ~) dapat ada di lokasi jika dan hanya jika dikelilingi oleh dua blok padat ( #) di baris yang sama.

Tantangan

Ambil daftar bilangan bulat positif sebagai input (dalam format apa pun), dan keluarkan kapasitas objek yang dicetak saat daftar digunakan sebagai instruksi.

Anda dapat menganggap daftar berisi setidaknya satu elemen dan semua elemen antara 1 dan 255.

Uji Kasus

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

Jawaban:

15

Haskell, 54 byte

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

Ekspresi scanl1 max ldan scanr1 max lmenghitung maksimum berjalan dari daftar bacaan maju dan mundur, yaitu profil air ditambah tanah jika air akan mengalir satu arah.

Orig:

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

Kiri:

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

Kanan:

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

Kemudian, profil gambar keseluruhan adalah yang minimum, yang sesuai dengan di mana air tidak bocor ke arah mana pun.

Minimum:

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

Akhirnya, jumlah air adalah jumlah daftar ini, yang berisi air dan tanah, dikurangi jumlah daftar asli, yang hanya berisi tanah.

Tidak
sumber
9

Jelly, 10 byte

U»\U«»\S_S

Meskipun APL membutuhkan beberapa tanda kurung, dan simbol dua karakter J, algoritmanya indah di Jelly.

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

Coba di sini .

lirtosiast
sumber
4

MATL , 14

Jawaban Matlab saya diterjemahkan ke MATL. Algoritma xnor.

Y>GPY>P2$X<G-s

Penjelasan

Y>: cummax()(input secara implisit didorong pada tumpukan)

G: push input (lagi)

P: flip()

Y>: cummax()

P: flip()

2$X<: min([],[])(minimum dua argumen)

G: push input (lagi)

-: -

s: sum()

Rainer P.
sumber
Apakah MATL adalah bahasa pengganti Matlab? Bisakah Anda memberikan tautan di tajuk?
Addison Crump
1
@FlagAsSpam Saya pikir ini sedikit lebih dari itu: esolangs.org/wiki/MATL
Martin Ender
@ MartinBüttner Apakah pseudocode untuk ini identik dengan pseudocode Matlab? Saya bertanya-tanya apakah itu terjemahan langsung, bukan berdasarkan pada terjemahan.
Addison Crump
1
@FlagAsSpam MATL berbasis stack, jadi ini jelas bukan substitusi biasa.
Martin Ender
Ya, ini terjemahan langsung. MATL berbasis stack (notasi polesan terbalik) dengan singkatan karakter satu hingga tiga untuk operator dan fungsi MATLAB . Lihat [ github.com/lmendo/MATL/blob/master/doc/MATL_spec.pdf] .
Rainer P.
3

Dyalog APL, 17 byte

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

Ini adalah kereta monadik yang mengambil larik input di sebelah kanan.

Algoritma ini hampir sama dengan xnor, walaupun saya menemukannya secara independen. Ini memindai maksimum di kedua arah (mundur dengan membalikkan array, memindai, dan membalikkan lagi), dan menemukan minimum vektorisasi dari mereka. Kemudian itu mengurangi array asli dan jumlah.

Cara lain untuk melakukan ini adalah dengan membagi array di setiap lokasi, tetapi itu lebih lama.

Coba di sini .

lirtosiast
sumber
1
Persis sama saya datang ke sini untuk menulis. :-) Ketika kami mendapatkan operator dual (alias bawah), Anda dapat menyimpan 3 byte dengan +/⊢-⍨⌈\⌊⌈\⍢⌽.
Adám
2

Matlab, 47

Juga menggunakan algoritma xnor.

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

Ini berfungsi dengan menyimpan titik tinggi di sebelah kiri, dan sementara iterasi melalui setiap titik berikutnya, menemukan titik tertinggi di sebelah kanan. Jika titik saat ini kurang dari kedua titik tinggi, maka itu menambah perbedaan minimum ke volume kumulatif.

Kode tidak dikunci:

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

Pertama kali saya mencoba bermain golf, MATLAB sepertinya bukan yang terbaik untuk melakukannya di ....

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

Port lain dari alghorithm @ xnor.

Neil
sumber
0

Python 2 , 68 byte

lambda l:sum(min(max(l[:i+1]),max(l[i:]))-v for i,v in enumerate(l))

Cobalah online!

ovs
sumber
0

Pip -l , 19 byte

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

Mengambil angka input sebagai argumen baris perintah. Atau, tambahkan -rbendera untuk menjadikannya sebagai garis stdin: Cobalah online!

Penjelasan

Tidak seperti semua jawaban lain, di Pip sebenarnya lebih pendek untuk membangun (versi modifikasi) seni ASCII dan menghitung unit air.

Kita mulai dengan g, daftar argumen.

[1 4 2 1 5 2 3]

0Xgmenghasilkan daftar string n nol untuk setiap n dalam g.

[0 0000 00 0 00000 00 000]

ZD1kemudian ritsleting string ini bersama-sama, gunakan 1untuk mengisi setiap celah di daftar bersarang persegi panjang yang dihasilkan:

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

STmengubah daftar ini menjadi string. The -lmenspesifikasikan flag yang daftar diformat sebagai berikut: setiap daftar bersarang bergabung bersama tanpa pemisah, dan pada tingkat atas separator adalah baris baru. Jadi kita mendapatkan string multiline ini - pada dasarnya, diagram objek, tetapi terbalik:

0000000
1001000
1011010
1011011
1111011

Kami kemudian menemukan semua kecocokan dari regex `0.*0`. Ini cocok dengan dua dinding terluar dan segala sesuatu di antara mereka di setiap baris.

[0000000 001000 011010 0110]

Jmenggabungkan string-string ini menjadi satu string besar, dan $+menjumlahkannya, memberikan jumlah 1s - yang sama dengan jumlah air yang bisa dipegang oleh objek.

6
DLosc
sumber