Itu hujan? Saya tidak tahu

10

Ini adalah tetesan hujan:

! | . " :

Ini adalah partikel awan:

( ) _ @ $ &

Saya ingin Anda memverifikasi, ketika diberi blok teks, apakah hujan atau tidak. Hujan jika, untuk setiap tetesan hujan, ada partikel awan di suatu tempat di atasnya. Harus ada satu partikel awan untuk setiap tetes hujan. Output truthy atau nilai falsy yang menunjukkan kesimpulan Anda.

Contoh yang valid

(@@@@@@)
 ( $ &  )
Q   (  )
..  .  !
 : .
  |"   !
    .

()()()
......

@_$ &
errrr
h_r-5
.:. .
 "

Contoh tidak valid

!
()

$$$$$
(   )
:::::
.....

Ini adalah sehingga program terpendek dalam karakter menang.

Seadrus
sumber
2
"Pasti ada satu partikel awan untuk setiap tetes hujan"
Biru
@feersum Contoh tidak valid kedua adalah contoh yang Anda cari.
Seadrus
@feersum, begitu;)
Seadrus
Bisakah kita mengasumsikan baris diisi dengan spasi untuk membentuk persegi panjang?
feersum
3
@ Zona, tidak: setidaknya satu
msh210

Jawaban:

4

APL (30)

{∧/∊≤/+⍀¨⍵∘∊¨'!|.":' '()_@$&'}

Ini adalah fungsi yang mengambil matriks karakter sebagai input, dan memberikan output boolean.

Uji:

      ex1 ex2 ex3 ex4 ex5
┌─────────┬──────┬─────┬──┬─────┐
│(@@@@@@) │()()()│@_$ &│! │$$$$$│
│ ( $ &  )│......│errrr│()│(   )│
│Q   (  ) │      │h_r-5│  │:::::│
│..  .  ! │      │.:. .│  │.....│
│ : .     │      │ "   │  │     │
│  |"   ! │      │     │  │     │
│    .    │      │     │  │     │
└─────────┴──────┴─────┴──┴─────┘
      {∧/∊≤/+⍀¨⍵∘∊¨'!|.":' '()_@$&'}¨ex1 ex2 ex3 ex4 ex5
1 1 1 0 0

Penjelasan:

  • ⍵∘∊¨'!|.":' '()_@$&': untuk kedua set karakter (hujan dan awan), dan setiap karakter dalam ⍵, lihat apakah karakternya adalah anggota set.
  • +⍀¨: dapatkan jumlah running untuk setiap kolom dan setiap set
  • ≤/: untuk setiap posisi dalam ⍵, periksa bahwa jumlah tetesan hujan tidak melebihi jumlah partikel awan dalam jumlah yang berjalan
  • ∧/∊: kembalikan boolean DAN semua elemen dalam hasil
marinus
sumber
5

C ++ 11, 186 184 byte

#include<map>
int i,c;int main(){std::map<int,int>p;while(~(c=getchar())){for(int m:{40,41,95,64,36,38})p[i]+=c==m;for(int m:{33,124,46,34,58})if(c==m&&!p[i]--)return 1;i=c-10?i+1:0;}}

Tidak disatukan

#include <map>
int i, c;
int main()
{
    std::map<int, int> p;
    while (~(c = getchar()))
    {
//        for (int m : { '(', ')', '_', '@', '$', '&'})
        for (int m : { 40, 41, 95, 64, 36, 38})
            p[i] += c == m;
//        for (int m : { '!', '|', '.', '"', ':'})
        for (int m : { 33, 124, 46, 34, 58})
            if (c == m && !p[i]--)
                return 1;
        i = c - '\n' ? i + 1 : 0;
    }
    return 0;
}

Pendekatan dasar, menyimpan posisi partikel awan dalam satu baris dan jika partikel hujan dijumpai, ia memeriksa apakah partikel awan berada di atasnya dan mengurangi penghitung partikel awan dalam kolom itu. Program mengembalikan 0 jika valid dan 1 sebaliknya.

Zereges
sumber
Tidak bisakah Anda ganti c-m?0:p[i]++dengan p[i]+=c==m? Atau apakah itu tidak lagi berfungsi di C ++ 11?
marinus
@marinus Mungkin ya.
Zereges
4

Siput , 125

{t.{t(\(|\)|\_|\@|\$|\&)=(u.,~)d!(.,~)t.!(.,~},!{t(\!|\||\.|\"|\:)ud!(.,~}t(\(|\)|\_|\@|\$|\&)!(d.,~)u.,~},!{t(\!|\||\.|\"|\:

Program mengeluarkan area kisi (atau 1 jika luasnya 0) jika hujan; jika tidak, saya hanya menerapkan kelas karakter gaya regex.

Versi tidak dikoleksi Ini berisi instruksi palsu untuk awan atau tetesan hujan alih-alih menuliskan semua omong kosong. \whatever(Digantikan dengan .dalam program nyata) berarti sesuatu yang seharusnya menjadi tetesan hujan, tetapi sebenarnya bisa menjadi apa saja karena tidak masalah jika kita mencocokkan tetesan hujan dengan awan.

{
    t \whatever   ,, Pick a drop in a new column
    {
        t \cloud ,, Find a cloud with 
        =(u.,~)  ,, nothing above in the same column marked
        !(d.,~)  ,, but not in an empty column
        t \whatever
        !(d.,~)
    },
    !(t \drop ud !(.,~) )  ,,no drops remaining in column
    t \cloud
    !(d.,~)
    u.,~
},             ,, repeated 0 or more times
! (t \drop)   ,, no drops left
feersum
sumber
sistem komentar yang menarik.
Seadrus
2

Python 2, 121 byte

def f(i):
 for l in zip(*i.split('\n')):
  s=0
  for p in l:
   s+=p in'()_@$&';s-=p in'!|.":'
   if s<0:return
 return 1

Diharapkan input akan menjadi persegi panjang.

TFeld
sumber
1

JavaScript ES6, 112

Tes menjalankan cuplikan di bawah ini di peramban yang mendukung EcmaScript 6 yang menerapkan fungsi panah, operator sebar, dan string templat (saya menggunakan Firefox)

f=t=>!t.split`
`.some(r=>[...r].some((c,i)=>(c='!|.":()_@$&'.indexOf(c),n[i]=~c?c<5?~-n[i]:-~n[i]:n[i])<0),n=[])

//TEST
console.log=x=>O.innerHTML+=x+'\n';

test_valid = [
 '(@@@@@@)\n ( $ &  )\nQ   (  )\n..  .  !\n : .\n  |"   !\n    .',
 '()()()\n......',
 '@_$ &\nerrrr\nh_r-5\n.:. .\n "'
] 
console.log('Valid');
test_valid.forEach(t=>console.log(t+'\n'+f(t)+'\n'))

test_invalid = ['!\n()','$$$$$\n(   )\n:::::\n.....']
console.log('Invalid');
test_invalid.forEach(t=>console.log(t+'\n'+f(t)+'\n'))
<pre id=O></pre>

edc65
sumber
1

Perl 5, 80

79, plus satu untuk -Ebukan-e

@a=();while(<>){@_=split'';(0>($a[$_]+=/[()_@&\$]/-/[!|.":]/)?die:1)for@_}say 1
msh210
sumber
2
Saya tidak bisa membaca Perl, tetapi saya kuat dalam matematika: 79 + 1 = 80
edc65
1

Julia, 90 karakter

s->all(cumsum(map(i->i∈"!|.\":"?-1:i∈"()_@\$&",mapfoldl(collect,hcat,split(s,"
")))').>-1)

Berbeda dengan solusi asli (di bawah), ini menggunakan matematika untuk menentukan solusi. mapfoldl(collect,hcat,split(s,"\n"))(ditulis di atas dengan \ndiganti dengan baris baru yang sebenarnya untuk menyimpan karakter) mengubah string menjadi array karakter 2d. map(i->i∈"!|.\":"?-1:i∈"()_@\$&",...)menciptakan array angka, dengan 1 jika karakternya adalah awan, -1 jika karakternya hujan, dan 0 sebaliknya.

cumsum(...')menghitung jumlah kumulatif dari baris (biasanya akan ditulis cumsum(...,2), tetapi karena kita tidak peduli tentang orientasi sejak saat ini, mentransposisi hanya biaya satu karakter), dan kemudian all(... .>-1)memeriksa angka negatif - negatif hanya akan terjadi jika karakter hujan muncul tanpa didahului oleh karakter cloud.

Julia, 139 136 karakter

s->(t=join(mapfoldl(i->split(i,""),.*,split(s,"
")),"
");while t!=(t=replace(t,r"[()_@$&](.*?)[!|.\":]",s"\g<1>"))end;∩("!|.\":",t)==[])

Fungsi ini pertama-tama mentransposisi teks sehingga baris menjadi kolom dan sebaliknya. Perhatikan bahwa baris baru hadir dalam kode dalam bentuk baris baru yang sebenarnya, untuk menyimpan satu karakter per instance.

Fungsi kemudian secara iteratif menggantikan pasangan cloud / droplet dengan spasi, dan setelah semua pasangan tersebut dihapus, ia mengembalikan true jika ada tetesan yang tersisa dan false jika tidak.

r"[()_@$&](.*?)[!|.\":]"- ini adalah regex yang akan mencocokkan pasangan cloud / droplet dengan cara yang malas, dengan grup 1 berisi segalanya antara cloud dan droplet. Kemudian s"\g<1>"suruh untuk menghapus awan dan tetesan yang cocok, tetapi simpan di antara keduanya (diperlukan karena dapat mengandung awan) - \g<1>adalah apa pun yang cocok di grup 1 regex. ∩("!|.\":",t)==[]akan menghasilkan persimpangan karakter tetesan dengan string terakhir, dan jika kosong, maka tidak ada karakter tetesan hadir, dan hujan.

Glen O
sumber
@nimi - Anda tidak benar-benar membutuhkannya. Anda dapat mengganti yang hdigunakan dengan fungsi anonim yang sebenarnya. Seperti ini: g((s->join(foldl(.*,[split(i,"")for i=split(s,"\n")]),"\n")s->join(foldl(.*,[split(i,"")for i=split(s,"\n")]),"\n"))("()()()\n......"))- menyebutnya hhanya membuatnya lebih mudah untuk dipanggil.
Glen O
@nimi - untuk "fungsi tunggal untuk memanggil", itu adalah pernyataan yang sedikit lebih masuk akal, tetapi tidak jelas apa yang menjadi dasar komunitas itu - saya akan membuat posting meta yang menanyakan hal itu.
Glen O
@nimi - itulah yang akan saya dapatkan klarifikasi, saat ini, dengan pos meta.
Glen O
Ini diperdebatkan untuk pertanyaan ini sekarang, karena saya menemukan cara yang lebih baik untuk melakukannya, dengan hanya satu fungsi.
Glen O