Unzuverlässiger Datenstrom

8

Ihre Herausforderung besteht darin, ein Programm zu entwickeln, das einen Datenübertragungsstrom nachahmt. Ihr Programm sollte Eingaben von stdin lesen und direkt an stdout ausgeben. Um das Problem interessanter zu machen, ist der Ausgabestream "fehlerhaft" und muss mehrere Anforderungen erfüllen:

  1. Es sollte eine 10% ige Chance bestehen, dass jedes Zeichen um +1 ASCII-Code verschoben wird (ex 'a' wird zu 'b', '9' wird zu ':') usw.
  2. Die Eingabe und Ausgabe sollte nur druckbare ASCII-Werte abdecken ('!' Bis '~', Dezimal 33 bis einschließlich Dezimal 126). Wenn der Zufall +1 auf einem '~' (Dezimalzahl 126) auftritt, wird ein '!' (Dezimal 33) sollte stattdessen ausgegeben werden.
  3. Wenn drei Zeichen zufällig hintereinander verschoben werden, sollte das Programm "FEHLERCODE 4625: NICHT WIEDERHERSTELLBARER FEHLER, BITTE KONTAKTIEREN SIE IHREN SYSTEMADMINISTRATOR" (nachfolgende Zeilenumbruch optional) ausgeben und die Ausführung anhalten.

Um das Problem zu vereinfachen, sind hier einige andere Kriterien:

  1. Sie können davon ausgehen, dass die Eingabe immer gültig ist. Das heißt, es enthält nur die Werte '!' durch '~'.
  2. Das Programm sollte fortgesetzt werden, bis drei Zeichen zufällig hintereinander verschoben wurden. Es ist davon auszugehen, dass EOF niemals auftreten wird.
  3. Die Zufälligkeit muss sich zwischen den Läufen unterscheiden. Wenn Ihr Zufallszahlengenerator gesetzt werden muss, um bei jedem Lauf ein eindeutiges Ergebnis zu erzielen, muss Ihr Code es setzen.
  4. Sie müssen ein Programm schreiben, keine Funktion.
  5. Sie müssen Eingaben von stdin nehmen und Ausgaben in stdout schreiben.
  6. Sie dürfen keine externen Bibliotheken oder Ressourcen verwenden.
  7. Ihr Code muss einen frei verfügbaren und funktionierenden Intrepreter oder Compiler haben.

Es gelten die Standardregeln für Code-Golf. Gewinner ist derjenige, der in zwei Wochen (Donnerstag, 20. Februar 2014) das kürzeste Programm veröffentlicht hat.

Josh
quelle
Ist es OK , anzunehmen , dass es wird ein EOF sein? Kann ich insbesondere alle Eingaben in den Speicher lesen, bevor ich eine Ausgabe produziere, wie es GolfScript normalerweise tut?
Ilmari Karonen
@IlmariKaronen wahrscheinlich nicht; Es wäre nicht möglich, genügend Eingaben für Ihr RNG zu garantieren, um 3 aufeinanderfolgende Fehler zu machen.
TypeIA
1
@IlmariKaronen Gemäß den Spezifikationen wird EOF niemals auftreten. Die einzige Ausgangsbedingung sind drei Zeichen, die hintereinander umgedreht werden.
Josh

Antworten:

4

Befunge-98, 166 159 156 155 148

Dieser verbessert die andere ausgezeichnete Befunge-Antwort mit der richtigen Wahrscheinlichkeit (1/10) und ist etwas kompakter:

~>?#v?1+\1>+\:'~1+-4k#x07_$'!>,:3-!#v_
>#?>>>\$\0^>
^<<
A"##  "CT YOUR SYSTEM ADMINISTRATOR"<@,kM'"ERROR CODE 4625: UNRECOVERABLE ERROR, PLEASE CONT
TypeIA
quelle
Einige Implementierungskommentare: xwird an zwei Stellen als "goto" verwendet. Kantenumhüllung wird (ab) ausgiebig verwendet, einschließlich der Steuerung, die durch den Zwischenraum zwischen ASEund fließt CONTACT. Der Zähler "3 in einer Reihe" befindet sich am unteren Rand des Stapels. Backslash wird verwendet, um bei Bedarf darauf zu tauschen und darauf zuzugreifen.
TypeIA
1
Das ist Qualität hier. Ich mag es wirklich, was Sie mit der Saite am Ende gemacht haben, um den Einstiegspunkt dort zu ermöglichen, wo Sie ihn gebraucht haben
Cruncher
Ich habe an diesem Wochenende viele Dinge versucht, um das zu reduzieren, und ich kann es nicht einmal mit einem einzigen Charakter. Aber ich habe nicht aufgegeben! :)
TypeIA
1
Der RNG-Block wurde so umstrukturiert, dass nur drei ?Anweisungen verwendet werden (von denen eine von zwei Pfaden getroffen wird, sodass die Wahrscheinlichkeit immer noch genau 1/10 beträgt). Außerdem wurden einige kleinere Änderungen vorgenommen, um 7 weitere Zeichen zu entfernen!
TypeIA
Herzlichen Glückwunsch zum Gewinn!
Josh
4

C, 168 Zeichen

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

Das Seeding des PRNG durch diese Lösung nutzt die Tatsache, dass moderne Betriebssysteme bei jedem Lauf den Speicherort des Stacks im Speicher ändern, als grundlegende Maßnahme gegen Exploits, die den Stapel zerschlagen.

Brot-Box
quelle
Sie können die Variable cvollständig loswerden, indem Sie den getchar()Aufruf in putchar()eine ausgefallene Mathematik verschieben und diese verwenden ...
Josh
Ich glaube, Sie müssen es noch haben, cdamit Sie den getchar()Wert gegen 126 testen und ihn an weitergeben können putchar().
Brotkasten
Daher die ausgefallene Mathematik ... Ich glaube, sie putchar((getchar()-33+(rand()%10?i=0:1))%94+33))sollte funktionieren. Wenn ich Ihre Lösung als Basis verwende, habe ich 165 Zeichen.
Josh
2

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'
Paul Prestidge
quelle
Können Sie erklären, was das ist :3while?
Uri Agassi
@UriAgassi das :3ist eigentlich das Ende dieser Anweisung: Hiermit wird e=r>0?e-r :3der Wert von e (Anzahl der vor dem Abbruch verbleibenden sequenziellen Fehler) basierend auf r festgelegt (1, wenn das zuletzt verarbeitete Zeichen ein Fehler war, 0, wenn nicht). Es ist nur gegen die Weile gedrückt, um Platz zu sparen:>
Paul Prestidge
1
Und Ruby erkennt das whileohne Leerzeichen davor? Das ist so dunkel und unlesbar! ;)
Uri Agassi
2

Charge - 359

Offen für Vorschläge, um die Herausforderungsregeln vollständig einzuhalten.

Ich werde daran arbeiten, es kleiner / besser zu machen - ich wollte es veröffentlichen, während es funktioniert, bevor ich es kaputt mache.

@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%

Es gibt definitiv einige Möglichkeiten, Golf zu spielen.

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

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

Nicht Golf -

@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%
unclemeat
quelle
2

Befunge-93 (206)

Es hat 142 Nicht-Leerzeichen. Technisch ist es nicht konform, da es eine Wahrscheinlichkeit von 1/9 und nicht 1/10 für einen Fehler hat.

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    %"
   >   ^^<

Ausführen als cat /dev/urandom | tr -dc '!-~' | ./befungee.py -c 100 ../rand.

Mit dieser Eingabe erhalten !!!!aaaaaaa~~~~~~~~~~wir die Ausgabe, die !"!!aabaaba~~~!~~~~!!angibt, dass die Fehler korrekt behandelt werden.

Joel Bosveld
quelle
Die 10% Chance zu bekommen wäre ziemlich schwierig. Jede Ihrer 9 müsste sich in eine andere 2 aufteilen (werfen Sie die dritte zurück). Dann müssen 8 der 18 zum Anfang zurückkehren
Cruncher
@Cruncher ähnelt dem Ansatz, den ich in meiner Befunge-Einreichung verwendet habe und der die richtige Wahrscheinlichkeit hat. Es werden vier verwendet, und einige Codepfade werden als "Nops" an den Anfang des RNG zurückgemeldet.
TypeIA
1

PHP 190

das ist der weitere Weg, den ich spielen könnte, aber ich finde es ziemlich gut, dass es weniger als 100 Zeichen von der Spitze entfernt ist

<? 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;}
Einacio
quelle
1

C # - 346 330 313 309 297 288 278 274

Ein bisschen lang, macht aber den 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");}}
user3188175
quelle
1
c=n==0?c+1:0ist kürzer als c+=(n==0?1:-c)...
Timwi
1
(n==1?1:0)ist kürzer als (n==1?n--:(--n-n))(und dann natürlich die später ändern n==0zu n==1)
Timwi
Vielen Dank, Sie haben fast das gesamte Programm umgeschrieben!
user3188175
Du bist fantastisch.
user3188175
Hm, warum das (false)? Wenn überhaupt, willst du nicht (true)?
Timwi
1

sh bash, auf 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

Etwas besser als 10%, da zufällig Zahlen zwischen 0 und 32767 generiert werden, also sind es wirklich 3.277 bei 32.768 Gewinnchancen (10.0006%).

Danke, @ Gilles (aber nicht sicher, was du mit der Umstrukturierung meinst. Hatte auch einige andere Ideen in der Dusche.

Nicht dass Charles
quelle
Da Sie Bash-Funktionen verwenden (dies ist also wirklich eine Bash-Lösung), können Sie [ $RANDOM -gt 3276 ]auf ((RANDOM>3276))und [ $[t++] -eq 2 ]bis verkürzen ((t++==2)). Ich denke, Sie können auch ein paar Zeichen speichern, indem Sie als umstrukturieren while read -n1 a;((RANDOM>3276))&&….
Gilles 'SO - hör auf böse zu sein'
@ Gilles Danke. Was meinst du mit dem while read...Teil?
Nicht dass Charles
Entschuldigung, ich habe an der falschen Stelle abgeschnitten. Machen Sie die Schleife while …;do :;doneoder until …;do :;done, Sie sollten in der Lage sein, einige Zeichen zu rasieren.
Gilles 'SO - hör auf böse zu sein'
1

C 260 257 237 225 189 174

Mein erster Golf, Vorschläge geschätzt.

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 ist sehr zufällig.

Beim Kompilieren erhalten Sie Warnungen.

Vielen Dank für die Hilfe von Breadbox und Josh.

Millinon
quelle
1
Erste Vorschläge: Lassen Sie die #include; C akzeptiert (mit Warnungen) Aufrufe von nicht deklarierten Funktionen (innerhalb von Grenzen). Verwenden Sie globale Variablen, um eine automatische Nullinitialisierung zu erhalten. Finden Sie Möglichkeiten, den ternären Operator anstelle von if/ else-Anweisungen zu verwenden. Die Verwendung foranstelle von whilebietet mehr Möglichkeiten, um die Anzahl der Anweisungen der obersten Ebene zu verringern und die Klammern um den Schleifenkörper wegzulassen. Viel mehr, das erwähnt werden könnte: Untersuchen Sie andere C-Lösungen auf dieser Site.
Brotkasten
Danke für die Vorschläge - ich dachte, gcc würde sich ohne mindestens stdio beschweren, aber anscheinend ist es cool. Ich hatte auch eine dumme Variable namens 'count'. Es sieht so aus, als hätte die for-Schleife auch viel gekürzt.
Millinon
Sie können deklarieren nund cim globalen Bereich. Auf diese Weise können Sie die intDeklaration löschen und die Initialisierung auf Null automatisch durchführen.
Josh
Ich habe mich entschieden, cden nicht initialisierten Wert in zu verwenden srand. Ich denke, ich könnte &coder &nstattdessen verwenden, was Breadbox verwendet.
Millinon
Ich liebe den Trick, den Sie sich ausgedacht haben, um die Notwendigkeit Ihrer zweiten Variablen zu beseitigen!
Josh