8
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ Are we allowed to print the strings with trailing spaces if the output is visually the same? \$\endgroup\$ – J. Sallé Nov 23 '18 at 13:00
  • \$\begingroup\$ Should the last line be terminated by a linefeed? \$\endgroup\$ – user77406 Nov 26 '18 at 13:57
  • \$\begingroup\$ @Rogem It's optional. \$\endgroup\$ – Veskah Nov 26 '18 at 20:57

12 Answers 12

4
\$\begingroup\$

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 ⎕←.

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

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
}
\$\endgroup\$
  • \$\begingroup\$ printing is the killer there :/ \$\endgroup\$ – Adam Mar 25 at 6:14
3
\$\begingroup\$

C# (Visual C# Interactive Compiler), 207 bytes

int i,p;for(Write("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:\n");i++<5;Write("!."[p+=new Random().Next(2)]))System.Threading.Thread.Sleep(2000);Write($"\nSuccess Rate is {p*20} percent ({p}/5)");

Almost half a year later, I golf down about a 100 bytes.

Try it online!

\$\endgroup\$
  • 2
    \$\begingroup\$ 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). \$\endgroup\$ – J. Sallé Nov 23 '18 at 14:35
  • \$\begingroup\$ 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 \$\endgroup\$ – Robin B Nov 27 '18 at 7:40
3
\$\begingroup\$

C (gcc), 172 bytes

So, I shaved off a whopping 6 bytes off of this thing with some quite ridiculous trickery. Compile with -DK=!sleep(2)-putchar(rand()%2?33:46)/46. Depends on the sleep() function being defined in the system standard libraries. Does not loop or recurse.

p(n){puts("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:");printf("\nSuccess rate is %i percent (%i/5)",n*20,n=K+K+K+K+K);}

Try it online!

Explanation

This solution depends on three critical implementation/runtime details. First, the sleep() must not be interrupted, via e.g. a signal. Second, the additions and subtractions being resolved in order from left-to-right. Third, the arguments to printf() must be resolved right-to-left.

With that out of the way, let's sort through this thing.

p(n){ // Unfortunately, I need a variable to store the RNG result.
    // This is straight-forward printing of a line.
    puts("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:");
    // So, resolving right-to-left, we have a) the K preprocessor macros,
    // b) the assigment of their sum to n, c) the percentage equivalent of
    // the fraction n/5 and d) a constant format string.
    // The summation of the K's is where the magic happens.
    printf("\nSuccess rate is %i percent (%i/5)",n*20,n=K+K+K+K+K);
}

The compiler argument

-DK=!sleep(2)-putchar(rand()%2?33:46)/46

So, starting from the left (i.e. like it should resolve), we have sleep(). sleep() returns the number of seconds left when it returns, so we expect the user (and other processes) to be kind and to not interrupt our sleep. We take the logical complement, and because in our case sleep() will always return 0, the result is 1. More on the significance later.

Next, we enter putchar(). putchar() prints a single 1-byte character, and returns the value of the byte. So, we get a random value inside, compute modulo-2 for a nice 50-50 split (albeit with horrible entropy), and then ternary-conditional it into our desired characters - ! (33) and . (46). Then we divide the return value of putchar() with 46.

Now, that division will return 0 for ! and 1 for . - so we take 1 (from !sleep()) and subtract the result of the division from that. Presto!

Okay, there's a slight problem. When you write things to a buffer in C (i.e. stdout), it doesn't necessarily write to the receiving end immediately. In fact, when I was running this on my distro of choice, I discovered that it would only print the pings after the program terminated. However, given that all the other solutions in C are letting that slide, and that there probably exists at least one machine out there somewhere does that and fulfills all the other prerequisites (and one could always just "fix" that in the kernel...), I'm not going to mess with my score by fflush()ing stdout.

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

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>

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

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

\$\endgroup\$
  • \$\begingroup\$ 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 \$\endgroup\$ – Veskah Nov 21 '18 at 22:22
  • 1
    \$\begingroup\$ Can you shave off 3 bytes from using *20 instead of /5*100? \$\endgroup\$ – Ciaran_McCarthy Nov 21 '18 at 23:09
  • \$\begingroup\$ @Veskah Yes, thanks. \$\endgroup\$ – AdmBorkBork Nov 26 '18 at 13:42
  • \$\begingroup\$ @Ciaran_McCarthy Holy cow, thanks for the blindingly-obvious golf. :) \$\endgroup\$ – AdmBorkBork Nov 26 '18 at 13:43
1
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ 201 bytes. \$\endgroup\$ – Erik the Outgolfer Nov 21 '18 at 16:09
  • \$\begingroup\$ @EriktheOutgolfer Thanks! :) \$\endgroup\$ – TFeld Nov 22 '18 at 8:03
1
\$\begingroup\$

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>

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

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!

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

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!

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

PHP, 161 bytes

<?="Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:
";for(;$x++<5;print$y?'!':'.')$z+=$y=rand()%2+sleep(2);echo"
Success rate is ",$z*20," percent ($z/5)";

Try it online!

$ php fakeping.php

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

C (gcc), 176 174 bytes

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

Try it online!

Saved 2 bytes thanks to Rogem

Ungolfed:

f(i,j) {
    for (puts("Sending 5, 100-byte ICMP Echos, timeout is 2 seconds"),
            j = i = 5; sleep(0), i--;
            putchar(rand() % 2 ? j--, 33 : 46));
    printf("\nSuccess rate is %d percent (%d/5)",j * 20, j);
}
\$\endgroup\$
  • \$\begingroup\$ 174 with 33 and 46 instead of '!' and '.', respectively. \$\endgroup\$ – user77406 Mar 28 at 22:41

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.