304
\$\begingroup\$

This is an challenge in which each answer builds on the previous answer. I recommend sorting the thread by "oldest" in order to be sure about the order in which the posts are made.

Note: This has become quite a long-lasting challenge, and posting new answers is fairly difficult. As such, there's now a chat room available for this challenge, in case you want advice on a particular part of a potential answer, have ideas for languages that could be added, or the like. Feel free to drop in if you have anything to ask or say!

The task

The nth program to be submitted must run in n different languages; specifically, all the languages added in previous programs to be submitted, plus one more. The program must output 1 when run in the first language used in answers to this question, 2 when run in the second language, and so on. For example, the first answer could print 1 when run in Python 3, and the second answer could output 1 when run in Python 3 and 2 when run in JavaScript; in this case, the third answer would have to output 1 when run in Python 3, 2 when run in JavaScript, and 3 when run in some other language.

Additional rules

  • Your program must run without erroring out or crashing. Warnings (and other stderr output) are acceptable, but the program must exit normally (e.g. by running off the end of the program, or via a command such as exit that performs normal program termination).

  • The output must be only the integer, but trailing newlines are OK. Other unavoidable stdout output is also allowed. Examples: interpreter name and version in Befunge-93, space after printed string in Zephyr. Some languages provide two methods of printing – with and without trailing space; in this case method without trailing space must be used.

  • Each answer must be no more than 20% or 20 bytes (whichever is larger) longer than the previous answer. (This is to prevent the use of languages like Lenguage spamming up the thread, and to encourage at least a minor amount of golfing.)

  • Using different versions of the same language is allowed (although obviously they'll have to print different numbers, so you'll need to fit a version check into the polyglot). However, you may not use a language feature that returns the language's version number. Repeating the exact same language is, obviously, impossible (as the program would have to deterministically print one of two different numbers).

  • Tricks like excessive comment abuse, despite being banned in some polyglot competitions, are just fine here.

  • You don't have to use the previous answers as a guide to writing your own (you can rewrite the whole program if you like, as long as it complies with the spec); however, basing your answer mostly on a previous answer is allowed and probably the easiest way to make a solution.

  • You cannot submit two answers in a row. Let someone else post in between. This rule applies until victory condition is met.

  • As this challenge requires other competitors to post in the same languages you are, you can only use languages with a free implementation (much as though this were a contest).

  • In the case where a language has more than one interpreter, you can pick any interpreter for any given language so long as all programs which are meant to run successfully in that language do so in that interpreter. (In other words, if a program works in more than one interpreter, future posts can pick either of those interpreters, rather than a post "locking in" a particular choice of interpreter for a language.)

  • If some interpreter gets updated and the program no longer works in the newer version then new answers can either stick to the old version or fix the program to work in the new version.

  • This challenge now uses the new PPCG rules about language choice: you can use a language, or a language interpreter, even if it's newer than the question. However, you may not use a language/interpreter that's newer than the question if a) the language was designed for the purpose of polyglotting or b) the language was inspired by this question. (So newly designed practical programming languages are almost certainly going to be OK, as are unrelated esolangs, but things like A Pear Tree, which was inspired by this question, are banned.) Note that this doesn't change the validity of languages designed for polyglotting that are older than this question.

  • Note that the victory condition (see below) is designed so that breaking the chain (i.e. making it impossible for anyone else to answer after you via the use of a language that is hard to polyglot with further languages) will disqualify you from winning. The aim is to keep going as long as we can, and if you want to win, you'll have to respect that.

Answer format

As all the answers depend on each other, having a consistent answer format is going to be helpful. I recommend formatting your answer something like this (this is an example for the second link in the chain):

2. JavaScript, 40 bytes

(program goes here)

This program prints 1 in Python 3, and 2 in JavaScript.

(if you want to explain the program, the polyglotting techniques, etc., place them here)

Victory condition

Once there have been no new answers for 14 days, the winner will be whoever posted the second newest answer, i.e. the largest polyglot that's been proven not to have broken the chain. Extending the chain after that is still very welcome, though!

The winner is Chance, see answer 194 (TemplAt).

Language list

// This snippet is based on the snippet from hello world thread https://codegolf.stackexchange.com/questions/55422/hello-world
// It was tested only in Google Chrome

// https://stackoverflow.com/a/4673436
if (!String.prototype.format) {
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, (match, number) => (typeof args[number] != 'undefined' ? args[number] : match) );
  };
}

var QUESTION_ID = 102370; // from the question url
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";

function answersUrl(index) {
  return "https://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

var answers = [], answer_page = 1;

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      if (data.has_more) { $('#status').text($('#status').text() + '.'); getAnswers(); }
      else process();
    },
    // [Documentation](http://api.jquery.com/jquery.ajax/) states that `error` handler is not called for cross-domain JSONP requests, 
    // but it works here, probably because api.stackexchange.com and codegolf.stackexchange.com are on the same domain.
    error:  function (a,b,c) { 
      $('#status').text( "Failed to load answers: " + b + " " + c );
      console.log( b + " " + c );
    },
  });
}

getAnswers();

// https://stackoverflow.com/questions/6290442/html-input-type-text-onchange-event-not-working/39834997#39834997
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event
const input = document.querySelector('input');
input.addEventListener('input', onSearchInput);

function onSearchInput(e)
{
    var table = document.getElementsByTagName("table")[0];
    var str = e.srcElement.value.toLowerCase();
    var num_results = 0;

    if(str == "") // optimization for empty input
    {
        // show all rows
        for(var i = 1, row; row = table.rows[i]; i++)
        {
            row.className = "";
            num_results++;
        }
    }
    else
    {
        for(var i = 1, row; row = table.rows[i]; i++)
        {
            var hidden = row.innerText.toLowerCase().indexOf(str) == -1;
            if(!hidden) num_results++;
            row.className = hidden ? "hidden" : "";
        }
    }
    document.getElementById("results").innerText = "Results: " + num_results;
}


/* Function ParseHeader() extracts answer number, language name and size of polyglot from answer header.
   Argument: `header` - answer header string without markup, eg. "1. Python 3 (8 bytes)" or "59. Tcl, 1324 bytes".
   Retval:  object, eg. {num: 1, language: "Python 3", size: 8} or 
            null if header has wrong format
  
   There are two formats of header, new one with comma and old one with parens.
   Parsing new format only with regexp is hard because:
   - language name may contain commas,                                 eg. "51. Assembly (x64, Linux, AS), 1086 bytes"
   - there may be several sizes, of which the last one should be used, eg. "210. Haskell without MonomorphismRestriction, 10035 9977 bytes"

   There are only several answers with old format header: 1-5, 7, 12-17, 21. All of them have single size and don't have parens in language name,
   so they can be parsed with simple regexp.
   
   Algorithm: Find commas. If there are no commas parse it as old format. Otherwise parse it as new format.
   New format parsing: Let everything after last comma be `sizes`. Check if `sizes` ends with the word "bytes". If not, set size to 0.
   Take the word before "bytes" and convert it to number. Parse the rest of the header (before last comma) with regexp.
*/
function ParseHeader(header)
{
  var a = header.split(',');
  if(a.length > 1) // current format: Number "." Language "," Size+ "bytes"
  {
    // filter(s=>s) removes empty strings from array (handle multiple consecutive spaces)
    var sizes = a[a.length-1].split(" ").filter(s=>s); // " 123 100  bytes " -> ["123", "100", "bytes"]
    var size;
    if(sizes.length < 2 || sizes[sizes.length-1] != "bytes") size = 0;
    else size = +sizes[sizes.length-2];

    a.splice(a.length-1,1); // remove last element
    var match = a.join(',').match(/(\d*)\.(.*)/);
    if (!match) return null;
    return{
            num: +match[1],
            language: match[2].trim(),
            size: size,
          };
  }
  else // old format: Number "." Language "(" Size "bytes" ")"
  {
    var format = /(\d*)\.([^(]*)\((\d*)\s*bytes\)/;
    var match = header.match(format);
    if (!match) return null;
    return{
            num: +match[1],
            language: match[2].trim(),
            size: +match[3]
          };
  }
}

// 1533246057 (number of seconds since UTC 00:00 1 Jan 1970) -> "Aug 2 '18"
// other useful Date functions: toUTCString, getUTCDate, getUTCMonth, getUTCFullYear
function FormatDate(n)
{
  var date = new Date(n*1000); // takes milliseconds
  var md = date.toLocaleDateString("en-US", {timeZone:"UTC", day:"numeric", month:"short"});
  var y  = date.toLocaleDateString("en-US", {timeZone:"UTC", year:"2-digit"});
  return md + " '" + y;
}


var processed = []; // processed answers, it's called `valid` in original snippet

function ProcessAnswer(a)
{
  var body = a.body, header;

  //
  // Extract header from answer body.
  // Try find <h1> header (markdown #). If not found try find <h2> (markdown ##).
  // Extracted header contains only text, all markup is stripped.
  // For 99 language markup is later readded to language name because markup is essential for it.
  //
  var el = document.createElement('html'); // dummy element used for finding header
  el.innerHTML = body;
  var headers = el.getElementsByTagName('h1');
  if(headers.length != 0) header = headers[0].innerText;
  else {
    headers = el.getElementsByTagName('h2');
    if(headers.length != 0) header = headers[0].innerText;
    else { console.log(body); return; } // error: <h1> and <h2> not found
  }

  var info = ParseHeader(header)
  if(!info) { console.log(body); return; } // error: unrecognised header format

  if(info.num == 99 && info.language == "99") info.language = "<i>99</i>";

  processed.push({
    num:         info.num,
    language:    info.language,
    size:        info.size,
    answer_link:   a.share_link,
    user:          a.owner.display_name,
    user_link:     a.owner.link,         // `undefined` if user was deleted
    creation_date: a.creation_date,      // unix epoch (number of seconds since UTC 00:00 1 Jan 1970)
  });
}

function process()
{
  $('#status').remove();

  answers.forEach(ProcessAnswer); // answers -> processed
  
  processed.sort( (a,b)=>(a.num-b.num) ); // sort by answer number, ascending

  processed.forEach(function (a) {
    
    var date = FormatDate(a.creation_date);

    var user = a.user_link ? ('<a href="'+a.user_link+'">'+a.user+'</a>') : a.user; // redundant code, currently the only deleted user is ais523
    if(user == "user62131") user = '<a href="https://chat.stackexchange.com/users/246227/ais523">ais523</a>';

    var style = (a.num == 194) ? "background: #ccf" : ""; // 194 is winner answer

    var row = "<tr style='{0}'><td>{1}</td> <td><a href='{2}'>{3}</a></td> <td>{4}</td> <td>{5}</td> <td>{6}</td></tr>"
              .format(style, a.num, a.answer_link, a.language, a.size, user, date);

    $('#answers').append( row );
  });
}
a {text-decoration:none}
a:visited {color:#00e}

table, td, th { border: 1px solid black; }
td, th { padding-left: 5px; padding-right: 5px; white-space: nowrap; }
tr:hover { background-color: #ff9; }
td:first-child  { text-align:center; } /* # */
td:nth-child(4) { font-style:italic; } /* author */
td:nth-child(5) { text-align:right;  } /* date */

p { margin: 8px 0px }
.hidden { display: none } /* search hides rows */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
  <span>Search: </span><input autofocus> &nbsp;<span id="results"></span>
</p>
<table class="answer-list">
  <thead>
    <tr><th>#</th> <th>Language</th> <th>Size (bytes)</th> <th>Author</th> <th>Date</th></tr>
  </thead>
  <tbody id="answers">
  
  </tbody>
</table>
<div id="status">Loading answers...</div>

\$\endgroup\$
28
  • 4
    \$\begingroup\$ For people who can see deleted posts: the Sandbox post was here. \$\endgroup\$
    – user62131
    Commented Dec 6, 2016 at 19:00
  • 6
    \$\begingroup\$ There's no need to copy the previous program, although of course you can use it as a guide; redoing the program from scratch is likely to take longer! There's no need to permalink to answers; sorting by oldest will show all the answers in order already. \$\endgroup\$
    – user62131
    Commented Dec 6, 2016 at 19:44
  • 4
    \$\begingroup\$ @ais523 I think what was meant was that should new answers contain try it links with the new code? \$\endgroup\$
    – Blue
    Commented Dec 6, 2016 at 19:45
  • 7
    \$\begingroup\$ I think we need a script that takes a hex dump of the code and automatically runs it in all the languages... \$\endgroup\$
    – mbomb007
    Commented Dec 7, 2016 at 20:05
  • 5
    \$\begingroup\$ This is the Versatile integer printer posted as a different type of challenge. (Inspiration?) The final answer (currently) would score 0.0127, only beaten by Sp3000's 30 language submission... :) \$\endgroup\$ Commented Dec 17, 2016 at 12:11

451 Answers 451

1
12 13 14 15
16
0
\$\begingroup\$

449. Python 1.1.0, 18900 bytes

Try it online!

Build script. Building should be done on a 32-bit system. 64-bit build barely works, segfaults on innocent things like pow(2,2) or hasattr([],'x'). Note: when running python from Windows console via wsl the message Segmentation fault is not displayed, it is only visible in Linux console.

Python 1.1.0 doesn't have __builtins__, so it is separated from later versions with len(dir()). In Python 1.1.0 dir() == ['__name__'], in Python 1.2.0 dir() == ['__builtins__', '__doc__', '__name__'].

fish complains about command substitutions, which can be fixed by adding a space: dir (). However, this produces syntax error in Ruby 1.9.3 (only). To fix that, I use eval: len(eval ("dir()"))<3 (space after eval is again for fish).

Note: Python 1.0.1 doesn't support multiline strings, cannot be added.

\$\endgroup\$
1
12 13 14 15
16

Your Answer

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