23
\$\begingroup\$

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!

Task

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

Input

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

10 Answers 10

11
\$\begingroup\$

JavaScript (ES6), 269 267 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.

\$\endgroup\$
  • 3
    \$\begingroup\$ something goes wrong at the upper left corner \$\endgroup\$ – J42161217 May 24 '17 at 1:51
  • \$\begingroup\$ -1 because it's bugged (see Jenny's comment) \$\endgroup\$ – Destructible Lemon May 24 '17 at 2:13
  • 1
    \$\begingroup\$ @DestructibleLemon Sorry about that, I got bitten by a "feature" of Firefox's clipboard... should be OK now. \$\endgroup\$ – Neil May 24 '17 at 8:05
  • \$\begingroup\$ 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. \$\endgroup\$ – Shaggy May 24 '17 at 8:55
  • 1
    \$\begingroup\$ @Shaggy Great find, thanks! \$\endgroup\$ – Neil May 24 '17 at 12:00
5
\$\begingroup\$

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..
enter image description here

\$\endgroup\$
  • 1
    \$\begingroup\$ 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 \$\endgroup\$ – Khaled.K May 24 '17 at 11:53
  • 1
    \$\begingroup\$ This does not account for the possibility of a drop falling on an @ :v \$\endgroup\$ – Jenkar May 24 '17 at 13:10
  • \$\begingroup\$ @Jenkar that is the second time you have said that on answers. Please explain what you mean. \$\endgroup\$ – caird coinheringaahing May 24 '17 at 15:16
  • \$\begingroup\$ @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? \$\endgroup\$ – Jenkar May 24 '17 at 15:59
  • \$\begingroup\$ @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. \$\endgroup\$ – caird coinheringaahing May 24 '17 at 16:02
3
\$\begingroup\$

F#, non-recursive 379 414 404 bytes

open System
let z=String.replicate
let mutable s,d=z 54" ",new Random()
while Seq.exists((<>)'@')s do 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);d.Next54|>fun i->s<-(s.[i]|>function|' '->"."|'.'->"o"|'o'->"O"|_->"@")|>(fun c->s.Remove(i,1).Insert(i,c))

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#, 406 441 438 437 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
    Threading.Thread.Sleep(1000);
    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
\$\endgroup\$
  • \$\begingroup\$ You can save 1 char by open System and removing System from the Random() and Threading.Thread.Sleep() calls ;) \$\endgroup\$ – vzwick May 24 '17 at 22:49
  • \$\begingroup\$ A few more characters shaved: tio.run/##TZDfa4NADMff/… \$\endgroup\$ – vzwick May 24 '17 at 23:07
  • \$\begingroup\$ @vzwick thanks :) found another few bytes as I was editig \$\endgroup\$ – Brunner May 25 '17 at 8:44
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

C, 313 309 305 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();
}

enter image description here

\$\endgroup\$
2
\$\begingroup\$

Ruby, 237 224 228 218 206 198 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 :

Gif

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

Bash, 576 510 429 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]}
case $c in  )a[$d]=.;;.)a[$d]=o;;o)a[$d]=0;;0)a[$d]=@;esac
done

Wow, golfed a lot. If anyone have any idea for further golfing, I'm open to suggestions

Try it yourself! It has the sleep commented because of the 60 seconds limit

Here is the gif:

enter image description here

\$\endgroup\$
1
\$\begingroup\$

Perl, 167 bytes

Note that \x1b is a literal escape character.

$_="\x1bc 24_
|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!

\$\endgroup\$
0
\$\begingroup\$

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

enter image description here

\$\endgroup\$
  • \$\begingroup\$ Never used Mathematica but could you assign to Table, 95 and 32? \$\endgroup\$ – caird coinheringaahing May 23 '17 at 23:55
  • \$\begingroup\$ As in t=Table x = 32 and y = 95? \$\endgroup\$ – caird coinheringaahing May 24 '17 at 6:16
  • \$\begingroup\$ yes of course. I golfed it a lot since yesterday \$\endgroup\$ – J42161217 May 24 '17 at 7:27
  • \$\begingroup\$ You might be able to remove 6 bytes by replacing the last Flatten with f? \$\endgroup\$ – caird coinheringaahing Jul 24 '17 at 9:05
0
\$\begingroup\$

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+=)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.