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:
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 code-golf
-
\$\begingroup\$ Are we allowed to print the strings with trailing spaces if the output is visually the same? \$\endgroup\$J. Sallé– J. Sallé2018年11月23日 13:00:58 +00:00Commented Nov 23, 2018 at 13:00
-
\$\begingroup\$ Should the last line be terminated by a linefeed? \$\endgroup\$user77406– user774062018年11月26日 13:57:40 +00:00Commented Nov 26, 2018 at 13:57
-
\$\begingroup\$ @Rogem It's optional. \$\endgroup\$Veskah– Veskah2018年11月26日 20:57:04 +00:00Commented Nov 26, 2018 at 20:57
14 Answers 14
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);}
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.
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
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 ⎕←.
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);}
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
}
-
\$\begingroup\$ printing is the killer there :/ \$\endgroup\$Adam– Adam2019年03月25日 06:14:56 +00:00Commented Mar 25, 2019 at 6:14
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)");
-
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é– J. Sallé2018年11月23日 14:35:43 +00:00Commented Nov 23, 2018 at 14:35
-
\$\begingroup\$ You can get this down to 299 bytes by inline constructing
Randominstead of saving it invar r. Heres a link to my suggestestion \$\endgroup\$Amelia B– Amelia B2018年11月27日 07:40:00 +00:00Commented Nov 27, 2018 at 7:40 -
\$\begingroup\$ This keeps crashing with IndexOutOfBoundsExceptions for me. \$\endgroup\$the default.– the default.2019年11月20日 15:00:09 +00:00Commented Nov 20, 2019 at 15:00
-
\$\begingroup\$ @mypronounismonicareinstate Fixed. How did I not catch this months ago? \$\endgroup\$Gymhgy– Gymhgy2019年11月21日 02:24:39 +00:00Commented Nov 21, 2019 at 2:24
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)
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>
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)"
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
-
-
1\$\begingroup\$ Can you shave off 3 bytes from using
*20instead of/5*100? \$\endgroup\$Ciaran_McCarthy– Ciaran_McCarthy2018年11月21日 23:09:38 +00:00Commented Nov 21, 2018 at 23:09 -
\$\begingroup\$ @Veskah Yes, thanks. \$\endgroup\$AdmBorkBork– AdmBorkBork2018年11月26日 13:42:55 +00:00Commented Nov 26, 2018 at 13:42
-
\$\begingroup\$ @Ciaran_McCarthy Holy cow, thanks for the blindingly-obvious golf. :) \$\endgroup\$AdmBorkBork– AdmBorkBork2018年11月26日 13:43:15 +00:00Commented Nov 26, 2018 at 13:43
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)')
Timing doesn't work in TIO, but works in console. (TIO outputs at the end of execution)
-7 bytes, thanks to Erik the Outgolfer
-
\$\begingroup\$ 201 bytes. \$\endgroup\$Erik the Outgolfer– Erik the Outgolfer2018年11月21日 16:09:21 +00:00Commented Nov 21, 2018 at 16:09
-
\$\begingroup\$ @EriktheOutgolfer Thanks! :) \$\endgroup\$TFeld– TFeld2018年11月22日 08:03:09 +00:00Commented Nov 22, 2018 at 8:03
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(_),'')
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)")
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)"}
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)";
$ php fakeping.php
Sending 5, 100-byte ICMP Echos, timeout is 2 seconds:
.!.!.
Success rate is 40 percent (2/5)
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);}
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);
}
-
\$\begingroup\$ 174 with
33and46instead of'!'and'.', respectively. \$\endgroup\$user77406– user774062019年03月28日 22:41:12 +00:00Commented Mar 28, 2019 at 22:41
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,
Unfortunately, I could only test it on TIO, where it returns everything after ten seconds, but it should work as expected.
Explore related questions
See similar questions with these tags.