Implement ROT-47... in ROT-47

23

4

Challenge: Implement ROT-47 in code that works as both itself and as the ROT-47 version of itself.

Scoring:

Your score is calculated as a percentage of used, ROT-47 eligible bytes in total of both versions of the program divided by total bytes (all characters) of both versions.

A used, ROT-47 eligible byte is any character that would be converted by the ROT-47 cipher that is not part of a comment or ignored by the compiler/interpreter. For example, any character in a brainfuck program that is not +-<>[],. is not considered a used byte, and any character in a C program including and after // or inside /* */ is not considered a used byte. All special symbols in APL are not considered used, as are all characters in a Whitespace program (sorry).

Ties will be broken by the program with the most upvotes. If there is still a tie, then the shortest program wins.

Example scoring:

C: 62/64 = 96.875%

Notice there is a space in this program. Obviously also, this program is not a valid entry because it doesn't even compile, but I wanted to show how scoring works.

main(){printf("Hello World!");}

durron597

Posted 2014-03-03T20:46:47.133

Reputation: 4 692

4And what language does >2:?WXLAC:?E7WQw6==@ (@C=5PQXjN compile in? – None – 2014-03-03T20:51:23.727

@hosch250 lol, that was just a dumb example – durron597 – 2014-03-03T20:52:35.123

1By "ROT-47 eligible" do you mean "in the ASCII range 33 to 126"? I.e. if my C program has spaces or newlines or tabs, do those count as ROT-47 eligible or not? What about the fact that some spaces are essential in order for a program to function in many languages - do those not count as used because they are not R47-eligible, even though the program would break without them? – Jonathan Van Matre – 2014-03-03T21:06:04.550

@JonathanVanMatre The spaces or newlines or tabs don't count because I feel the scoring would be too complicated otherwise; and I don't want Whitespace to be able to score 100%, because that would defeat the purpose. – durron597 – 2014-03-03T21:53:19.217

The score seems to be Turing-undecidable in the general case when using an interpreter, and dependent on undocumented properties of compilers when using a compiler. – Peter Taylor – 2014-03-03T22:40:29.007

2

To everyone who is objecting to my crazy scoring rules, please comment/answer here: http://meta.codegolf.stackexchange.com/questions/1167/change-scoring-type-after-the-fact

– durron597 – 2014-03-04T00:40:03.360

Answers

28

Ruby, 100% (74 characters)

Input on STDIN, output on STDOUT.

Vj=s=gets;puts(s.tr'!-~','P-~!-O');Vj;'lDl86EDjAFEDWD]ECVP\OV[V!\OP\~VXj;'

The second line is the first line ROT-47'd. Therefore, when ROT-47ing the whole program, it becomes:

';lDl86EDjAFEDWD]ECVP\OV[V!\OP\~VXj';jV=s=gets;puts(s.tr'!-~','P-~!-O');jV

My strategy here is based upon the fact that:

  • V is ' when ROT-47'd

  • j is ; when ROT-47'd

  • Therefore, Vj=...Vj; turns into ';l...';, which is essentially a no-op

    • Now you can create any arbitrary code that does anything normally and no-ops when ROT-47'd. This is because Vj=...Vj; can support running any code as you could do Vj=0;{INSERT ANY CODE};Vj;, and that will become '...'; when ROT-47'd. You just have to be careful not to use V in that code, since that will break it.
  • Similar logic can be used in reverse to produce the second half (jV instead of Vj)

Doorknob

Posted 2014-03-03T20:46:47.133

Reputation: 68 138

okay you are correct I never specified that and I won't retroactively. However, spaces still do not count as eligible characters; this should be 136/140 I think. – durron597 – 2014-03-03T22:08:26.520

1@durron597 Fixed; no more spaces. – Doorknob – 2014-03-03T22:09:41.127

Dang ruby not requiring lines to end with a semicolon :) – durron597 – 2014-03-03T22:15:37.107

16

C - 54.6%

Y;BW;XL;jNj;AW(){XL^Y;};main(int i,char**v){char*x=v[1];while(*x){if(*x>32&&*x<128)*x=(*x+15)%94+32;putchar(*x++);}}//Y^Nj>2:?W:?E :[492CYYGXL492CYIlG,`.jH9:=6WYIXL:7WYImbaUUYIk`agXYIlWYIZ`dXThcZbajAFE492CWYIZZXjNN

When ROT-47-translated, we get

*jq(j){j;};jp(WXL){/*jNj>2:?W:?E :[492CYYGXL492CYIlG,`.jH9:=6WYIXL:7WYImbaUUYIk`agXYIlWYIZ`dXThcZbajAFE492CWYIZZXjNN^^*/};main(int i,char**v){char*x=v[1];while(*x){if(*x>32&&*x<128)*x=(*x+15)%94+32;putchar(*x++);}}

Both programs compile, and ROT-47-translate the first argument:

$ ./a "hello world"
96==@ H@C=5

mniip

Posted 2014-03-03T20:46:47.133

Reputation: 9 396

I had trouble getting this to work on ideone. I'm very impressed seeing a score above 50% though! – durron597 – 2014-03-03T22:04:34.633

@durron597 It won't work on ideone as it accepts input via arguments, not stdin – mniip – 2014-03-03T22:06:54.167

1Upvote for implementing ROT-47 for arguments, not just for self-translation. That should have been in the spec. – Jonathan Van Matre – 2014-03-04T00:26:51.813

10

GolfScript, 120 / 120 bytes = 100%

{:&&32>&&+254<*{7+7+94%33+}*}%LiUUbamUUZadckYLfZfZhcTbbZNYNT

or, in ROT-47:

LiUUbamUUZadckYLfZfZhcTbbZNYNT{:&&32>&&+254<*{7+7+94%33+}*}%

No comments or string abuse. The undefined command LiUUbamUUZadckYLfZfZhcTbbZNYNT (which equals the rest of the code in ROT-47) is a no-op, but it still gets executed by the interpreter, so I believe it counts as used.

This was actually a pretty easy challenge in GolfScript. The main difficulty was in avoiding the digit 1, which is mapped by ROT-47 into the GolfScript command `. The commands ., -, ,, \, [, /, ] and ^ also had to be avoided, but that was fairly easy in this case, since the task required no array building.

Bonus:

Here's a GolfScript period-2 quine (i.e. a program that prints a second program that prints the first program again) where the two programs are the ROT-47 transforms of each other:

{`'0$~'+.{7+7+94%33+}%@!{0$@@;}*}0$~L1V_SOVZ]LfZfZhcTbbZNToPL_SoojNYN_SO

This program outputs itself ROT-47 encoded, yielding another GolfScript program:

L1V_SOVZ]LfZfZhcTbbZNToPL_SoojNYN_SO{`'0$~'+.{7+7+94%33+}%@!{0$@@;}*}0$~

which, in turn, also outputs itself ROT-47 encoded, yielding the previous program again. Thus, this program is also a rotating quine.

Ilmari Karonen

Posted 2014-03-03T20:46:47.133

Reputation: 19 513

Your denominator is wrong: "divided by total bytes (all characters) of both versions". 60/120 = 50% – Jonathan Van Matre – 2014-03-04T00:00:38.933

@JonathanVanMatre: All bytes in both versions are used (= executed by the interpreter), so that would be 120 / 120 = still 100%. – Ilmari Karonen – 2014-03-04T00:03:20.723

I'm unsure of the scoring because I don't know golfscript. I know that, for example, A in brainfuck would count in the numerator but not the denominator. Is this the same thing or different? – durron597 – 2014-03-04T00:32:19.277

@durron597: LiUUbamUUZadckYLfZfZhcTbbZNYNT is a valid identifier in GolfScript, and will be executed as a command. However, it's not one of the built-in commands, nor is it assigned a meaning by the program, so by default it simply does nothing.

– Ilmari Karonen – 2014-03-04T00:36:56.243

6

python, 96.1% (?)

According to your definition, strings count as used code?

V=input();print("".join([chr(33+(ord(V[i])+14)%94)for i in range(len(V))]));V
'l:?AFEWXjAC:?EWQQ];@:?W,49CWbbZW@C5WD,:.XZ`cXThcX7@C : :? C2?86W=6?WDXX.XXj'

qwr

Posted 2014-03-03T20:46:47.133

Reputation: 8 929

1In retrospect they shouldn't have, but it's far too late now – durron597 – 2014-03-03T22:28:21.920