TryItOnquine Challenge

49

7

(based on this post and the ensuing discussion on chat -- also, much thanks to Dennis for TIO!)

The Challenge

Choose a language that's currently available on the TryItOnline site, for example PowerShell. Write code in that language on that page, that doesn't take any input, such that when the Run button is clicked, the output on that page is the exact same as what is in the "Plain URL" field when the Save/Store button is clicked instead.

For a fictitious example, suppose that aaa was the code for a solution to this in PowerShell. Then, the result of clicking Run with aaa as the code on https://tio.run/#powershell should output https://tio.run/##K8gvTy0qzkjNyfn/PzEx8f9/AA, which is also the "Plain URL" field when the Save/Store button is clicked.

Scoring

The resulting URL is your submission to this challenge. The winner is the shortest URL measured in bytes. For the example above, the URL https://tio.run/##K8gvTy0qzkjNyfn/PzEx8f9/AA is the submission to the challenge, at 44 bytes. The shortest URL that fulfills the rest of this challenge wins the challenge and earns brownie points (points not redeemable). Given that there is a distinct minimum possible length, if two submissions tie in length, the earlier submission wins.

URL Generation

This is the start of the URL generation algorithm in the repository. You can see how the main code area is taken, any extra elements are appended, the string is deflated and Base64 converted, and then ## prepended, etc. I won't go into full detail here; part of the challenge is to parse and understand how the URLs are generated in order to exploit any potential quirks in said algorithm.

Rules / Clarifications

  • The actual code should take no input and produce only the quine-URL as output.
    -- This means the only text fields that should be populated when clicking into the URL are the Code, Header, Footer or corresponding "Compiler Flag" fields; the Input and Arguments fields are forbidden and must remain empty/unused. Clicking the Run button should only change the Output field. For this challenge, the Debug field is ignored in all situations.
  • Usual quine rules apply to the code to the extent possible (for example, the code cannot read its own source code via .code.tio).
  • Please include a description of how the code works in your submission.
  • Submitting a "cheaty" quine by submitting a Git pull request to the TIO repository to create a "trick" URL or shortcut or the like is not allowed.
  • Similarly, submitting a pull request to update a particular language to produce a "trick" URL is not allowed.
  • Please be nice to Dennis' servers and don't abuse them or attempt exploits for the sake of this challenge.

AdmBorkBork

Posted 2017-07-19T16:33:50.280

Reputation: 41 581

15Remember, last rule is important! There's already a bunch of DDoS attacks going on. – Erik the Outgolfer – 2017-07-19T16:59:28.663

What is a "PR"? – Adám – 2017-07-19T17:09:00.183

Related. – Adám – 2017-07-19T17:15:00.370

console.log(window.location.href) - I know this doesn't work, but if there is a language that can read the current URL of TIO can you say "this only works when run on TIO after clicking the link button once" and output the current URL? – Magic Octopus Urn – 2017-07-19T17:42:31.653

@MagicOctopusUrn All user code is executed on the server side. Getting direct access to the permalink URL is not possible. – Dennis – 2017-07-19T17:48:11.877

@Dennis That is, well, if they don't implement the algorithm themselves. ;) – Erik the Outgolfer – 2017-07-19T18:07:36.240

@Dennis I figured it wasn't possible just looking at the JavaScript on GitHub for the URL generation, but I didn't read everything. It'd be logical for you to execute a client-side language on the client's side. For instance, I was thinking JS may just use JS to sniff what the user's browser executes it as. – Magic Octopus Urn – 2017-07-19T18:16:22.640

1Fictitious example: if my submission is https://tio.run/##a+a which links to a program that outputs https://tio.run/##a+a, is it valid even tough the link generated by saveState would have been https://tio.run/##a@a – TwiNight – 2017-07-20T01:04:50.713

1@TwiNight Good question. That would be an interesting situation, but would not fit into the rules here and so would not be a valid submission. – AdmBorkBork – 2017-07-20T12:29:45.107

1Were you waiting until TIOv2 to post this? – mbomb007 – 2017-07-27T21:52:29.290

@mbomb007 Not intentionally. – AdmBorkBork – 2017-07-28T12:26:06.187

The conversation you linked that we had happened in April, so I was just wondering. – mbomb007 – 2017-07-28T13:21:24.593

Answers

15

Python 2, URL length = 170 bytes

https://tio.run/##K6gsycjPM/r/v9hWqQDCjqlISwPhYlvVIuvM3IL8ohKFpMTiVDMT64KizLwS9YySkoJiK339ksx8vaLSPH1lZXVtiAK9JDOT1Lzk/JRUDY1iVdViTT0YT70qJzNJXVMz2shK1yRWE2aHEkUW4Db//38A
s="python2\xff\xffs=%r;import base64;print'https://tio.run/##'+base64.b64encode((s%%s).encode(('zlib'))[2:-4])\xff\xff";import base64;print'https://tio.run/##'+base64.b64encode((s%s).encode(('zlib'))[2:-4])

Try it online!

This relies on three coincidences:

  1. The default zlib level 6 happens to give the same results as zlib level 9 for this string, modulo the header that I strip.
  2. The compressed length is divisible by 3, so base64 does not generate any = padding characters.
  3. The base64 output does not contain any + characters.

Anders Kaseorg

Posted 2017-07-19T16:33:50.280

Reputation: 29 242

15

Bash, 174 166 165 157 bytes

https://tio.run/##S0oszvj/v6QosUBBV1dBvaAoM68kTSGjpKSg2EpfvyQzP0avqDRPX1lZRQMqp6RaHFORlgbCSgpJQO0KSgkg/QlKNelVmQU1JYmZOQq6ydqGhjVA2VQzEwXdckNjS011BdcIz5D//wE

This encodes the following Bash program.

trap -- 'printf https://tio\.run/##$(printf "%s\xff\xff" bash "`trap`"|gzip|tail -c+11|base64 -w139)' EXIT

Try it online!

Thanks to @jimmy23013 for golfing 8 bytes off my original approach, for an approach that saved another byte, and for golfing another 8 bytes off that approach!

Dennis

Posted 2017-07-19T16:33:50.280

Reputation: 196 637

2@jimmy23013 I can't count the number of times I've typed base64 | tr -d \\n into my terminal... Thanks! – Dennis – 2017-07-23T17:12:19.917

@jimmy23013 Managed to get rid of it, but it cost three bytes. Annoyingly, https://tio.run/##S0oszvj/v6QosUBBV1dBvaAoM68kTSGjpKSg2EpfvyQzP0avqDRPX1mZCyqlWhwTU+HmBiYUkoC6FZQSQNoTlGrSqzILakoSM3MUdJO1DQ1rgLKpZiYKuuWGJmY1xakpCoaF6gquEZ4h//8DAA gets rid of that + but introduces another one elsewhere.

– Dennis – 2017-07-23T18:59:28.410

@jimmy23013 Now that's a clever way of getting rid of the second line. Thanks again! – Dennis – 2017-07-24T04:05:54.087

What's the problem with + symbols? (Haven't had a go at this, just curious.) – Steve Bennett – 2017-07-24T04:39:41.557

@SteveBennett The challenge requires generating the exact URL the online interpreter generates, and TIO replaces + characters with @ for permalinks. – Dennis – 2017-07-24T04:44:54.567

Ah, makes sense. Now, why does it do that? + is allowed in URLs, right? – Steve Bennett – 2017-07-25T02:38:32.123

3@SteveBennett I think I had a good reason. I don't quite remember it though. – Dennis – 2017-07-25T02:55:03.867

What about base64 -w0? – Solomon Ucko – 2020-02-21T23:14:34.037

13

Pyth, URL length = 134 bytes

https://tio.run/##K6gsyfj/X68syy/ZS6lYmyujpKSg2EpfvyQzX6@oNE9fWZnLwae4OLrI3dA9NITLQZ9LM8vZxqSkRC@qOJqrAKiby9vZyNTUmwtiBpefl7e3ppnJ//8A

Code:

.vjNcJ"s+
https://tio.run/##
@Lss[rG1GUT
@/
)jC<4tt.Zs[
pyth
KC255K
.vjNcJ
NJKK)64

Try it online!

Uses Pyth’s zlib builtin (.Z), and an inline implementation of base64.

How it works

The outer stage:

.vjNcJ"…
      "…    take this 75-byte string
     J      assign it to J
    c       split on whitespace
  jN        join on N = '"'
.v          evaluate as Pyth code

The inner stage, obtained by replacing whitespace in the string J with double quotes:

s+"https://tio.run/##"@Lss[rG1GUT"@/")jC<4tt.Zs["pyth"KC255K".vjNcJ"NJKK)64
                                               [                             begin a list:
                                                "pyth"                         string,
                                                       C255                    character 255
                                                      K                        assign that to K,
                                                           K                   K again,
                                                            ".vjNcJ"           string,
                                                                    N          '"',
                                                                     J         J (the 75-byte string),
                                                                      K        K again,
                                                                       K       K again
                                                                        )    end list
                                              s  concatenate
                                            .Z   compress with zlib
                                           t     remove first character
                                          t      remove first character
                                        <4       remove last 4 characters
                                       C         convert from base 256
                                      j                                  64
                                                 convert to base 64 digits
                      @L                         map d ↦ the following indexed at d:
                          [                        begin a list:
                            G                        alphabet ("abcdefghijklmnopqrstuvwxyz")
                           r 1                       uppercase,
                              G                      alphabet again,
                               UT                    unary range of length T = 10: [0, …, 9],
                                 "@/"                string,
                                     )             end list
                         s                         concatenate
                        s                          concatenate (we now have the base64 alphabet)
 +"https://tio.run/##"                           prepend string
s                                                concatenate

(It’s too bad the “Input” field is disallowed, or I’d have a 118 byte solution.)

Anders Kaseorg

Posted 2017-07-19T16:33:50.280

Reputation: 29 242

1Did... Did you just outgolf Dennis on a challenge built around TIO‽ – Engineer Toast – 2017-08-14T13:02:15.510

4

PowerShell, 274 bytes

https://tio.run/##TY/rCsIwDIVfZaiYFV2HooIbgu8xBrYzboXSljYq3p59VkHZjxAOJydf4uwVfehQ676fphO5e1TK8pPSWBfF1StCobW8EYYUJMyrphO@qmtw/xzMluv1t37maJoePpsm8sVGP5eV7V25JDslsozmgOJRHAcQ3t6BldARuVDkOcVBfzb5eAwRYM0FPcUQWSkCblaBvDJtPLxaLDmPnTf2bCjbsppxj06LBlPYwRxgoGdR74E9vw9mnQ2UZObF@v4N

It's all thanks to the following snippet:

&($b={[io.file]::writeallbytes('b',[char[]]'powershell'+255+255+[char[]]"&(`$b={$b})"+255+255);gzip -f b;$b=[io.file]::readallbytes('b.gz');'https://tio.run/##'+[convert]::tobase64string($b[12..($b.count-9)]).replace('=','').replace('+','@')|write-host -n})

Try it online!

Andrei Odegov

Posted 2017-07-19T16:33:50.280

Reputation: 939

Holy christ, can you explain how you got to this answer? If I even tried in Java or something it'd be pure trial and error. – Magic Octopus Urn – 2017-08-01T21:17:19.763

4

JavaScript (Node.js), 214 bytes

v=()=>console.log('https://tio.run/##'+require(`zlib`).deflateRawSync(Buffer.from(`javascript-node\xff\xffv=`+v+`;v()\xff\xff`,`ascii`)).toString("base64"));v()

Try it online!

user202729

Posted 2017-07-19T16:33:50.280

Reputation: 14 620