g | x | w | all
Bytes Lang Time Link
nan250313T113636Zdwseo
005Perl + Lua + JavaScript Rhino + Ruby + Python 3161121T063355Zuser6213

dwseo یا ممتازی مارکتینگ خدمات طراحی سایت،سئو،پشتیبانی سایت

Perl + Lua + JavaScript (Rhino) + Ruby + Python (3), 5 languages

m=[[']|^$=;eval($n=q@sub t {(chr 39)=~//&&"["=~//&&0!~//||die; 690 == length $n.$_[0][0][0] and print "Perl: A004442$/1$/"; print 1^++$.,$/ while 1;}@);t([ [q 9)',
    ']] n=[[function t(p) if #(m..n..p)-1==688 then print("Lua: A000045") a=1 b=1 while true do print(a) print(b) a=a+b b=b+a end end end]] loadstring(n)() t([['],
   '\x3044',
   'if((""+m).length == 640) print("JavaScript: A000217"); for(i=1;;i++)print(i*(i+1)/2)',
   'm.inspect.length == 700 and print("Ruby: A000027\n"); $i=0; print(++$i, "\n") while $i=$i+1',
   'exec(m[5])',
   'print("Python: A000012" if len(repr(m)) == 676 else ""); exec(m[6])',
   'while True: print(1)',
   'eval(m[eval(m[1][2])])',
   'eval(m[([22]+[7])[1] ])',
   8];eval(m[m[9]])

I used Rhino, an offline (non-browser-dependent) JavaScript implementation, because it makes local testing easier; it produces output using print instead of alert. You can change each occurrence of print to alert in the fourth line to get a program that will work in a browser.

This program uses the technique of storing most of the strings used for the various languages in data structures and evaluating them. We can determine if a character was deleted via checking the size of the resulting structure. That might sound easy, but it's surprisingly hard to ensure that for each language, every character of the program is either inside a string somewhere or else will break the syntax if deleted.

The program works in three different ways, depending on what language is in use.

Lua

The Lua interpretation of the program is one of the simplest and shows off the general techniques in use, so it's a good place to start. Because [[...]] is a string literal in Lua, the program parses like this:

m=[[...]] n=[[...]] loadstring(n)() t([[...]])

Here, m and the argument to t() are used to capture the parts of the program used by "other languages" in order to check them for modification; n contains the majority of the Lua code (it defines a function t when evaluated via loadstring). It should be fairly obvious that every byte that isn't inside a string literal will break the program if deleted; deleting one of =()[], the first use of m and n, or the final t will cause a syntax error; and deleting the argument to loadstring, or corrupting the name of the function itself, will make it impossible for the program to do anything useful as the content of n is never run. (Note that the trick of defining and then calling a function allows us to read the rest of the program "from the left", meaning that we don't need to write any Lua code physically to the right of the final ]]) in order to continue executing Lua after the entire program has been read.)

The implementation of t is fairly simple; it checks to ensure that m, n and p have the expected total length, then prints out the required information (the language's name, sequence number, and the Fibonacci sequence). One slight subtlety here is that I subtract 1 from the length and compare it to 688, rather than comparing to 689 directly; this is to avoid putting a literal 9 digit in the source code (the reason for this will become clear later).

JavaScript, Ruby, Python

All three of these languages parse the program the same way: as a definition of a nested data structure m, followed by eval(m[m[9]]). The definition of m looks like this:

m=[['...','...'],'...','...','...','...','...','...','...','...',8];

In other words, m is a nested list here, and we can index it to get at various strings within the list. The eval(m[m[9]]) check ensures that m has the expected number of elements; the program will therefore do nothing useful if one of the commas gets deleted (other than the first), even if the language can parse it. This ensures that all the strings from m[1] onwards are either intact or have one character deleted. We can observe that deleting any character outside a string literal here will break the program; without the initial m or an intact eval it can't run anything, without the = or ; or a parenthesis or square bracket it won't parse, deleting an apostrophe will cause an unterminated string (all the apostrophes in the program are used as string delimiters and none are escaped), and it won't find the right string to run without the final ms and 9 intact.

Assuming that everything is fine except for possibly the contents of the strings inside m, we then try to determine which entry to run. This uses fragments of code that are written in the common subset of the languages' syntaxes, but have different meanings in the languages in question. To distinguish between JavaScript and the other languages, we run ([22]+[7])[1]; this collapses to [22, 7][1] (i.e. 7) in Ruby and Python, but "227"[1] (i.e. "2", which JavaScript is happy to treat as 2 for the purpose of list indexing) in JavaScript. Then to distinguish between Ruby and Python, we take the third character of the string '\x3044'; Python expands \x escapes in both '' and "" strings, thus seeing this as 4, whereas Ruby does not expand escapes in strings if they're delimited using '', and thus sees the third character as 3. (We convert these strings to integers in a portable way by using eval yet again. It's not a recommended method of converting a string to an integer, but it does work in more languages than most other methods do.)

This means that a different string gets executed in each language, so we can start using language-specific syntax. All three programs basically do the same thing; they convert the entire data structure m to a string, measure its length, and compare it to an expected value. If it's wrong, they refuse to print the language name and sequence number, thus failing to comply with the spec (as required). Then they print an appropriate sequence. Ruby prints the consecutive integers, whereas JavaScript prints the triangular numbers (this is mostly because I'm more experienced with Java than I am with Ruby). Python is a bit more complex, because eval in Python only runs expressions, and you need exec for statements; additionally, Python isn't hugely fond of semicolons, and thus I needed to split the Python program over two execs to make it work. Because I'm not very experienced at Python one-liners, I chose to print the sequence of all-1s; boring, I know, but based on the tiebreak we've selected I wanted to get this submitted.

Perl

Saving the best for last. People who have any experience with Perl will know that variable names have to start with a punctuation mark (with $ being by far the most common; other names are used for special cases like lists and dictionaries). Some of the languages I'm using don't like dollars in variable names (Ruby is OK with it, but one other language besides Perl isn't so useful…), which means that I can't start the program with a variable assignment. What Perl does have is a fairly wide range of interesting quoting operators, so it would be trivial to hide the start of the program from Perl by capturing it in a string literal with q= ... = (which is one of the many, many ways to write a string in Perl). However, hiding the text from Perl is something we can't do; in order to make the quine comment-free, we need to be able to see everything!

The obvious approach is to read the string entirely from the right, but I couldn't think of a way to do that while writing the program, so I had to take a different approach. It's possible to match a regex against $_ (Perl's "variable used by default") via writing the regex as an expression by itself; something like /:(.):/ would look for a character between two colons in $_ and store it in $1. We can change the quote marks used for regexes by preceding the first with m; thus, as our program starts with m=[[']|^$=, Perl will parse this as /[[']|^$/. Matching that regex against $_ might seem fairly useless; however, Perl has a convenience feature that allows the use of the notation // to repeat the last successfully matched regex. It matches ($_ is the empty string, thus it matches the ^$ branch of the regex), meaning that we can determine if any characters got deleted from the regex by testing it on various strings to see if it matches! Some characters being deleted from the regex (such as the ]) will cause a parse failure. For the others, we match it against chr 39 (i.e. an apostrophe, written as a character code so as not to alarm Python), against "[", and against 0 (which Perl stringifies to "0", expecting two matches and a non-match:

Apart from the regex experimentation, everything works much the same way as in Lua. The program is arranged slightly differently:

m= ... =;eval($n=q@ ... @);t([ [q 9 ... 9]])

but it still comes down to basically the same thing (just with weirder quote marks; q can make basically anything into a quote mark, including in this case the digit 9, which is why we couldn't use it in the rest of the program). Likewise, deleting any of these characters will break the parse for the same reason it does in the corresponding Lua. The code that's assigned to $n (and evaluated) defines t to ensure that the regex is intact, then check to ensure that $n and its own argument are intact, then print the required output (I chose sequence A004442 this time, because I was feeling a bit quirky and creative). Note that we can safely use a 9 in 690, the expected total lengths of $n and $_[0][0][0] ("the first element of the first element of the first argument"), as it appears to the left of the q 9 open-quote in the program.

Extensions?

I think this program is close to its limit in terms of languages. You'd either need to find a new creative way to quote strings that doesn't clash with the existing constructions, or else to find another language with syntax close enough to JavaScript/Ruby/Python that the define-lists-and-eval trick works. (I tried looking into esolangs, but they tend to be worse with respect to string literals than more exoteric languages do, and the rules against reading the source make it hard to cheat with them.)