7
\$\begingroup\$

Your challenge is to golf a program that mimics a data transmission stream. Your program should read input from stdin and output it directly to stdout. To make the problem more interesting, the output stream is 'faulty', and must meet several requirements:

  1. There should be a 10% chance that each character is shifted +1 ascii code (ex 'a' becomes 'b', '9' becomes ':'), etc.
  2. The input and output should only cover printable ascii values ('!' through '~', decimal 33 through decimal 126, inclusive). If the random +1 occurs on a '~' (decimal 126), a '!' (decimal 33) should be output instead.
  3. If three characters are randomly shifted in a row, the program should output "ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR" (trailing newline optional) and halt execution.

To simplify the problem, here are a few other criteria:

  1. You can assume the input will always be valid; that is, it will only contain values '!' through '~'.
  2. The program should continue on until three characters are randomly shifted in a row; it's safe to assume that EOF will never occur.
  3. The randomness must differ across runs; if your random number generator needs to be seeded to get an unique result each run, then your code needs to seed it.
  4. You must write a program, not a function.
  5. You must take input from stdin and write output to stdout.
  6. You may not use any external libraries or resources.
  7. Your code must have a freely available and working intrepreter or compiler.

Standard code-golf rules apply. Winner is whoever has the shortest program posted two weeks from now (Thursday, Feb 20th, 2014).

\$\endgroup\$
3
  • \$\begingroup\$ Is it OK to assume that there will be an EOF? In particular, can I read all the input into memory before producing any output, like GolfScript normally does? \$\endgroup\$ Commented Feb 7, 2014 at 18:21
  • \$\begingroup\$ @IlmariKaronen probably not; it wouldn't be possible to guarantee enough input for your RNG to make 3 consecutive errors. \$\endgroup\$
    – TypeIA
    Commented Feb 7, 2014 at 18:28
  • 1
    \$\begingroup\$ @IlmariKaronen as per the specs, EOF will never occur. The only exit condition is three characters flipping in a row. \$\endgroup\$
    – Josh
    Commented Feb 7, 2014 at 18:56

12 Answers 12

4
\$\begingroup\$

Befunge-98, 166 159 156 155 148

This one improves on the other excellent Befunge answer with the correct probability (1/10) and is slightly more compact:

~>?#v?1+\1>+\:'~1+-4k#x07_$'!>,:3-!#v_
>#?>>>\$\0^>
^<<
A"##  "CT YOUR SYSTEM ADMINISTRATOR"<@,kM'"ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONT
\$\endgroup\$
5
  • \$\begingroup\$ Some implementation comments: x is used in two places as a "goto." Edge wrapping is (ab)used extensively, including control flowing through the space gap between ASE and CONTACT. The "3-in-a-row" counter is kept at the bottom of the stack; backslash is used to swap to and access it where needed. \$\endgroup\$
    – TypeIA
    Commented Feb 7, 2014 at 17:55
  • 1
    \$\begingroup\$ This is quality befunge right here. I really like what you did with the string at the end, to allow the entry point where you needed it \$\endgroup\$
    – Cruncher
    Commented Feb 7, 2014 at 18:40
  • \$\begingroup\$ I tried a lot of things this weekend to whittle this down and I can't, even by a single character. But I haven't given up! :) \$\endgroup\$
    – TypeIA
    Commented Feb 10, 2014 at 23:21
  • 1
    \$\begingroup\$ Restructured the RNG block to use only three ? instructions (one of which is hit by two paths, so the probability is still exactly 1/10) and made some other minor tweaks to shave off 7 more chars! \$\endgroup\$
    – TypeIA
    Commented Feb 11, 2014 at 15:43
  • \$\begingroup\$ Congrats on winning! \$\endgroup\$
    – Josh
    Commented Feb 21, 2014 at 14:05
4
\$\begingroup\$

C, 168 characters

i;main(c){for(srand(&c);i++<3;putchar(rand()%10?i=0,c:c-126?c+1:33))c=getchar();
puts("ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR");}

This solution's seeding of the PRNG takes advantage of the fact that modern OSes change the stack's location in memory on each run, as a basic measure against stack-smashing exploits.

\$\endgroup\$
3
  • \$\begingroup\$ You can get rid of the variable c completely by moving the getchar() call into putchar() and using some fancy math... \$\endgroup\$
    – Josh
    Commented Feb 7, 2014 at 17:39
  • \$\begingroup\$ I believe you still need to have c so you can test getchar()'s value against 126 in addition to passing it to putchar(). \$\endgroup\$
    – breadbox
    Commented Feb 7, 2014 at 18:13
  • \$\begingroup\$ Hence the fancy math...I believe putchar((getchar()-33+(rand()%10?i=0:1))%94+33)) should work. Using your solution as a base, it gets me down to 165 characters. \$\endgroup\$
    – Josh
    Commented Feb 7, 2014 at 18:38
2
\$\begingroup\$

Ruby, 156

e=3
putc(($_.ord-33+r=rand(10)/9)%94+33)/e=r>0?e-r :3while gets(1)rescue$><<'ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR'
\$\endgroup\$
3
  • \$\begingroup\$ Could you explain what is that :3while? \$\endgroup\$
    – Uri Agassi
    Commented Feb 7, 2014 at 7:40
  • \$\begingroup\$ @UriAgassi the :3 is actually the end of this statement: e=r>0?e-r :3 which sets the value of e (number of sequential errors remaining before we abort) based on r (1 if the last character processed was an error, 0 if not). It's just pushed up against the while to save space :> \$\endgroup\$ Commented Feb 7, 2014 at 11:32
  • 1
    \$\begingroup\$ And ruby recognizes the while without a space before it? That is so obscure and unreadable! ;) \$\endgroup\$
    – Uri Agassi
    Commented Feb 7, 2014 at 15:21
1
\$\begingroup\$

Batch - 359

Open to suggestions to make it completely compliant to the challenge rules.

I will work on making it smaller / better - I wanted to post it while it's working, before I break it.

@echo off&setLocal enableDelayedExpansion&for /L %%a in (33,1,126)do cmd/cexit %%a&set %%a=!=exitcodeAscii!
set a=%~1
:l
if defined a (
set c=!a:~0,1!&set a=!a:~1!&set b=0&set/ar=%RANDOM%*10/32768+1
if !r!==1 for /L %%b in (33,1,126)do (
if !b!==1 echo !%%b!>>f
if "!c!"=="!%%b!" set b=1
)
if !b!==1 set/pc=<f&del f
set o=%o%!c!&goto l
) 
echo %o%

There are definitely quite a few ways to golf it down.

h:\uprof>UDS.bat "test ing"
tesu inh

h:\uprof>UDS.bat "test ing"
tfsu ing

Un-golfed -

@echo off
setLocal enableDelayedExpansion
for /L %%a in (33,1,126) do (
    cmd /c exit %%a
    set %%a=!=exitcodeAscii!
)
set a=%~1
:l
if defined a (
    set c=!a:~0,1!
    set a=!a:~1!
    set b=0
    set /a r=%RANDOM%*10/32768+1
    if !r!==1 for /L %%b in (33,1,126) do (
        if !b!==1  echo !%%b!>>f
        if "!c!"=="!%%b!" set b=1
    )
    if !b!==1 set /p c=<f& del f
    set o=%o%!c!
    goto l
) 
echo %o%
\$\endgroup\$
1
\$\begingroup\$

PHP 190

that's the further i could golf it, but i think it's pretty good that it is less than 100 chars from the leading

<? while($a=fread(STDIN,1)){if(!rand(0,9)){$a=$a=='~'?'!':chr(ord($a)+1);@$i+=1;$i>2&&die("ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR");}else$i=0;echo$a;}
\$\endgroup\$
1
\$\begingroup\$

C# - 346 330 313 309 297 288 278 274

Kinda long but does the job.

using System;class m{static void Main(){int c=0;var r=new Random();while(c<3){int n=r.Next(10);var j=Console.In.Read();Console.Write((char)(n<1?j>'}'?'!':++j:j));c=n<1?c+1:0;}Console.Write("ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR");}}
\$\endgroup\$
14
  • 1
    \$\begingroup\$ c=n==0?c+1:0 is shorter than c+=(n==0?1:-c)... \$\endgroup\$
    – Timwi
    Commented Feb 7, 2014 at 17:16
  • 1
    \$\begingroup\$ (n==1?1:0) is shorter than (n==1?n--:(--n-n)) (and then of course change the later n==0 to n==1) \$\endgroup\$
    – Timwi
    Commented Feb 7, 2014 at 17:18
  • \$\begingroup\$ Thanks a lot, you've nearly rewritten the entire program! \$\endgroup\$ Commented Feb 7, 2014 at 17:28
  • \$\begingroup\$ You're amazing. \$\endgroup\$ Commented Feb 7, 2014 at 17:29
  • \$\begingroup\$ Hm, why the (false)? If anything, don’t you want (true)? \$\endgroup\$
    – Timwi
    Commented Feb 7, 2014 at 17:34
1
\$\begingroup\$

sh bash, on OSX, 211, 208, 203, 200, 196, 185

IFS=
while read -n1 a;do
((RANDOM>3276))&&echo $a&&t=0||{
tr !-}~ \"-~!<<<$a
((t++==2))&&echo ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR&&exit
}
done

Slightly better than 10% since random will generate numbers between 0 and 32767, so really it's 3,277 in 32,768 odds (10.0006%).

Thanks, @Gilles (but not sure what you mean about the while restructure. had some other ideas in the shower, too.

\$\endgroup\$
3
  • \$\begingroup\$ Since you're using bash features (so this is a bash solution, really), you can shorten [ $RANDOM -gt 3276 ] to ((RANDOM>3276)) and [ $[t++] -eq 2 ] to ((t++==2)). I think you can also save a few characters by restructuring as while read -n1 a;((RANDOM>3276))&&…. \$\endgroup\$ Commented Feb 7, 2014 at 11:42
  • \$\begingroup\$ @Gilles Thanks. What do you mean about the while read... part? \$\endgroup\$ Commented Feb 7, 2014 at 14:51
  • \$\begingroup\$ Sorry, I truncated in the wrong place. Make the loop while …;do :;done or until …;do :;done, you should be able to shave a few characters. \$\endgroup\$ Commented Feb 7, 2014 at 14:56
1
\$\begingroup\$

C, 260 257 237 225 189 174

My first golf, suggestions appreciated.

n;main(){for(srand(&n);n!=3;putchar((getchar()+(rand()%10==7?!!++n:(n=0))-33%94)+33));puts("ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR");}

7 is very random.

Compiling will give you warnings.

Thanks for help from breadbox and Josh.

\$\endgroup\$
9
  • 1
    \$\begingroup\$ Initial suggestions: Leave off the #include; C will accept (with warnings) calls to undeclared functions (within limits). Use global variables to get automatic zero-initialization. Find ways to use the ternary operator instead of if/else statements. Using for in place of while gives more opportunities for reducing the number of top-level statements and omitting the brackets around the loop body. Lots more that could be mentioned: examine other C solutions on this site. \$\endgroup\$
    – breadbox
    Commented Feb 7, 2014 at 4:54
  • \$\begingroup\$ Thanks for the suggestions - I thought gcc would complain without at least stdio, but apparently it's cool. I also had a silly variable still named 'count'. It looks like the for loop cut down a lot, too. \$\endgroup\$
    – millinon
    Commented Feb 7, 2014 at 5:17
  • \$\begingroup\$ You can declare n and c at the global scope. This would allow you to drop the int declaration as well as letting the initialization to zero be automatic. \$\endgroup\$
    – Josh
    Commented Feb 7, 2014 at 17:41
  • \$\begingroup\$ I decided to use c's uninitialized value in srand. I guess I could use &c or &n instead, which is what breadbox used. \$\endgroup\$
    – millinon
    Commented Feb 7, 2014 at 17:51
  • \$\begingroup\$ I love the trick you came up with to eliminate the need for your second variable! \$\endgroup\$
    – Josh
    Commented Feb 7, 2014 at 18:44
1
\$\begingroup\$

Vyxal s, 63 bytes

ƛ₀℅‹¬;:ĠṠ3<A[?C+₇‹33VC|`»ȯ ¬⋎ 4625: un₆¬×→ »ȯ, ƛṙ λḊ λ¢ ƛβ ↑Ẇ`⇧

Try it Online!

ƛ    ;                      # Map input to...
 ₀℅‹¬                       # 1 with chance 10%
      :ĠṠ                   # Get sums of groups of identical run lengths
         3<A[               # If all are less than 3 (no error)
             ?C+            # Add randoms to input charcodes
                ₇‹33V       # Replace 127 with 33
                     C      # Get charcodes
                      |`... # Else output the string
\$\endgroup\$
0
\$\begingroup\$

JavaScript (Node.js), 215 bytes

for(z=1,r='';z<<=9;z|=y+''==x,r+=y>'~'?'!':y)require('fs').readSync(0,x=Buffer(1),0,1),y=x.map(t=>t+(Math.random()<.1));console.log(r+'ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR')

Try it online!

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

05AB1E, 65 64 63 bytes

v9°Ω})DÅγsÏ3åi.•kUàø¸àŸ´•uŽIZ‘‰ëƒË ÿ: ÿ‰ë,‚µ€Í€ž‚«¢é‘ësÇ+ƵQ33:ç

Try it online!

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

Kotlin, 357 355 bytes

2 bytes saved after discovering this

import java.util.*import kotlin.random.*import kotlin.random.Random
var c=0
fun main(){var a =Scanner(System.`in`).next().toMutableList()
for(i in a.indices){if(Random.nextUInt()%10u<1u){c++;if(a[i]=='~')a[i]='!' else a[i]=a[i]+1}else if(c<3)c=0}
if(c>2)print("ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR")else print(a)}

Try it online!

I've noticed that adding newlines causes the same amount of bytes to accumulate compared to adding a semicolon. hence why it isnYt so one liney. this of course does not work with tio.run as it requires input. If you see any places where there could be any kind of improvement please tell.

Ungolfed version

import java.util.*import kotlin.random.*import kotlin.random.Random
var c =0
fun main()
{
    var a = Scanner(System.`in`).next().toMutableList()
    for(i in a.indices){
        if(Random.nextUInt()%10u<1u)
        {
            c++
            if(a[i]=='~') a[i]='!'
            else a[i]=a[i]+1
        }
        else if(c<3)c=0
    }
    if(c>2) print("ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR")
    else print(a)
}

Try it online!

    import java.util.*;import kotlin.random.Random;import kotlin.random.*
    var c=0
    fun main(){var a =Scanner(System.`in`).next().toMutableList()
    for(i in a.indices){if(Random.nextUInt()%10u<1u){c++;if(a[i]=='~')a[i]='!' else a[i]=a[i]+1}else if(c<3)c=0}
    if(c>2)print("ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONTACT YOUR SYSTEM ADMINISTRATOR")else print(a)}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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