24
\$\begingroup\$

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!");}
\$\endgroup\$
6
  • 4
    \$\begingroup\$ And what language does >2:?WXLAC:?E7WQw6==@ (@C=5PQXjN compile in? \$\endgroup\$
    – user10766
    Mar 3, 2014 at 20:51
  • \$\begingroup\$ @hosch250 lol, that was just a dumb example \$\endgroup\$
    – durron597
    Mar 3, 2014 at 20:52
  • 1
    \$\begingroup\$ By "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? \$\endgroup\$ Mar 3, 2014 at 21:06
  • \$\begingroup\$ @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. \$\endgroup\$
    – durron597
    Mar 3, 2014 at 21:53
  • 2
    \$\begingroup\$ To everyone who is objecting to my crazy scoring rules, please comment/answer here: meta.codegolf.stackexchange.com/questions/1167/… \$\endgroup\$
    – durron597
    Mar 4, 2014 at 0:40

4 Answers 4

28
\$\begingroup\$

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)

\$\endgroup\$
3
  • \$\begingroup\$ 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. \$\endgroup\$
    – durron597
    Mar 3, 2014 at 22:08
  • 1
    \$\begingroup\$ @durron597 Fixed; no more spaces. \$\endgroup\$
    – Doorknob
    Mar 3, 2014 at 22:09
  • \$\begingroup\$ Dang ruby not requiring lines to end with a semicolon :) \$\endgroup\$
    – durron597
    Mar 3, 2014 at 22:15
16
\$\begingroup\$

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
\$\endgroup\$
3
  • \$\begingroup\$ I had trouble getting this to work on ideone. I'm very impressed seeing a score above 50% though! \$\endgroup\$
    – durron597
    Mar 3, 2014 at 22:04
  • \$\begingroup\$ @durron597 It won't work on ideone as it accepts input via arguments, not stdin \$\endgroup\$
    – mniip
    Mar 3, 2014 at 22:06
  • 1
    \$\begingroup\$ Upvote for implementing ROT-47 for arguments, not just for self-translation. That should have been in the spec. \$\endgroup\$ Mar 4, 2014 at 0:26
10
\$\begingroup\$

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.

\$\endgroup\$
4
  • \$\begingroup\$ Your denominator is wrong: "divided by total bytes (all characters) of both versions". 60/120 = 50% \$\endgroup\$ Mar 4, 2014 at 0:00
  • \$\begingroup\$ @JonathanVanMatre: All bytes in both versions are used (= executed by the interpreter), so that would be 120 / 120 = still 100%. \$\endgroup\$ Mar 4, 2014 at 0:03
  • \$\begingroup\$ 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? \$\endgroup\$
    – durron597
    Mar 4, 2014 at 0:32
  • \$\begingroup\$ @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. \$\endgroup\$ Mar 4, 2014 at 0:36
6
\$\begingroup\$

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'
\$\endgroup\$
1
  • 1
    \$\begingroup\$ In retrospect they shouldn't have, but it's far too late now \$\endgroup\$
    – durron597
    Mar 3, 2014 at 22:28

Your Answer

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

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