# Raindrops are falling on my… glasses?

I live in the UK, where it rains. A lot. I also have the unfortunate necessity to need to wear glasses to see, which means that when it rains (as it is now), I can barely see out of them. This challenge is so that you can all experience the same!

Output ASCII art glasses with a drop of water added each second.

None

## Output

A pair of glasses with drops of water on them.

### Glasses

 ________________________
|          /__\          |
|         /    \         |
|        /      \        |
\_______/        \_______/


### Raindrops

A raindrop is denoted by a .. A raindrop is randomly placed on the glasses' lenses. So when a raindrop is placed, the glasses might look like this

 ________________________
|          /__\          |
|    .    /    \         |
|        /      \        |
\_______/        \_______/


If it is placed on a blank space (), an . is placed on the image. If it is placed on a square which already has a raindrop, the drop graduates.

The steps on drops are

• no drops placed:
• 1 drop placed: .
• 2 drops placed: o
• 3 drops placed: O
• 4+ drops placed: @

## Rules

• The image should look as though it stays in place. This means that you can either clear the screen or print enough newlines to "clear" the screen. You cannot return a list of steps. Sorry about this, but you should be able to work around that.
• When outputting newlines to "clear" the screen, you must have at least 3 newlines between the glasses.
• The code runs until the glasses are full of fully graduated drops i.e. until the output looks like this:
     ________________________
|@@@@@@@@@@/__\@@@@@@@@@@|
|@@@@@@@@@/    \@@@@@@@@@|
|@@@@@@@@/      \@@@@@@@@|
\_______/        \_______/

• Shortest code in bytes wins.
• "The code runs until the glasses are full of fully graduated drops" Perhaps specify an approximate sleep/wait time? Like 150 or 250 ms? – Kevin Cruijssen May 24 '17 at 8:14
• Does the code have to stop when the glasses look like the final output or can it keep running but just not affect anything? – TheLethalCoder May 24 '17 at 8:28
• @TheLethalCoder I would imagine until the glasses are full, as written in the spec :v – Jenkar May 24 '17 at 11:24
• Droplet's random fall does have to fall randomly on lenses even on part of the bits of the lens that are @, right? – Jenkar May 24 '17 at 14:17
• @TheLethalCoder it should terminate after all have graduated – caird coinheringaahing May 24 '17 at 15:12

## JavaScript (ES6), 269267 265 bytes

document.write('<pre id=o>')
a=[... _8_8_8
| 9 /__\\  9|
| 9/ 4\\ 9|
| 8/ 6\\ 8|
\\_7/ 8\\_7/.replace(/.\d/g,s=>s[0].repeat(s[1]))]
s=" .oO@@"
g=_=>o.innerHTML=a.join
f=(i=s.indexOf(a[j=Math.random()*a.length|0])+1)=>i?g(a[j]=s[i]):f()
g()
setInterval(f,1e3)

Edit: Saved 2 4 bytes thanks to @Shaggy.

• something goes wrong at the upper left corner – J42161217 May 24 '17 at 1:51
• -1 because it's bugged (see Jenny's comment) – Destructible Lemon May 24 '17 at 2:13
• @DestructibleLemon Sorry about that, I got bitten by a "feature" of Firefox's clipboard... should be OK now. – Neil May 24 '17 at 8:05
• Save a couple of bytes with innerText instead of textContent and search instead of indexOf. And a few more by just using <pre id=o as HTML, rather than document.writeing it. – Shaggy May 24 '17 at 8:55
• @Shaggy Great find, thanks! – Neil May 24 '17 at 12:00

# Java 8, 449 421 bytes

v->{String q="########",g=" ________________________\n|##"+q+"/__\\##"+q+"|\n|#"+q+"/    \\#"+q+"|\n|"+q+"/      \\"+q+"|\n\\_______/        \\_______/\n\n\n";for(int t=0,n,x;g.matches("(?s).*[#\\.oO].*");Thread.sleep(150)){for(;(x=g.charAt(n=(int)(Math.random()*g.length())))!=35&x!=46&x!=111&x!=79;);if(t++>0)g=g.substring(0,n)+(x<36?".":x<47?"o":x<80?"@":"O")+g.substring(n+1);System.out.println(g.replace('#',' '));}}


Explanation:

Try it here. (Thread.sleep is removed so you instantly see the result.)

v->(){                      // Method without empty unused parameter and no return-type
String q="########",g=" ________________________\n|##"+q+"/__\\##"+q+"|\n|#"+q+"/    \\#"+q+"|\n|"+q+"/      \\"+q+"|\n\\_______/        \\_______/\n\n\n";
//  The glasses (with inner spaces replaced by '#')
for(int t=0,n,x;          //  Index integers
g.matches("(?s).*[#\\.oO].*");
//   Loop (1) as long as the glasses still contain "#.oO"
Thread.sleep(150)){   //   And sleep 150ms after each iteration to give the animation
for(;                   //   Inner loop (2)
(x=g.charAt(n=(int)(Math.random()*g.length())))!=35&x!=46&x!=111&x!=79;
//    To find the next '#', '.', 'o' or 'O' randomly
);                      //   End of inner loop (2)
if(t++>0)               //   Flag so it prints the initial glasses without a raindrop
g=g.substring(0,n)+(x<36?".":x<47?"o":x<80?"@":"O")+g.substring(n+1);
//    Add a raindrop on this random position
System.out.println(g    //   And print the glasses
.replace('#',' ')); //   After we've replaced '#' with spaces
}                         //  End of loop (1)
}                           // End of method


Output:

NOTE: The dots are a bit weird in the gif, but that's a problem in my ScreenToGif.exe..

• You know what is dazzling me about, those weird dots (same applies to scaled-down ") really look like there is a real water drop on top of my screen – Khaled.K May 24 '17 at 11:53
• This does not account for the possibility of a drop falling on an @ :v – Jenkar May 24 '17 at 13:10
• @Jenkar that is the second time you have said that on answers. Please explain what you mean. – caird coinheringaahing May 24 '17 at 15:16
• @RandomUser Basicly, the current code in this answer looks for a spot that is not yet an @ to fall on, rather than falling on the lenses randomly, even if it is an at. The "4+" in requirements seems to indicate that this is not the case to go, but instead one should fall on the lens randomly, including an @. Is this not the correct interpretation? – Jenkar May 24 '17 at 15:59
• @Jenkar It doesn't matter how it does it, just that it does it without violating any rules or standard loopholes. I never said "It must have a uniform random distribution" in the question so this answer is fine. – caird coinheringaahing May 24 '17 at 16:02

# F#, non-recursive 379414 404 bytes

open System
let z=String.replicate
let mutable s,d=z 54" ",new Random()


Try it online!

• -7 bytes thanks to @vzwick
• by aliasing String.replicate
• by opening System instead of referencing it every time
• -3 bytes by reducing the while loop to one line

I love the premise of this challenge :)

And thanks for the earworm.

# F#, 406441438437 423 bytes

open System
let z=String.replicate
let s,d=z 54" ",new Random()
let rec(!)s=s="";printfn" %s\n|%s/__\\%s|\n|%s/    \\%s|\n|%s/%7s%s|\n\\_______/%9s_______/\n\n"(z 24"_")(s.[..9])(s.[10..19])(s.[20..28])(s.[29..37])(s.[38..45])"\\"(s.[46..53])"\\";Threading.Thread.Sleep(1000);if Seq.exists((<>)'@')s then d.Next 54|>fun i-> !((s.[i]|>function|' '->"."|'.'->"o"|'o'->"O"|_->"@")|>(fun c->s.Remove(i,1).Insert(i,c)))else()
!s


Try it online!

• -3 bytes by constraining s to string by comparing it with string
• -1 byte, function name is now "!" saving a single space when calling it
• -7 bytes thanks to @vzwick
• by aliasing String.replicate
• by opening System instead of referencing it every time
• -1 byte, no need for parenthesis when calling d.Next
• -6 bytes, function is now one line

# Explanation

open System
let z = String.replicate    // define alias
let s, d = z 54 " ", new Random() // s holds a flat representation of the glasses.. glasses
let rec(!) s =
s=""; // type s to string
printfn" %s\n|%s/__\\%s|\n|%s/    \\%s|\n|%s/%7s%s|\n\\_______/%9s_______/\n\n"
(z 24 "_")     // top of the glasses
(s.[..9])      // slice
(s.[10..19])   // and
(s.[20..28])   // dice
(s.[29..37])   // the
(s.[38..45])   // glasses
"\\"           // \ gets prepended with 6 spaces thanks to %7s
(s.[46..53])
"\\";          // same deal, just 8 spaces this time
if Seq.exists((<>)'@') s then // if not everything's totally covered
d.Next 54                 // get new random int < 54 (string has indices 0-53)
|> fun i->                // passing is shorter than a let binding, saves two spaces and a new line
!(                    // call the function again with new drop on glasses
(s.[i]              // get part of the glasses drop fell on
|>function
|' '->"."           // promote drop
|'.'->"o"
|'o'->"O"
|_->"@")
|>(fun c-> s.Remove(i,1).Insert(i,c))) // and insert this in the string
else ()
!s

• You can save 1 char by open System and removing System from the Random() and Threading.Thread.Sleep() calls ;) – vzwick May 24 '17 at 22:49
• A few more characters shaved: tio.run/##TZDfa4NADMff/… – vzwick May 24 '17 at 23:07
• @vzwick thanks :) found another few bytes as I was editig – Brunner May 25 '17 at 8:44

# Python 2, 365 328 bytes

That's a bit better...

import time,random
g=' '+'_'*24+r"""
|xxX/__\Xxx|
|xX/    \Xx|
|X/      \X|
\_______/        \_______/""".replace('X','x'*8)
while 1:
print'\n'*3+g.replace('x',' ')
s='x.oO@@'
if all(c not in g for c in s[:-2]):exit()
i,c=random.choice([(i,s[s.index(j)+1])for i,j in enumerate(g)if j in s])
g=g[:i]+c+g[i+1:]
time.sleep(1)


Try it online

The above link uses 30 lines instead of 3, but you can see it with 3 if you resize your browser window to be small enough vertically. Change time.sleep(1) to time.sleep(.1) for 10x speed.

# C, 313309305 304 bytes

Needs to be golfed down quite a bit;

c;f(r,q){for(char*m=" ________________________\n|**********/__\\**********|\n|*********/    \\*********|\n|********/      \\********|\n\\_______/        \\_______/\n";c<216;r=rand()%144,m-=135)for(system("clear");*m++;putchar(*m^42?*m:32))q=--r?*m:*m^42?*m^46?*m^111?*m^79?*m:64:79:111:46,c+=q!=*m,*m=q;}


I run it with the following test stub

main()
{
srand(time(0));
f();
}


# Ruby, 237224228218206198 197 bytes

g=" #{?_*24}
|x##/__ax##|
|x#/    ax#|
|x/      ax|
a#{u=?_*7}/xa#{u}/

".gsub ?x,?#*8;217.times{|t|puts g.tr('#a',' \\');()while t<216&&g[x=rand*106]!~/[#.oO]/;g[x]=g[x].tr '#.oO','.oO@';sleep 1}


Try it online!

Previous answer was wrong, it did not take into account a raindrop falling on a @. Apparently not a requirement. Some bytes saved.

This terminates with an error thrown, but this definitely terminates as soon as the full glasses are printed.

• Saved 13 bytes by putting the printing into a lambda, and changing the assignment to use tr (duh)
• 8 bytes loss with the 1 second requirement.
• 10 bytes gain by using the gsub trick instead of interpolation (seen & adapted from mbomb007's Python answer).
• 12 bytes gain by removing the lambda printing now that the print is written only once >.>
• 1 byte gain by making all the \\ be a, then changing back inside the tr
• 7 byte gain by putting the changing the spaces on the last line with another x (duh). In case some of you guys are wondering why this doesn't affect the main loop : the main loop doesn't consider the last line to determine its x.
• 1 byte gain by removing the at the end of the top of the glasses

Yay < 200 bytes :D

Gif :

• For future reference you can edit your previous answer to one that works instead of deleting it and adding a new one. – TheLethalCoder May 24 '17 at 14:02
• Could you add in a gif of this running? – caird coinheringaahing May 24 '17 at 15:15
• @RandomUser Done. – Jenkar May 24 '17 at 17:53

# Bash, 576510429 416 Bytes

j()(IFS=
printf "$*") for i in {53..0};{ a[$i]=
b[$i]=@;} while(($i == 0));do clear
echo  " ________________________
|j ${a[@]::10}/__\\j${a[@]:10:10}|
|j ${a[@]:20:9}/ \\j${a[@]:29:9}|
|j ${a[@]:38:8}/ \\j${a[@]:46}|
\_______/        \_______/"
[ j ${a[@]} = j${b[@]} ]&&{
i=1
}
sleep 1
d=shuf -i0-53 -n1
c=${a[$d]}
|10X/__\\10X|
|9X/4 \\9X|
|8X/6 \\8X|
\\7_/8 \\7_/
";s/\d+(.)/$1x$&/ge;do{$a[rand 54]++,sleep print s/X/($",".",o,O)[$a[$-++%54]]||"@"/ger}while grep$_<4,@a  See it online! ## Mathematica, 438 bytes f=Flatten;p=Print;z=32;q=95;l=124;t=Table;v=z~t~8;s={f@{z,q~t~24,z},f@{124,z~t~10,47,q,q,92,z~t~10,l},f@{l,z~t~9,47,z~t~4,92,z~t~9,l},f@{l,v,47,z~t~6,92,v,l},f@{92,q~t~7,47,v,92,q~t~7,47}};c=0;Monitor[While[c<54,a=s[[i=RandomInteger@{2,4},j=RandomChoice[Range[2,13-i]~Join~Range[14+i,25]]]];If[a==z,s[[i,j]]=46,If[a==46,s[[i,j]]=111,If[a==111,s[[i,j]]=48,If[a==48,s[[i,j]]=64]]]];c=Count[Flatten@s,64];Pause@1],Column@FromCharacterCode@s]  here is a 10x speed result gif • Never used Mathematica but could you assign to Table, 95 and 32? – caird coinheringaahing May 23 '17 at 23:55 • As in t=Table x = 32 and y = 95? – caird coinheringaahing May 24 '17 at 6:16 • yes of course. I golfed it a lot since yesterday – J42161217 May 24 '17 at 7:27 • You might be able to remove 6 bytes by replacing the last Flatten with f? – caird coinheringaahing Jul 24 '17 at 9:05 # PHP, 262 254 bytes for($t=" 8_8_8_
|Y9Y/__\Y9Y|
|9Y/4 \9Y|
|8Y/6 \8Y|
\\7_/8 \\7_/";$c=$t[$i++];)$s.=$c<1?$c:str_repeat($t[$i++],$c);for(;$c=$s[++$k];)$c!=Y?:$s[$m[]=$k]=" ";for(;$u<216;print str_pad($s,999,"
",sleep(1)))$u+=($c=".oO@"[$a[$p=rand(0,53)]++])&&$s[$m[$p]]=$c;


Run with -nR or try it online.

breakdown

# prep 1: generate template from packed string
for($t=" 8_8_8_\n|Y9Y/__\Y9Y|\n|9Y/4 \9Y|\n|8Y/6 \8Y|\n\\7_/8 \\7_/";$c=$t[$i++];)$s.=$c<1?$c:str_repeat($t[$i++],$c);
# prep 2: map substituted spaces and replace with real spaces
for(;$c=$s[++$k];)$c!=Y?:$s[$m[]=$k]=" "; # loop until glasses are fully wet: for(;$u<216;
# 4. print glasses prepended with 865 newlines
print str_pad($s,999,"\n", # 3. wait 1 second sleep(1)))$u+=($c=".oO@"[$a[$p=rand(0,53) # 1. pick random position ]++]) # 2. and increment &&$s[$m[$p]]=$c # if not fully wet, graduate drop ; # and increment drop count ($u+=)