Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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).

share|improve this question
    
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? –  Ilmari Karonen Feb 7 at 18:21
    
@IlmariKaronen probably not; it wouldn't be possible to guarantee enough input for your RNG to make 3 consecutive errors. –  dvnrrs Feb 7 at 18:28
1  
@IlmariKaronen as per the specs, EOF will never occur. The only exit condition is three characters flipping in a row. –  Josh Feb 7 at 18:56
add comment

9 Answers

up vote 4 down vote accepted

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
share|improve this answer
    
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. –  dvnrrs Feb 7 at 17:55
1  
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 –  Cruncher Feb 7 at 18:40
    
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! :) –  dvnrrs Feb 10 at 23:21
1  
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! –  dvnrrs Feb 11 at 15:43
    
Congrats on winning! –  Josh Feb 21 at 14:05
add comment

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.

share|improve this answer
    
You can get rid of the variable c completely by moving the getchar() call into putchar() and using some fancy math... –  Josh Feb 7 at 17:39
    
I believe you still need to have c so you can test getchar()'s value against 126 in addition to passing it to putchar(). –  breadbox Feb 7 at 18:13
    
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. –  Josh Feb 7 at 18:38
add comment

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'
share|improve this answer
    
Could you explain what is that :3while? –  Uri Agassi Feb 7 at 7:40
    
@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 :> –  Chron Feb 7 at 11:32
1  
And ruby recognizes the while without a space before it? That is so obscure and unreadable! ;) –  Uri Agassi Feb 7 at 15:21
add comment

Befunge-93 (206)

It has 142 non-whitespace characters. Technically it is non-conforming, as it has probability 1/9 not 1/10 to error.

v$,_\1+:4-v
~> ^1:  <v_$$"ROTARTSINIMDA METSYS RUOY TCATNOC ESAELP ,RORRE ELBAREVOCERNU :5264 EDOC RORRE">:#,_@
 ^ < < < \
   1     "
 ^0?2^
   ^ 3  +"
> >?>?4^"-
   v 5  !"
 ^8?6> ^"^
   7    %"
   >   ^^<

Run as cat /dev/urandom | tr -dc '!-~' | ./befungee.py -c 100 ../rand.

With this input !!!!aaaaaaa~~~~~~~~~~ we get the output !"!!aabaaba~~~!~~~~!! indicating that the errors are correctly handled.

share|improve this answer
    
To get the 10% chance would be rather difficult. Each of your 9 would have to split into another 2(throw the third one back). Then 8 of the 18 have to path back to the beginning –  Cruncher Feb 7 at 18:17
    
@Cruncher that's similar to the approach I used in my Befunge submission, which has correct probability. Four ?s are used and some code paths feed back to the beginning of the RNG as "nops." –  dvnrrs Feb 7 at 18:34
add comment

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%
share|improve this answer
add comment

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;}
share|improve this answer
add comment

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");}}
share|improve this answer
1  
c=n==0?c+1:0 is shorter than c+=(n==0?1:-c)... –  Timwi Feb 7 at 17:16
1  
(n==1?1:0) is shorter than (n==1?n--:(--n-n)) (and then of course change the later n==0 to n==1) –  Timwi Feb 7 at 17:18
    
Thanks a lot, you've nearly rewritten the entire program! –  user3188175 Feb 7 at 17:28
    
You're amazing. –  user3188175 Feb 7 at 17:29
    
Hm, why the (false)? If anything, don’t you want (true)? –  Timwi Feb 7 at 17:34
show 9 more comments

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.

share|improve this answer
    
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))&&…. –  Gilles Feb 7 at 11:42
    
@Gilles Thanks. What do you mean about the while read... part? –  Charles Feb 7 at 14:51
    
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. –  Gilles Feb 7 at 14:56
add comment

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.

share|improve this answer
1  
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. –  breadbox Feb 7 at 4:54
    
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. –  millinon Feb 7 at 5:17
    
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. –  Josh Feb 7 at 17:41
    
I decided to use c's uninitialized value in srand. I guess I could use &c or &n instead, which is what breadbox used. –  millinon Feb 7 at 17:51
    
I love the trick you came up with to eliminate the need for your second variable! –  Josh Feb 7 at 18:44
show 4 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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