Simulate a Cisco Ping

8

2

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

Veskah

Posted 2018-11-21T02:49:38.603

Reputation: 3 580

Are we allowed to print the strings with trailing spaces if the output is visually the same? – J. Sallé – 2018-11-23T13:00:58.020

Should the last line be terminated by a linefeed? – None – 2018-11-26T13:57:40.787

@Rogem It's optional. – Veskah – 2018-11-26T20:57:04.737

Answers

5

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.

user77406

Posted 2018-11-21T02:49:38.603

Reputation:

4

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

J. Sallé

Posted 2018-11-21T02:49:38.603

Reputation: 3 233

Trailing newline is fine. Commenting here because I'm on mobile – Veskah – 2018-11-24T07:17:39.427

⎕DL 2⊣⎕←... -> ⎕DL≢⎕←... – ngn – 2018-11-24T08:41:59.817

3

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

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

Try it online!

Embodiment of Ignorance

Posted 2018-11-21T02:49:38.603

Reputation: 7 014

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é – 2018-11-23T14:35:43.263

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 – 2018-11-27T07:40:00.380

This keeps crashing with IndexOutOfBoundsExceptions for me. – my pronoun is monicareinstate – 2019-11-20T15:00:09.813

@mypronounismonicareinstate Fixed. How did I not catch this months ago? – Embodiment of Ignorance – 2019-11-21T02:24:39.363

3

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
}

Luke Stevens

Posted 2018-11-21T02:49:38.603

Reputation: 979

printing is the killer there :/ – Adam – 2019-03-25T06:14:56.230

2

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

AdmBorkBork

Posted 2018-11-21T02:49:38.603

Reputation: 41 581

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 – 2018-11-21T22:22:08.767

1Can you shave off 3 bytes from using *20 instead of /5*100? – Ciaran_McCarthy – 2018-11-21T23:09:38.573

@Veskah Yes, thanks. – AdmBorkBork – 2018-11-26T13:42:55.997

@Ciaran_McCarthy Holy cow, thanks for the blindingly-obvious golf. :) – AdmBorkBork – 2018-11-26T13:43:15.640

2

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>

Shaggy

Posted 2018-11-21T02:49:38.603

Reputation: 24 623

1

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

TFeld

Posted 2018-11-21T02:49:38.603

Reputation: 19 246

201 bytes. – Erik the Outgolfer – 2018-11-21T16:09:21.617

@EriktheOutgolfer Thanks! :) – TFeld – 2018-11-22T08:03:09.037

1

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>

guest271314

Posted 2018-11-21T02:49:38.603

Reputation: 1

1

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!

Sean

Posted 2018-11-21T02:49:38.603

Reputation: 4 136

1

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!

Οurous

Posted 2018-11-21T02:49:38.603

Reputation: 7 916

1

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)

640KB

Posted 2018-11-21T02:49:38.603

Reputation: 7 149

1

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

qookie

Posted 2018-11-21T02:49:38.603

Reputation: 81

174 with 33 and 46 instead of '!' and '.', respectively. – None – 2019-03-28T22:41:12.967

1

05AB1E, 83 bytes

т’Sïà 5, ÿ-ÄÁ ICMP ®Ès, €º€Ä is 2 šÀ:’,„.!5ãΩDv.Z.Zy?}õ,'.¢xT*“íÞ„¼€ˆ ÿ‰» (ÿ/5)“.ª?

Try it online!

Grimmy

Posted 2018-11-21T02:49:38.603

Reputation: 12 521

1

Befunge-98 (PyFunge), 164 bytes

#va":sdnoces 2 si tuoemit ,sohcE PMCI etyb-001 ,5 gnidneS5"k,>0"2 peels"=k
>?1'!>,+\1+:4`!jv\'^'=1p
;>0'.^;")5/",,,@>$" si etar sseccuS"afk,,:2a**.'0+"( tnecrep"9k,

Try it online!

Unfortunately, I could only test it on TIO, where it returns everything after ten seconds, but it should work as expected.

david

Posted 2018-11-21T02:49:38.603

Reputation: 180