# Is it raining? I can't tell

These are raindrops:

! | . " :


These are clouds particles:

( ) _ @ $&  I want you to verify, when given a block of text, whether or not it is raining. It is raining if, for every raindrop, there is a cloud particle somewhere above it. There must be one cloud particle for every raindrop. Output a truthy or falsy value denoting your conclusions. # Valid examples (@@@@@@) ($ &  )
Q   (  )
..  .  !
: .
|"   !
.


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


@_$& errrr h_r-5 .:. . "  # Invalid examples ! ()  $
(   )
:::::
.....


This is a so the shortest program in characters wins.

• "There must be one cloud particle for every raindrop" – Blue Nov 7 '15 at 21:46
• @feersum The second invalid example is the example you are looking for. – Seadrus Nov 7 '15 at 21:50
• @feersum I see ;) – Seadrus Nov 7 '15 at 21:59
• Can we assume the rows are padded with spaces to form a rectangle? – feersum Nov 7 '15 at 22:05
• @Zereges, no: at least one – msh210 Nov 8 '15 at 10:14

# APL (30)

{∧/∊≤/+⍀¨⍵∘∊¨'!|.":' '()_@$&'}  This is a function that takes a character matrix as input, and gives a boolean output. Test:  ex1 ex2 ex3 ex4 ex5 ┌─────────┬──────┬─────┬──┬─────┐ │(@@@@@@) │()()()│@_$ &│! │$│ │ ($ &  )│......│errrr│()│(   )│
│Q   (  ) │      │h_r-5│  │:::::│
│..  .  ! │      │.:. .│  │.....│
│ : .     │      │ "   │  │     │
│  |"   ! │      │     │  │     │
│    .    │      │     │  │     │
└─────────┴──────┴─────┴──┴─────┘
{∧/∊≤/+⍀¨⍵∘∊¨'!|.":' '()_@$&'}¨ex1 ex2 ex3 ex4 ex5 1 1 1 0 0  Explanation: • ⍵∘∊¨'!|.":' '()_@$&': for both sets of characters (rain and clouds), and each character in ⍵, see if the character is a member of the set.
• +⍀¨: get a running sum for each column and each set
• ≤/: for each position in ⍵, check that the amount of raindrops does not exceed the amount of cloud particles in the running sum
• ∧/∊: return the boolean AND of all the elements in the result

# C++11, 186 184 bytes

#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;}}


Ungolfed

#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; }  Basic approach, storing positions of cloud particles in a row and if rain particle is encountered, it checks whether the cloud particle is above it and decreases the counter of cloud particles in that column. The program returns 0 if it's valid and 1 otherwise. • Can't you replace c-m?0:p[i]++ with p[i]+=c==m? Or does that no longer work in C++11? – marinus Nov 9 '15 at 11:00 • @marinus Probably yes. – Zereges Nov 9 '15 at 15:33 # Snails, 125 {t.{t($$|$$|\_|\@|$|\&)=(u.,~)d!(.,~)t.!(.,~},!{t(\!|\||\.|\"|\:)ud!(.,~}t($$|$$|\_|\@|$|\&)!(d.,~)u.,~},!{t(\!|\||\.|\"|\:  The program outputs the area of the grid (or 1 if its area is 0) if it is raining; otherwise 0. If only I had implemented regex-style character classes. Ungolfed version This contains fake instructions for clouds or raindrops instead of writing out all the gibberish. \whatever (replaced with . in the real program) means a thing that ought to be a raindrop, but can actually be anything because it doesn't matter if we match a non-raindrop to a cloud. { 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  • interesting comment system. – Seadrus Nov 8 '15 at 1:32 # Python 2, 121 bytes 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


Expects the input to be padded to be rectangular.

# JavaScript ES6, 112

Test running the snippet below in an EcmaScript 6 compliant browser implementing arrow functions, spread operator and template strings (I use 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>

## Perl 5, 80

79, plus one for -E instead of -e

@a=();while(<>){@_=split'';(0>($a[$_]+=/[()_@&$]/-/[!|.":]/)?die:1)for@_}say 1  • I can't read Perl, but I'm strong in math: 79+1 = 80 – edc65 Nov 8 '15 at 23:02 # Julia, 90 characters s->all(cumsum(map(i->i∈"!|.\":"?-1:i∈"()_@$&",mapfoldl(collect,hcat,split(s,"
")))').>-1)


Unlike the original solution (below), this uses mathematics to determine the solution. mapfoldl(collect,hcat,split(s,"\n")) (written above with \n replaced with an actual newline to save characters) converts the string into a 2d array of characters. map(i->i∈"!|.\":"?-1:i∈"()_@\$&",...) creates an array of numbers, with 1 if the character is a cloud, -1 if the character is rain, and 0 otherwise. cumsum(...') calculates the cumulative sums of the rows (would normally be written cumsum(...,2), but since we don't care about orientation from this point on, transposing only costs one character), and then all(... .>-1) checks for a negative number - negatives will only occur if a rain character appears without being preceded by a cloud character. ## Julia, 139 136 characters s->(t=join(mapfoldl(i->split(i,""),.*,split(s," "))," ");while t!=(t=replace(t,r"[()_@$&](.*?)[!|.\":]",s"\g<1>"))end;∩("!|.\":",t)==[])


This function first transposes the text so that rows become columns and vice-versa. Note that newlines are present in the code in the form of actual newlines, to save one character per instance.

The function then iteratively replaces cloud/droplet pairs with spaces, and once all such pairs are removed, it returns true if there are any droplets remaining and false otherwise.

r"[()_@\$&](.*?)[!|.\":]" - this is a regex that will match cloud/droplet pairs in a lazy manner, with group 1 containing everything between cloud and droplet. Then s"\g<1>" tells it to remove the matched cloud and droplets, but keep the stuff in between (necessary as it may contain clouds) - the \g<1> is whatever was matched in group 1 of the regex. ∩("!|.\":",t)==[] will generate the intersection of the droplet characters with the final string, and if it's empty, then none of the droplet characters are present, and it's raining.

• @nimi - you don't actually need it. You can replace the h in the use with the actual anonymous function. Like this: g((s->join(foldl(.*,[split(i,"")for i=split(s,"\n")]),"\n")s->join(foldl(.*,[split(i,"")for i=split(s,"\n")]),"\n"))("()()()\n......")) - calling it h just makes it easier to invoke. – Glen O Nov 8 '15 at 9:45
• @nimi - as for the "single function to call", that's a slightly more reasonable assertion, but it's not clear what the community standing on that is - I'm going to make a meta post asking about it. – Glen O Nov 8 '15 at 9:50
• @nimi - that's what I'm going to get clarification on, right now, with a meta post. – Glen O Nov 8 '15 at 9:59
• It's moot for this question now, as I found a better way to do it, with only one function. – Glen O Nov 9 '15 at 5:53