Premise:

For those in networking, you've most likely sent a ping to or from some device to make sure everything's properly connected. Cisco, a popular company in networking[citation needed], has a command for it in their IOS that looks like this:

Capture

(Image source)

Your challenge is to graphically recreate a portion of this. The portions we are skipping are the first line (Type escape sequence to abort.) entirely, along with the IP address and round-trip times.

You will start by outputting the following:

Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:

You will then simulate the echo requests going out. Each request will start by waiting 2 seconds and then generating the response. A successful echo response is represented by a !, a failed one by .. We won't actually be sending packets but to represent packet loss, your program must randomly choose between the two options with a non-zero chance for each. This line will start empty and each tick will add another character.

After the fifth echo, the percentage line will be outputted and the program should then terminate. The percentage line will be in the format of

Success rate is $p percent ($s/5)

where $p is in regex 0|20|40|60|80|100 and $s is the number of successful echos. The screen must be updated after each wait period by either redrawing the new state or appending to the existing echo line. This includes the Sending line.

Example run: (The tick count should not be displayed and is there to clarify what the output should look like at each time step)

#Tick 0
Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:

#Tick 1
Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:
.

#Tick 2
Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:
.!

#Tick 3
Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:
.!.

#Tick 4
Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:
.!.!

#Tick 5
Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:
.!.!.
Success rate is 40 percent (2/5)

Input:

No usable input provided.

Output:

Any reasonable format. An example final output looks like this:

Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:
...!!
Success rate is 40 percent (2/5)    

Rules:

  • You must either append to the echo line or redraw the screen after each tick.
  • ! and . do not have to be equally likely, just both possible.
  • Successive runs must be able to generate different results
  • Gifs or webms of your output would be cool. No bonus or anything for it though.
  • Standard Loopholes forbidden
  • This is
  • Are we allowed to print the strings with trailing spaces if the output is visually the same? – J. Sallé Nov 23 at 13:00
  • Should the last line be terminated by a linefeed? – Rogem Nov 26 at 13:57
  • @Rogem It's optional. – Veskah Nov 26 at 20:57

10 Answers 10

APL (Dyalog Unicode), 147 138 bytes

{5=≢⍵⊣⎕DL≢⎕←↑⌽'.!'[⍵]'Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:':⎕←('Success rate is',×∘20,'percent (','/5)',⍨⍕)+/⍵}¨1↓¨,\?6⍴2

Try it online!

This is a big Direct function. As with other answers, the TIO link will only output after the execution is completed. That said, @Adám has created a handy helper function so the timestamps can be visualized. That version of the code can be found here.

This answer uses ⎕IO←0, which sets the Index Origin of everything from 1 to 0.

Thanks to @ngn for the 9 bytes saved (and for ruining my explanation! Now I have to do it again (ლಠ益ಠ)ლ)

How:

The function receives 1 fixed argument, which is on the right.

As , we have ¨1↓¨,\?6⍴2. This expression randomly chooses (?) between 0 and 1 6 times (6⍴2 creates a 6 element vector of 2's). The results are concatenated (,\) to form a 6 element vector of 1 to 6 element vectors (e.g.: 1 0 1 0 1 1 0 1 1 0 0 1 1 0 1 0 1 1 0 1 0). The first element of each is dropped (1↓¨), and then each resulting vector is passed as (¨), running the function 6 times.

{5=≢⍵⊣...:...} is a conditional statement. If has 5 elements (aka if it's the last iteration), it'll execute the code after the guard (:). The assures the condition will be the last thing evaluated, so the program will always print the string before the guard.

{...⎕DL≢⎕←↑⌽'.!'[⍵]'Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:'...} creates a two-element vector formed by the indexed vector '.!'[⍵], which will output the successes and failures, and the ping string itself. That vector is then reversed (monadic ) to the correct order, then mixed (monadic ) into a matrix. That matrix is then output to stdout (⎕←), and a DeLay (⎕DL) is added. The argument to ⎕DL is the number of elements in the matrix (), namely 2, creating a 2 second delay between function calls.

{...:⎕←('Success rate is',×∘20,'percent (','/5)',⍨⍕)+/⍵} creates the last string to be output. It'll sum the elements of the argument (+/⍵) and pass the result as argument to the tacit function inside the parenthesis. That function first prepends (dyadic ,, followed by ) the stringified () argument with the string '/5)', then appends that to the string 'percent ('. Next, it'll append the resulting string to 20 times the argument (×∘20), and then append it to the rest of the output, which is sent to stdout via ⎕←.

  • Trailing newline is fine. Commenting here because I'm on mobile – Veskah Nov 24 at 7:17
  • ⎕DL 2⊣⎕←... -> ⎕DL≢⎕←... – ngn Nov 24 at 8:41

C# - 307 299 bytes

using System;class D{static void Main(){Action<string>w=Console.Write;
w("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:\n");int 
g=0,i=0;for(;i++<5;){var p=new Random.Next(2)<1?".":"!";w(p);g=p=="!"? 
++g:g;System.Threading.Thread.Sleep(2000);}w($"\nSuccess rate is {g*20} percent 
({g}/5)");}}

Try It Online!

Saved 8 bytes thanks to @Robin B

  • 2
    Welcome to PPCG! I took the liberty of generating a Try It Online! link for you. I suggest you edit your answer with the template TIO provides for posting answers in PPCG (although that's naturally not required). – J. Sallé Nov 23 at 14:35
  • You can get this down to 299 bytes by inline constructing Random instead of saving it in var r. Heres a link to my suggestestion – Robin B Nov 27 at 7:40

JavaScript + HTML, 203 + 9 = 212 bytes

<pre id=o
f=(x,y=0,g=z=>setTimeout(f,2e3,-~x,y+z),u=s=>o.innerText+=s)=>x?x<6?u(`.!`[n=new Date%2],g(n)):u(`
Success rate is ${y/20} percent (${y}/5)`):u`Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:`&g(0)

Try it

If new Date isn't random enough then add 8 bytes to use Math.random() instead (some other modifications have been made to allow it to run properly in a Snippet):

f=(x,y=0,g=z=>setTimeout(f,2e3,-~x,y+z),u=s=>o.innerText+=s)=>x?x<6?u(`.!`[n=Math.random()+.5|0],g(n)):u(`
Success rate is ${y/20} percent (${y}/5)`):u`Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:
`&g(0)
f()
<pre id=o></pre>

Python 3, 221 220 216 209 208 201 bytes

import time,random
p=print
p('Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:')
n=0
exec("time.sleep(2);i=random.choice('.!');n+=i<'#';p(end=i);"*5)
p(f'\nSuccess rate is {n*20} percent ({n}/5)')

Try it online!

Timing doesn't work in TIO, but works in console. (TIO outputs at the end of execution)

-7 bytes, thanks to Erik the Outgolfer

JavaScript, 322 268 267 265 bytes

(f=(a,t,s)=>a--?new Promise(r=>setTimeout(r,2e3,s+='!.'[~~(Math.random()<.5)],t(`Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:`))).then(_=>t(s)||f(a,t,s)):t(`Success rate is ${s=s.match(/!/g),s=s?s.length*2:''}0 percent (${s/2}/5)`))(5,_=>console.log(_),'')

Try it online!

JavaScript + HTML, 299 bytes

To meet output formatting requirement

(f=(a,t,s)=>a--?new Promise(r=>setTimeout(r,2e3,s+='!.'[~~(Math.random()<.5)])).then(_=>t(...s)&&f(a,t,s)):t(`\nSuccess rate is ${s=s.match(/!/g),s=s?s.length*2:''}0 percent (${s/2}/5)`))(5,t=(..._)=>p.innerHTML+=_.pop(),'',t(`Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:\n`))
<pre id=p></pre>

Clean, 305 bytes

import StdEnv,Math.Random
s::!Int->Int
s _=code {
ccall sleep "I:I"
}
t::!Int->Int
t _=code {
ccall time "I:I"
}
Start#l=take 5(map((bitand)1)(genRandInt(t 0)))
=("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:\n",[if(e>0)'!''.'\\e<-l|s 2==0],"\nSuccess rate is ",20*sum l," percent (",sum l,"/5)")

Try it online!

Perl 6, 154 bytes

say "Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:";say
sum(map {sleep 2;.print;?/\!/},roll
5,<. !>).&{"\nSuccess rate is {$_*20} percent ($_/5)"}

Try it online!

PowerShell, 166 162 158 bytes

'Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:'
0..4|%{sleep 2;write-host -no '.!'[($x=0,1|Random)];$d+=$x}
"
Success rate is $($d*20) percent ($d/5)"

Try it online!

Really similar to the Python answer to TFeld. Timing doesn't work on TIO (TIO only outputs at program completion), but works locally.

The first line is just a string placed on the pipeline. The middle line loops from 0 to 4, each iteration sleeping for 2 seconds, then write-host with -nonewline. We're writing out either a ! or . chosen Randomly and stored into $x. We then increment $d based on $x.

The last line is another (multiline) string placed on the pipeline, with a little bit of calculation in the middle to come up with the percentage.

-1 byte thanks to Veskah
-3 bytes thanks to Ciaran_McCarthy

  • Turning the success line into a multi-line string instead of using back-tick n (don't know how to escape it in comments) should save a byte. 161 bytes – Veskah Nov 21 at 22:22
  • 1
    Can you shave off 3 bytes from using *20 instead of /5*100? – Ciaran_McCarthy Nov 21 at 23:09
  • @Veskah Yes, thanks. – AdmBorkBork Nov 26 at 13:42
  • @Ciaran_McCarthy Holy cow, thanks for the blindingly-obvious golf. :) – AdmBorkBork Nov 26 at 13:43

C (gcc), 178 bytes

Nothing too crazy going on here, just counting backwards, and utilizing the return value of putchar(). There was a variable g, but it got golfed, so instead of ping, we have pin.

p(i,n){puts("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:");for(n=i=5;i--;putchar(33+rand()%2*13)-46?:n--)sleep(2);printf("\nSuccess rate is %i percent (%i/5)",20*n,n);}

Try it online!

Legible formatting

p(i,n){
    puts("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:");
    for(n=i=5;i--;putchar(33+rand()%2*13)-46?:n--)
        sleep(2);
    printf("\nSuccess rate is %i percent (%i/5)",20*n,n);
}

Java (JDK), 227 bytes

()->{var o=System.out;int s=0,i=0;for(o.println("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:");i++<5;Thread.sleep(2000))o.print(Math.random()>.5&&s++<9?"!":".");o.printf("\nSuccess rate is %d percent (%d/5)",s*20,s);}

Try it online!


The ping in action

The ping in action


Explained

()->{                               // Lambda taking no input
    var o=System.out;               // Assign System.out to a variable
    int s=0,i=0;                    // Initialise successes and loop ints
    for(o.println("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:");
                                    // ^Print opening line
        i++<5;                      // Loop five times
        Thread.sleep(2000))         // Sleep for 2 seconds at the end of each loop
            o.print(                // Print out..
                Math.random()>.5    // ..if random number is greater than .5 (50%)
                    &&s++<9?        // ..and incremented successes 
                        "!":".");   // ! for success and . for failure
    o.printf("\nSuccess rate is %d percent (%d/5)",s*20,s);
                                    //^Print formatted closing line
}

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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