Search

Affichage des articles dont le libellé est algorithmic. Afficher tous les articles
Affichage des articles dont le libellé est algorithmic. Afficher tous les articles

lundi 20 mars 2017

Multiquine: final (4)

Context
Previous post  already presented the CS code template.
Now, here is the JS one
/*BOOTSTRAP*/
(function(language){
 var quote = String.fromCharCode(34), backslash = String.fromCharCode(92), newline = backslash + String.fromCharCode(114) + backslash + String.fromCharCode(110);
 var data =
 {
/*DATA*/
  cs: "CS_CODE_PLACEHOLDER",
  js: "JS_CODE_PLACEHOLDER",
  bf: "BF_CODE_PLACEHOLDER",
/*CODE*/
 };

 if(!language) language = 'js';
 var code = data[language];
 var bootstraps =
 {
   js: 'JS_BOOTSTRAP_PLACEHOLDER',
   cs: 'CS_BOOTSTRAP_PLACEHOLDER',
   bf: 'BF_BOOTSTRAP_PLACEHOLDER',
 }
 var res = bootstraps[language]
 switch(language)
 {
  case 'js':
   for(var i in data) res += ' ' + i + ': ' + quote + data[i].replace(new RegExp('\\\\', 'g'), backslash + backslash).replace(new RegExp(quote, 'g'), backslash + quote).replace(new RegExp(newline, 'g'), backslash + 'r' + backslash + 'n') + quote + ',\r\n';
   break;
  case 'cs':
   for(var i in data) res += ' data.Add(' + quote + i + quote + ', ' + quote + data[i].replace(new RegExp('\\\\', 'g'), backslash + backslash).replace(new RegExp(quote, 'g'), backslash + quote).replace(new RegExp(newline, 'g'), backslash + 'r' + backslash + 'n') + quote + ');\r\n';
   break;
  case 'bf':
   for(var i in data)
   {
     for (var j = 0; j < i.length; j++) { if (i.charCodeAt(j) == 13) continue; res += "+".repeat(i.charCodeAt(j)); res += '>'; }
res += '>';
for (var j = 0; j < data[i].length; j++) { if (data[i].charCodeAt(j) == 13) continue; res += "+".repeat(data[i].charCodeAt(j)); res += '>'; }
res += '>';
   }
   res += '\r\n';
 }
 res += code;
 console.log(res);
})()

Not really different from the C# version... Now, here is the BF one:
/*BOOTSTRAP*/
>>>>
/*DATA*/
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>CS_CODE_PLACEHOLDER>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>JS_CODE_PLACEHOLDER>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>>BF_CODE_PLACEHOLDER>
/*CODE*/
,>+<[>+++++++++[-<---------->]+<+[[-]>-<JS_BOOTSTRAP_PLACEHOLDER<<<[[<]<]>>[<++++++++[-<++++>]<..>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]+++[-<++++++++++++++++>]<++++++++++.--------------------------.++.[-]>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]++[-<++++++++++++++++>]<++.++++++++++.[-]++++++++++.[-]>>]<<<<[[<]<]>>[>]>[>]>[>]>[.>]>[>]>[>]>>>]>[-CS_BOOTSTRAP_PLACEHOLDER<<<[[<]<]>>[<++[-<++++++++++++++++>]<............[-]>++++++[-<++++++++++++++++>]<++++.---.+++++++++++++++++++.-------------------.[-]>++[-<++++++++++++++++>]<++++++++++++++.+++++++++++++++++++.+++++++++++++++++++++++++++++++++++..[-]>++[-<++++++++++++++++>]<++++++++.------.[-]>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]++[-<++++++++++++++++>]<++.++++++++++.------------.++.[-]>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]++[-<++++++++++++++++>]<++.+++++++.++++++++++++++++++.[-]++++++++++.[-]>>]<<<<[[<]<]>>[>]>[.>]>[[>]>]>>>]<]>[-<<<[[<]<]+++[-<+++++++>]<[->++>+++<<]>+>-....<<++++++++++.[-]>>>[[[[-<<.<+>>>]<.[->+<]<[->+<]>>>]<.[->+<]<[->+<]>>>]]<<<<<[<]++++++++++.[-]>[.>]]
 

Hum. Hum. Sigh...
Ok. Let's analyze.

  • Bootstrap: leave some free space.
  • Data: write "cs", leave a cell, write CS DATA (placeholder), then write "js", leave a cell, write JS DATA (placeholder), and finally write "bf", leave a cell, write BF DATA (... ?)
  • Code: read input
      • No entry : that's BF. Write BF bootstrap (>>>>), then go the the first data cell, copy data declaration (leave a cell when needed), go to BF part of the data and print as text
      • Input = "c" : that's CS. Write CS bootstrap, then go the first data cell, write '      data.Add("', then language name, then '", "', then language code (from data), by replacing " by \", \ by \\ and line breaks by \r\n. Finally, go to CS part of the data and print as text (change line breaks to real line breaks)
      • Otherwise: that's JS (and globally same as CS...)
The final part to our quine implementation would be to create a generation tool (that read templates, and inject bootstraps / code into each template to create final codes).
That's what I did, but it's clearly out of scope for this post.

Code - CS

using System;
using System.Collections.Generic;
using System.Text;

namespace Multiquine
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
            data.Add("cs", " string language = args.Length == 0 ? \"cs\" : args[0];\r\n string code = data[language];\r\n Dictionary<string, string> bootstraps = new Dictionary<string, string>();\r\n bootstraps.Add(\"cs\", \"using System;\\r\\nusing System.Collections.Generic;\\r\\nusing System.Text;\\r\\n\\r\\nnamespace Multiquine\\r\\n{\\r\\n class Program\\r\\n {\\r\\n static void Main(string[] args)\\r\\n {\\r\\n Dictionary<string, string> data = new Dictionary<string, string>();\\r\\n\");\r\n bootstraps.Add(\"js\", \"(function(language){\\r\\n var quote = String.fromCharCode(34), backslash = String.fromCharCode(92), newline = backslash + String.fromCharCode(114) + backslash + String.fromCharCode(110);\\r\\n var data = \\r\\n {\\r\\n\");\r\n bootstraps.Add(\"bf\", \">>>>\\r\\n\");\r\n Dictionary<string, string> dataAdd = new Dictionary<string, string>();\r\n dataAdd.Add(\"cs\", \" data.Add(\\\"{0}\\\", \\\"{1}\\\");\" + Environment.NewLine);\r\n dataAdd.Add(\"js\", \" {0}: \\\"{1}\\\",\" + Environment.NewLine);\r\n string res = bootstraps[language];\r\n if (language == \"bf\")\r\n {\r\n StringBuilder sb = new StringBuilder();\r\n foreach (string key in data.Keys)\r\n {\r\n foreach (char c in key)\r\n {\r\n if (c == '\\n') continue;\r\n if (c == '\\r')\r\n {\r\n sb.Append(\"++++++++++>\");\r\n continue;\r\n }\r\n sb.Append(new string('+', (int)c) + \">\");\r\n }\r\n sb.Append(\">\");\r\n foreach (char c in data[key])\r\n {\r\n if (c == '\\n') continue;\r\n if (c == '\\r')\r\n {\r\n sb.Append(\"++++++++++>\");\r\n continue;\r\n }\r\n sb.Append(new string('+', (int)c) + \">\");\r\n }\r\n sb.Append(\">\");\r\n }\r\n res += sb.ToString() + Environment.NewLine;\r\n }\r\n else\r\n {\r\n foreach (string key in data.Keys)\r\n res += String.Format(dataAdd[language], key, data[key].Replace(\"\\\\\", \"\\\\\\\\\").Replace(\"\\\"\", \"\\\\\\\"\").Replace(Environment.NewLine, @\"\\r\\n\"));\r\n }\r\n res += code;\r\n Console.Write(res);\r\n }\r\n }\r\n}");
            data.Add("js", " };\r\n\r\n if(!language) language = 'js';\r\n var code = data[language];\r\n var bootstraps = \r\n {\r\n js: '(function(language){\\r\\n var quote = String.fromCharCode(34), backslash = String.fromCharCode(92), newline = backslash + String.fromCharCode(114) + backslash + String.fromCharCode(110);\\r\\n var data = \\r\\n {\\r\\n',\r\n cs: 'using System;\\r\\nusing System.Collections.Generic;\\r\\nusing System.Text;\\r\\n\\r\\nnamespace Multiquine\\r\\n{\\r\\n class Program\\r\\n {\\r\\n static void Main(string[] args)\\r\\n {\\r\\n Dictionary<string, string> data = new Dictionary<string, string>();\\r\\n',\r\n bf: '>>>>\\r\\n',\r\n }\r\n var res = bootstraps[language]\r\n switch(language)\r\n {\r\n case 'js':\r\n for(var i in data) res += ' ' + i + ': ' + quote + data[i].replace(new RegExp('\\\\\\\\', 'g'), backslash + backslash).replace(new RegExp(quote, 'g'), backslash + quote).replace(new RegExp(newline, 'g'), backslash + 'r' + backslash + 'n') + quote + ',\\r\\n';\r\n break;\r\n case 'cs':\r\n for(var i in data) res += ' data.Add(' + quote + i + quote + ', ' + quote + data[i].replace(new RegExp('\\\\\\\\', 'g'), backslash + backslash).replace(new RegExp(quote, 'g'), backslash + quote).replace(new RegExp(newline, 'g'), backslash + 'r' + backslash + 'n') + quote + ');\\r\\n';\r\n break;\r\n case 'bf':\r\n for(var i in data)\r\n {\r\n for (var j = 0; j < i.length; j++) { if (i.charCodeAt(j) == 13) continue; res += \"+\".repeat(i.charCodeAt(j)); res += '>'; }\r\n res += '>';\r\n for (var j = 0; j < data[i].length; j++) { if (data[i].charCodeAt(j) == 13) continue; res += \"+\".repeat(data[i].charCodeAt(j)); res += '>'; }\r\n res += '>';\r\n }\r\n res += '\\r\\n';\r\n }\r\n res += code;\r\n console.log(res);\r\n})()");
            data.Add("bf", ",>+<[>+++++++++[-<---------->]+<+[[-]>-<[-]>++[-<++++++++++++++++>]<++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.+++++++++++++++.-------.-----------.+++++++++++++++++.-----------.++++++.-.[-]>++[-<++++++++++++++++>]<++++++++.[-]>++++++[-<++++++++++++++++>]<++++++++++++.-----------.+++++++++++++.-------.++++++++++++++.--------------------.++++++.--.[-]>++[-<++++++++++++++++>]<+++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.++++++++++++++++++++++.[-]>+++++++[-<++++++++++++++++>]<++++++.---------------------.+++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>+++++++[-<++++++++++++++++>]<+.++++.------.+++++.---------------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.++++++++++++.---.--.[-]>++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++++++.-------.+++++++++++++++++.[-]>++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++++++++.-----------.+.[-]>++[-<++++++++++++++++>]<++++++++.+++++++++++.+.-----------.+++.------------.[-]>++++++[-<++++++++++++++++>]<++.-.++.++++++++.++++++++.-------.-----------.++++++++++++++++++.-----------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.++++++++++++.---.--.[-]>++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++++++.-------.+++++++++++++++++.[-]>++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++++++++.-----------.+.[-]>++[-<++++++++++++++++>]<++++++++.+++++++++++++++++.-------.---------.+++.------------.[-]>++++++[-<++++++++++++++++>]<++++++++++++++.---------.++++++++++++++++++.-----------.---.+++++.---------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<++.-.++.++++++++.++++++++.-------.-----------.++++++++++++++++++.-----------.[-]>++[-<++++++++++++++++>]<.+++++++++++.-----------.[-]>+++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.++++++++++++.---.--.[-]>++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++++++.-------.+++++++++++++++++.[-]>++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++++++++.-----------.+.[-]>++[-<++++++++++++++++>]<++++++++.+++++++++..+++.-----------.---------.+++++++++++.-----------.[-]>++++++[-<++++++++++++++++>]<++.-.++.++++++++.++++++++.-------.-----------.++++++++++++++++++.-----------.[-]>++[-<++++++++++++++++>]<.+++++++++++.-----------.[-]>+++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.++++++++++++.---.--.[-]>++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++++++.-------.+++++++++++++++++.[-]>++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++++++++.-----------.+.[-]>++[-<++++++++++++++++>]<++++++++.+++++++++..-.-------.++++++++++++++++++.[-]++++++++++.++++++++++++++++++++++.[-]>+++++++[-<++++++++++++++++>]<++++++.---------------------.+++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<++++.---.+++++++++++++++++++.-------------------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]++++++++++.++++++++++++++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.[-]<<<[[<]<]>>[<++++++++[-<++++>]<..>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]+++[-<++++++++++++++++>]<++++++++++.--------------------------.++.[-]>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]++[-<++++++++++++++++>]<++.++++++++++.[-]++++++++++.[-]>>]<<<<[[<]<]>>[>]>[>]>[>]>[.>]>[>]>[>]>>>]>[-[-]>+++++++[-<++++++++++++++++>]<+++++.--.----------.+++++.-------.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++.------.+.---------------.++++++++.[-]>+++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++.--.----------.+++++.-------.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++.------.+.---------------.++++++++.[-]>++[-<++++++++++++++++>]<++++++++++++++.+++++++++++++++++++++.++++++++++++++++++++++++++++++++++++++++++++.---..-------.--.+++++++++++++++++.-----------.++++++.-.+++++.[-]>++[-<++++++++++++++++>]<++++++++++++++.+++++++++++++++++++++++++.++++++++++++++++++++++++++++++.+++++++++.---------.+++++++++++++.---------.------.[-]>+++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++.--.----------.+++++.-------.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++.------.+.---------------.++++++++.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>+++++[-<++++++++++++++++>]<++++.+++++++++++++++++.+++++++++++++++++++.----.[-]>+++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.[-]++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++++++++++.-------------.++++++++++++.--------.++++++++++++++.---.---------------.++.++.[-]>++[-<++++++++++++++++>]<.[-]>++++[-<++++++++++++++++>]<+++++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++.---------.++++++++.-----------.++++++++.++++.------------.+++++.---------.[-]++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.++++++++++++++++++++++....[-]>++++++[-<++++++++++++++++>]<+++.+++++++++.-----------.++++++++++++++++++..[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<.++++++++++++++++++++++++++++++++++.---.--------.+++++++++++.-----------------.++++++++++++.[-]++++++++++.++++++++++++++++++++++....[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.++++++++++++++++++++++........[-]>+++++++[-<++++++++++++++++>]<+++.+.-------------------.+++++++++++++++++++.-----------.------.[-]>++[-<++++++++++++++++>]<.[-]>+++++++[-<++++++++++++++++>]<++++++.-------.------.-----.[-]>++[-<++++++++++++++++>]<.[-]>++++[-<++++++++++++++++>]<+++++++++++++.++++++++++++++++++++.++++++++.+++++.[-]>++[-<++++++++++++++++>]<++++++++.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.------------.++.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<+.+++++++++++++++++.-----------.++++++++++++.[-]>++[-<++++++++++++++++>]<+++++++++.[-]++++++++++.++++++++++++++++++++++........[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.++++++++++++++++++++++............[-]>++++[-<++++++++++++++++>]<++++.+++++++++++++++++++++++++++++++++++++.------.+++++++++++++++++.-----------.++++++.-.-------------.+++++++++++++++++.+++++++.[-]>+++[-<++++++++++++++++>]<++++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++.------------.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.-----------------------------------------.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<++++.---.+++++++++++++++++++.-------------------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<++++++++++++++.---------.++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>++++[-<++++++++++++++++>]<++++.+++++++++++++++++++++++++++++++++++++.------.+++++++++++++++++.-----------.++++++.-.-------------.+++++++++++++++++.+++++++.[-]>+++[-<++++++++++++++++>]<++++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++.------------.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.-----------------------------------------.----------------------.+.++++++++++++++++++.[-]++++++++++.[-]<<<[[<]<]>>[<++[-<++++++++++++++++>]<............[-]>++++++[-<++++++++++++++++>]<++++.---.+++++++++++++++++++.-------------------.[-]>++[-<++++++++++++++++>]<++++++++++++++.+++++++++++++++++++.+++++++++++++++++++++++++++++++++++..[-]>++[-<++++++++++++++++>]<++++++++.------.[-]>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]++[-<++++++++++++++++>]<++.++++++++++.------------.++.[-]>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]++[-<++++++++++++++++>]<++.+++++++.++++++++++++++++++.[-]++++++++++.[-]>>]<<<<[[<]<]>>[>]>[.>]>[[>]>]>>>]<]>[-<<<[[<]<]+++[-<+++++++>]<[->++>+++<<]>+>-....<<++++++++++.[-]>>>[[[[-<<.<+>>>]<.[->+<]<[->+<]>>>]<.[->+<]<[->+<]>>>]]<<<<<[<]++++++++++.[-]>[.>]]");
            string language = args.Length == 0 ? "cs" : args[0];
            string code = data[language];
            Dictionary<string, string> bootstraps = new Dictionary<string, string>();
            bootstraps.Add("cs", "using System;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\n\r\nnamespace Multiquine\r\n{\r\n class Program\r\n {\r\n static void Main(string[] args)\r\n {\r\n Dictionary<string, string> data = new Dictionary<string, string>();\r\n");
            bootstraps.Add("js", "(function(language){\r\n var quote = String.fromCharCode(34), backslash = String.fromCharCode(92), newline = backslash + String.fromCharCode(114) + backslash + String.fromCharCode(110);\r\n var data = \r\n {\r\n");
            bootstraps.Add("bf", ">>>>\r\n");
            Dictionary<string, string> dataAdd = new Dictionary<string, string>();
            dataAdd.Add("cs", " data.Add(\"{0}\", \"{1}\");" + Environment.NewLine);
            dataAdd.Add("js", " {0}: \"{1}\"," + Environment.NewLine);
            string res = bootstraps[language];
            if (language == "bf")
            {
                StringBuilder sb = new StringBuilder();
                foreach (string key in data.Keys)
                {
                    foreach (char c in key)
                    {
                        if (c == '\n') continue;
                        if (c == '\r')
                        {
                            sb.Append("++++++++++>");
                            continue;
                        }
                        sb.Append(new string('+', (int)c) + ">");
                    }
                    sb.Append(">");
                    foreach (char c in data[key])
                    {
                        if (c == '\n') continue;
                        if (c == '\r')
                        {
                            sb.Append("++++++++++>");
                            continue;
                        }
                        sb.Append(new string('+', (int)c) + ">");
                    }
                    sb.Append(">");
                }
                res += sb.ToString() + Environment.NewLine;
            }
            else
            {
                foreach (string key in data.Keys)
                    res += String.Format(dataAdd[language], key, data[key].Replace("\\", "\\\\").Replace("\"", "\\\"").Replace(Environment.NewLine, @"\r\n"));
            }
            res += code;
            Console.Write(res);
        }
    }
}

Code - JS

(function(language){
 var quote = String.fromCharCode(34), backslash = String.fromCharCode(92), newline = backslash + String.fromCharCode(114) + backslash + String.fromCharCode(110);
 var data =
 {
 cs: " string language = args.Length == 0 ? \"cs\" : args[0];\r\n string code = data[language];\r\n Dictionary<string, string> bootstraps = new Dictionary<string, string>();\r\n bootstraps.Add(\"cs\", \"using System;\\r\\nusing System.Collections.Generic;\\r\\nusing System.Text;\\r\\n\\r\\nnamespace Multiquine\\r\\n{\\r\\n class Program\\r\\n {\\r\\n static void Main(string[] args)\\r\\n {\\r\\n Dictionary<string, string> data = new Dictionary<string, string>();\\r\\n\");\r\n bootstraps.Add(\"js\", \"(function(language){\\r\\n var quote = String.fromCharCode(34), backslash = String.fromCharCode(92), newline = backslash + String.fromCharCode(114) + backslash + String.fromCharCode(110);\\r\\n var data = \\r\\n {\\r\\n\");\r\n bootstraps.Add(\"bf\", \">>>>\\r\\n\");\r\n Dictionary<string, string> dataAdd = new Dictionary<string, string>();\r\n dataAdd.Add(\"cs\", \" data.Add(\\\"{0}\\\", \\\"{1}\\\");\" + Environment.NewLine);\r\n dataAdd.Add(\"js\", \" {0}: \\\"{1}\\\",\" + Environment.NewLine);\r\n string res = bootstraps[language];\r\n if (language == \"bf\")\r\n {\r\n StringBuilder sb = new StringBuilder();\r\n foreach (string key in data.Keys)\r\n {\r\n foreach (char c in key)\r\n {\r\n if (c == '\\n') continue;\r\n if (c == '\\r')\r\n {\r\n sb.Append(\"++++++++++>\");\r\n continue;\r\n }\r\n sb.Append(new string('+', (int)c) + \">\");\r\n }\r\n sb.Append(\">\");\r\n foreach (char c in data[key])\r\n {\r\n if (c == '\\n') continue;\r\n if (c == '\\r')\r\n {\r\n sb.Append(\"++++++++++>\");\r\n continue;\r\n }\r\n sb.Append(new string('+', (int)c) + \">\");\r\n }\r\n sb.Append(\">\");\r\n }\r\n res += sb.ToString() + Environment.NewLine;\r\n }\r\n else\r\n {\r\n foreach (string key in data.Keys)\r\n res += String.Format(dataAdd[language], key, data[key].Replace(\"\\\\\", \"\\\\\\\\\").Replace(\"\\\"\", \"\\\\\\\"\").Replace(Environment.NewLine, @\"\\r\\n\"));\r\n }\r\n res += code;\r\n Console.Write(res);\r\n }\r\n }\r\n}",
 js: " };\r\n\r\n if(!language) language = 'js';\r\n var code = data[language];\r\n var bootstraps = \r\n {\r\n js: '(function(language){\\r\\n var quote = String.fromCharCode(34), backslash = String.fromCharCode(92), newline = backslash + String.fromCharCode(114) + backslash + String.fromCharCode(110);\\r\\n var data = \\r\\n {\\r\\n',\r\n cs: 'using System;\\r\\nusing System.Collections.Generic;\\r\\nusing System.Text;\\r\\n\\r\\nnamespace Multiquine\\r\\n{\\r\\n class Program\\r\\n {\\r\\n static void Main(string[] args)\\r\\n {\\r\\n Dictionary<string, string> data = new Dictionary<string, string>();\\r\\n',\r\n bf: '>>>>\\r\\n',\r\n }\r\n var res = bootstraps[language]\r\n switch(language)\r\n {\r\n case 'js':\r\n for(var i in data) res += ' ' + i + ': ' + quote + data[i].replace(new RegExp('\\\\\\\\', 'g'), backslash + backslash).replace(new RegExp(quote, 'g'), backslash + quote).replace(new RegExp(newline, 'g'), backslash + 'r' + backslash + 'n') + quote + ',\\r\\n';\r\n break;\r\n case 'cs':\r\n for(var i in data) res += ' data.Add(' + quote + i + quote + ', ' + quote + data[i].replace(new RegExp('\\\\\\\\', 'g'), backslash + backslash).replace(new RegExp(quote, 'g'), backslash + quote).replace(new RegExp(newline, 'g'), backslash + 'r' + backslash + 'n') + quote + ');\\r\\n';\r\n break;\r\n case 'bf':\r\n for(var i in data)\r\n {\r\n for (var j = 0; j < i.length; j++) { if (i.charCodeAt(j) == 13) continue; res += \"+\".repeat(i.charCodeAt(j)); res += '>'; }\r\n res += '>';\r\n for (var j = 0; j < data[i].length; j++) { if (data[i].charCodeAt(j) == 13) continue; res += \"+\".repeat(data[i].charCodeAt(j)); res += '>'; }\r\n res += '>';\r\n }\r\n res += '\\r\\n';\r\n }\r\n res += code;\r\n console.log(res);\r\n})()",
 bf: ",>+<[>+++++++++[-<---------->]+<+[[-]>-<[-]>++[-<++++++++++++++++>]<++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.+++++++++++++++.-------.-----------.+++++++++++++++++.-----------.++++++.-.[-]>++[-<++++++++++++++++>]<++++++++.[-]>++++++[-<++++++++++++++++>]<++++++++++++.-----------.+++++++++++++.-------.++++++++++++++.--------------------.++++++.--.[-]>++[-<++++++++++++++++>]<+++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.++++++++++++++++++++++.[-]>+++++++[-<++++++++++++++++>]<++++++.---------------------.+++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>+++++++[-<++++++++++++++++>]<+.++++.------.+++++.---------------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.++++++++++++.---.--.[-]>++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++++++.-------.+++++++++++++++++.[-]>++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++++++++.-----------.+.[-]>++[-<++++++++++++++++>]<++++++++.+++++++++++.+.-----------.+++.------------.[-]>++++++[-<++++++++++++++++>]<++.-.++.++++++++.++++++++.-------.-----------.++++++++++++++++++.-----------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.++++++++++++.---.--.[-]>++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++++++.-------.+++++++++++++++++.[-]>++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++++++++.-----------.+.[-]>++[-<++++++++++++++++>]<++++++++.+++++++++++++++++.-------.---------.+++.------------.[-]>++++++[-<++++++++++++++++>]<++++++++++++++.---------.++++++++++++++++++.-----------.---.+++++.---------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<++.-.++.++++++++.++++++++.-------.-----------.++++++++++++++++++.-----------.[-]>++[-<++++++++++++++++>]<.+++++++++++.-----------.[-]>+++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.++++++++++++.---.--.[-]>++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++++++.-------.+++++++++++++++++.[-]>++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++++++++.-----------.+.[-]>++[-<++++++++++++++++>]<++++++++.+++++++++..+++.-----------.---------.+++++++++++.-----------.[-]>++++++[-<++++++++++++++++>]<++.-.++.++++++++.++++++++.-------.-----------.++++++++++++++++++.-----------.[-]>++[-<++++++++++++++++>]<.+++++++++++.-----------.[-]>+++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++.++++++++++++.---.--.[-]>++++[-<++++++++++++++++>]<+++.+++++++++++++++++++++++++++++++++++++.-------.+++++++++++++++++.[-]>++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++++++++.-----------.+.[-]>++[-<++++++++++++++++>]<++++++++.+++++++++..-.-------.++++++++++++++++++.[-]++++++++++.++++++++++++++++++++++.[-]>+++++++[-<++++++++++++++++>]<++++++.---------------------.+++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<++++.---.+++++++++++++++++++.-------------------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]++++++++++.++++++++++++++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.[-]<<<[[<]<]>>[<++++++++[-<++++>]<..>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]+++[-<++++++++++++++++>]<++++++++++.--------------------------.++.[-]>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]++[-<++++++++++++++++>]<++.++++++++++.[-]++++++++++.[-]>>]<<<<[[<]<]>>[>]>[>]>[>]>[.>]>[>]>[>]>>>]>[-[-]>+++++++[-<++++++++++++++++>]<+++++.--.----------.+++++.-------.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++.------.+.---------------.++++++++.[-]>+++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++.--.----------.+++++.-------.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++.------.+.---------------.++++++++.[-]>++[-<++++++++++++++++>]<++++++++++++++.+++++++++++++++++++++.++++++++++++++++++++++++++++++++++++++++++++.---..-------.--.+++++++++++++++++.-----------.++++++.-.+++++.[-]>++[-<++++++++++++++++>]<++++++++++++++.+++++++++++++++++++++++++.++++++++++++++++++++++++++++++.+++++++++.---------.+++++++++++++.---------.------.[-]>+++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++.--.----------.+++++.-------.[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<+++.++++++++++++++++++++++++++++++++++++++.------.+.---------------.++++++++.[-]>++[-<++++++++++++++++>]<++++++++++++++.[-]>+++++[-<++++++++++++++++>]<++++.+++++++++++++++++.+++++++++++++++++++.----.[-]>+++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.[-]++++++++++.[-]>++++++[-<++++++++++++++++>]<++++++++++++++.-------------.++++++++++++.--------.++++++++++++++.---.---------------.++.++.[-]>++[-<++++++++++++++++>]<.[-]>++++[-<++++++++++++++++>]<+++++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++.---------.++++++++.-----------.++++++++.++++.------------.+++++.---------.[-]++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.++++++++++++++++++++++....[-]>++++++[-<++++++++++++++++>]<+++.+++++++++.-----------.++++++++++++++++++..[-]>++[-<++++++++++++++++>]<.[-]>+++++[-<++++++++++++++++>]<.++++++++++++++++++++++++++++++++++.---.--------.+++++++++++.-----------------.++++++++++++.[-]++++++++++.++++++++++++++++++++++....[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.++++++++++++++++++++++........[-]>+++++++[-<++++++++++++++++>]<+++.+.-------------------.+++++++++++++++++++.-----------.------.[-]>++[-<++++++++++++++++>]<.[-]>+++++++[-<++++++++++++++++>]<++++++.-------.------.-----.[-]>++[-<++++++++++++++++>]<.[-]>++++[-<++++++++++++++++>]<+++++++++++++.++++++++++++++++++++.++++++++.+++++.[-]>++[-<++++++++++++++++>]<++++++++.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.------------.++.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<+.+++++++++++++++++.-----------.++++++++++++.[-]>++[-<++++++++++++++++>]<+++++++++.[-]++++++++++.++++++++++++++++++++++........[-]>+++++++[-<++++++++++++++++>]<+++++++++++.[-]++++++++++.++++++++++++++++++++++............[-]>++++[-<++++++++++++++++>]<++++.+++++++++++++++++++++++++++++++++++++.------.+++++++++++++++++.-----------.++++++.-.-------------.+++++++++++++++++.+++++++.[-]>+++[-<++++++++++++++++>]<++++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++.------------.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.-----------------------------------------.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<++++.---.+++++++++++++++++++.-------------------.[-]>++[-<++++++++++++++++>]<.+++++++++++++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>++++++[-<++++++++++++++++>]<++++++++++++++.---------.++++++++++++++++++.[-]>++[-<++++++++++++++++>]<.[-]>++++[-<++++++++++++++++>]<++++.+++++++++++++++++++++++++++++++++++++.------.+++++++++++++++++.-----------.++++++.-.-------------.+++++++++++++++++.+++++++.[-]>+++[-<++++++++++++++++>]<++++++++++++.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.[-]>++[-<++++++++++++++++>]<++++++++++++.------------.[-]>+++++++[-<++++++++++++++++>]<+++.+.--.---------.+++++.-------.-----------------------------------------.----------------------.+.++++++++++++++++++.[-]++++++++++.[-]<<<[[<]<]>>[<++[-<++++++++++++++++>]<............[-]>++++++[-<++++++++++++++++>]<++++.---.+++++++++++++++++++.-------------------.[-]>++[-<++++++++++++++++>]<++++++++++++++.+++++++++++++++++++.+++++++++++++++++++++++++++++++++++..[-]>++[-<++++++++++++++++>]<++++++++.------.[-]>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]++[-<++++++++++++++++>]<++.++++++++++.------------.++.[-]>>[<+>----------[------------------------[<++++++++++++++[->----<]+>++[<++++++++++++[->+++++++<]>+.[-<<+>>]]<[++++++++++++[-<+++++++>]<+..>]>]<[++++++++++++[->+++++++<]>+.[-]<<++++++++++++++++++++++++++++++++++.>]>]<[->+++++[-<++++++++++++++++>]<++++++++++++.++++++++++++++++++++++.----------------------.++++++++++++++++++.[-]<++++++++++>]>>]++[-<++++++++++++++++>]<++.+++++++.++++++++++++++++++.[-]++++++++++.[-]>>]<<<<[[<]<]>>[>]>[.>]>[[>]>]>>>]<]>[-<<<[[<]<]+++[-<+++++++>]<[->++>+++<<]>+>-....<<++++++++++.[-]>>>[[[[-<<.<+>>>]<.[->+<]<[->+<]>>>]<.[->+<]<[->+<]>>>]]<<<<<[<]++++++++++.[-]>[.>]]",
 };

 if(!language) language = 'js';
 var code = data[language];
 var bootstraps =
 {
 js: '(function(language){\r\n var quote = String.fromCharCode(34), backslash = String.fromCharCode(92), newline = backslash + String.fromCharCode(114) + backslash + String.fromCharCode(110);\r\n var data = \r\n {\r\n',
 cs: 'using System;\r\nusing System.Collections.Generic;\r\nusing System.Text;\r\n\r\nnamespace Multiquine\r\n{\r\n class Program\r\n {\r\n static void Main(string[] args)\r\n {\r\n Dictionary<string, string> data = new Dictionary<string, string>();\r\n',
 bf: '>>>>\r\n',
 }
 var res = bootstraps[language]
 switch(language)
 {
 case 'js':
 for(var i in data) res += ' ' + i + ': ' + quote + data[i].replace(new RegExp('\\\\', 'g'), backslash + backslash).replace(new RegExp(quote, 'g'), backslash + quote).replace(new RegExp(newline, 'g'), backslash + 'r' + backslash + 'n') + quote + ',\r\n';
 break;
 case 'cs':
 for(var i in data) res += ' data.Add(' + quote + i + quote + ', ' + quote + data[i].replace(new RegExp('\\\\', 'g'), backslash + backslash).replace(new RegExp(quote, 'g'), backslash + quote).replace(new RegExp(newline, 'g'), backslash + 'r' + backslash + 'n') + quote + ');\r\n';
 break;
 case 'bf':
 for(var i in data)
 {
 for (var j = 0; j < i.length; j++) { if (i.charCodeAt(j) == 13) continue; res += "+".repeat(i.charCodeAt(j)); res += '>'; }
res += '>';
for (var j = 0; j < data[i].length; j++) { if (data[i].charCodeAt(j) == 13) continue; res += "+".repeat(data[i].charCodeAt(j)); res += '>'; }
res += '>';
 }
 res += '\r\n';
 }
 res += code;
 console.log(res);
})()

Code - BF

This one is really long... So, please generate it from either JS or CS code :)

Note

I strongly suggest NOT TO USE the online interpreter (nor any interpreter actually) to try the BF code. I yo're using Ubuntu, you can use the BF package (if you're on any other Linux distribution, you can use the same package by building the source - it even works on Mac OSX).

And if you're using Windows, then you can download Cydia, and compile the BF sources as well 

Mutiquine: structure (3)

Context

The multiquine structure is composed by the bootstrap, the data declaration and the code.
Here is a C# example.

/*BOOTSTRAP*/
using System;
using System.Collections.Generic;
using System.Text;

namespace Multiquine
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
/*DATA*/
            data.Add("cs", "CS_CODE_PLACEHOLDER");
            data.Add("js", "JS_CODE_PLACEHOLDER");
            data.Add("bf", "BF_CODE_PLACEHOLDER");
/*CODE*/
            string language = args.Length == 0 ? "cs" : args[0];
            string code = data[language];
            Dictionary<string, string> bootstraps = new Dictionary<string, string>();
            bootstraps.Add("cs", "CS_BOOTSTRAP_PLACEHOLDER");
            bootstraps.Add("js", "JS_BOOTSTRAP_PLACEHOLDER");
            bootstraps.Add("bf", "BF_BOOTSTRAP_PLACEHOLDER");
            Dictionary<string, string> dataAdd = new Dictionary<string, string>();
            dataAdd.Add("cs", " data.Add(\"{0}\", \"{1}\");" + Environment.NewLine);
            dataAdd.Add("js", " {0}: \"{1}\"," + Environment.NewLine);
            string res = bootstraps[language];
            if (language == "bf")
            {
                StringBuilder sb = new StringBuilder();
                foreach (string key in data.Keys)
                {
                    foreach (char c in key)
                    {
                        if (c == '\n') continue;
                        if (c == '\r')
                        {
                            sb.Append("++++++++++>");
                            continue;
                        }
                        sb.Append(new string('+', (int)c) + ">");
                    }
                    sb.Append(">");
                    foreach (char c in data[key])
                    {
                        if (c == '\n') continue;
                        if (c == '\r')
                        {
                            sb.Append("++++++++++>");
                            continue;
                        }
                        sb.Append(new string('+', (int)c) + ">");
                    }
                    sb.Append(">");
                }
                res += sb.ToString() + Environment.NewLine;
            }
            else
            {
                foreach (string key in data.Keys)
                    res += String.Format(dataAdd[language], key, data[key].Replace("\\", "\\\\").Replace("\"", "\\\"").Replace(Environment.NewLine, @"\r\n"));
            }
            res += code;
            Console.Write(res);
        }
    }
}

The bootstrap 

/*BOOTSTRAP*/
using System;
using System.Collections.Generic;
using System.Text;

namespace Multiquine
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, string> data = new Dictionary<string, string>();
As mentionned, it's a static part, in C#, to initialize our program the way source code should be.
It also initializes the data structure, though the data themselves are not set yet.

The data

/*DATA*/
            data.Add("cs", "CS_CODE_PLACEHOLDER");
            data.Add("js", "JS_CODE_PLACEHOLDER");
            data.Add("bf", "BF_CODE_PLACEHOLDER");
In other words, for each language, add some data (we use placeholders that will be filled later)

The code

/*CODE*/
            string language = args.Length == 0 ? "cs" : args[0];
            string code = data[language];
            Dictionary<string, string> bootstraps = new Dictionary<string, string>();
            bootstraps.Add("cs", "CS_BOOTSTRAP_PLACEHOLDER");
            bootstraps.Add("js", "JS_BOOTSTRAP_PLACEHOLDER");
            bootstraps.Add("bf", "BF_BOOTSTRAP_PLACEHOLDER");
            Dictionary<string, string> dataAdd = new Dictionary<string, string>();
            dataAdd.Add("cs", " data.Add(\"{0}\", \"{1}\");" + Environment.NewLine);
            dataAdd.Add("js", " {0}: \"{1}\"," + Environment.NewLine);
            string res = bootstraps[language];
            if (language == "bf")
            {
                StringBuilder sb = new StringBuilder();
                foreach (string key in data.Keys)
                {
                    foreach (char c in key)
                    {
                        if (c == '\n') continue;
                        if (c == '\r')
                        {
                            sb.Append("++++++++++>");
                            continue;
                        }
                        sb.Append(new string('+', (int)c) + ">");
                    }
                    sb.Append(">");
                    foreach (char c in data[key])
                    {
                        if (c == '\n') continue;
                        if (c == '\r')
                        {
                            sb.Append("++++++++++>");
                            continue;
                        }
                        sb.Append(new string('+', (int)c) + ">");
                    }
                    sb.Append(">");
                }
                res += sb.ToString() + Environment.NewLine;
            }
            else
            {
                foreach (string key in data.Keys)
                    res += String.Format(dataAdd[language], key, data[key].Replace("\\", "\\\\").Replace("\"", "\\\"").Replace(Environment.NewLine, @"\r\n"));
            }
            res += code;
            Console.Write(res);
        }
    }
}
Everything that arrives after data declaration is the code. And our C# code does exactly what JS code will do, or BF code as well.

  • First, determine the desired output language (CS, JS or BF)
  • Then, initialize the output with target language's bootstrap (again, using placeholders, as other languages' bootstrap codes are not defined yet)
  • In theory, we should do the same for the 2 other languages, and only then move to the next part of the code, as it requires some knowledge about other quines' data declaration structure...
    • Build BF data declaration (write language name, and then language data, for each language), just make sure line breaks are processed in a slightly different way (to be more compliant with different interpreters)
    • OR build other languages data declaration (C# and JS were grouped because quite similar)
  • Finally, append target language's specific code (id est, append data as it's supposed to be the code, as string)
The next post will present the 3 templates, for CS, BF and JS, and the final results.

Multiquine : construction (2)

Context

We defined what a multiquine is, and picked 3 languages (C#, JS and BF).
Now, let's build our multiquine.

As a reminder, when building a simple quine, we stated that a quine needs 2 parts:

  • The data
  • The code
Code's goal is to write data definition, based on data contents, then write code, again based on data contents
And data is written afterwards, when code is completed, based on code source code.

To make things a bit more clear, let's introduce a third part (actually, the first one in our source codes): the bootstrap.

The bootstrap will be some static source code, written before data declaration.

Then, to build a multiquine:

  • Write the bootstrap
  • Declare data (leaving some blanks to be filled later) for each language
  • Write code
    • For a given language L (passed as program argument)
      • Write target bootstrap
      • Declare data the way it should be declared in language L
        • Note: declare data for all languages
      • Write code based on specific data related to language L

Multiquine : definition (1)

Context

We already implemented a quine, and also what we called a double-quine, though it's definitely not an official name.
Actually, double-quine may make people think it's a multiquine of 2 languages, which is not the case.

Let's first define what a multiquine is, and then try to implement one.
Considering a set S of N Turing-complete programming languages, a multiquine is a program, written in a language from S, that:

  • can be run without argument. It then prints its own source code, like a normal quine
  • can be run with an argument (that can have, in theory, N-1 different values). It then prints another program in a different language from S, that have the same 2 properties we are describing.
In other words, considering programming languages A, B and C, I have 3 programs Pa, Pb, Pc written in A, B and C
  • When Pa() is executed, it prints Pa's source code.
  • When Pa(arg1) is executed, it prints Pb's source code.
  • When Pa(arg2) is executed, it prints Pc's source code.
  • When Pb() is executed, it prints Pb's source code.
  • When Pb(arg3) is executed, it prints Pa's source code.
  • When Pb(arg4) is executed, it prints Pc's source code.
  • When Pc() is executed, it prints Pb's source code.
  • When Pc(arg5) is executed, it prints Pa's source code.
  • When Pc(arg6) is executed, it prints Pb's source code.
arg1 may be equal to arg6, arg2 to arg4 and arg4 to arg5, though it's not a mandatory condition.

In the following articles, we'll implement a multiquine for the 3 languages BrainFuck (of course), C# (I don't like Java...) and JavaScript (yes, it's a language)

jeudi 2 mars 2017

Quine: the code (2)

Context

Now that we know how to build a quine, let's build it.
Obviously, the shorter the code will be, the sorter the data will be as well, and same for the final quine. We'll see in next article how to obtain the data part easily

Initial state

  • Memory: empty
  • Cursor: first cell
  • Input: any

Process

  • In order to have a short code, we will build constants for + and > symbols, and print them as needed
  • To go efficiently through our array, we should move those constants after each iteration (less expensive than going back to the array start every time)
  • Therefore, we need to leave some space before setting data in memory, to store these constants at initialization, and then move them. 4 cells are enough.
  • The final code looks like
    • Move 4 cells to the left
    • Store data (using + and > only)
    • Go back to first cell
    • Generate + and > symbols just before first cell
    • Print > four times (to match the first row above, as this is outside data)
    • Go to first array cell and iterate
      • print + as many times as needed (and save a copy of the value)
      • print > once
      • move constants one cell to the left
      • go to next cell
    • Go back to first array cell and iterate
      • print value

Code

>>>>
data (that ends with a >)
go to array start
<[<]
build PLUS and GT
<<<+++++++[->+++<]>[->++>+++<<]>+>-
print GT 4 times
....
go to first cell
>
[
  print PLUS as many times as needed and save current data value
  [-<<.<+>>>]
  print GT
  <.
  move symbols
  [->+<]<[->+<]
  >>>
]
print code
<<<<[<]>[.>]

Final state

  • Memory: uncleaned
  • Cursor: who cares ?
  • Input: unused - non-cheating quine !
  • Output : 4 >, then data generation code, then data
Note: the part in yellow will define our data.
To be continued...

mardi 28 février 2017

Cipher: ASCII shift

Context

The Shift cipher (also known as Caesar cipher) is a very simple and basic encryption technique.
Basically, each letter from alphabet is substituted by the Nth letter after this one in the alphabet (wrapping on alphabet's end to the beginning). The value of N is the cipher key.
Here, let's have a similar algorithm based on ASCII codes. We can of course add a lot of checks to consider only letters, have different behaviors on upper cased / lower cased chars, wrap on alphabet, ... but we will keep it short and simple.
Our cipher will just read a key N (number in its decimal form), then a comma separator, and finally each char will be displayed with an offset of N.
The deciphering tool can be based on the same code, with only one instruction to be replaced (the offset is taken as a negative number)

Initial state

  • Memory: empty
  • Cursor: first cell
  • Input: N,text to encrypt / decrypt

Process

  • Read key
    • Read char
      • If it's a comma, stop reading key
      • Otherwise, consider char as next decimal digit of the current key
  • Cipher / decipher engine
    • Read char
    • Add / remove offset
    • Print char
    • Loop

Code - cipher - try it

read key and comma separator
>,[>++++[-<----------->]+<[---->++++++++[-<<[->+>>+<<<]>>>[-<<<+>>>]<]<[-<+>],>]>[->]<<]

read chars then shift and print
>,[<<[->+>+<<]>[-<+>]>.,]

 Code - decipher - try it

read key and comma separator
>,[>++++[-<----------->]+<[---->++++++++[-<<[->+>>+<<<]>>>[-<<<+>>>]<]<[-<+>],>]>[->]<<]

read chars then shift and print
>,[<<[->+>-<<]>[-<+>]>.,]

 Final state

  • Memory: key 0 0
  • Cursor: third cell
  • Input: empty
  • Output: ciphered text

jeudi 23 février 2017

Sort: Counting sort

Context

Counting sort is a sort algorithm dedicated to lists having values in a small set. Then, one can create an array of same size and store values (or count) while reading.
Using BrainFuck, all our values are stored between 0 and 255. Therefore, it might be an interesting sort algorithm. Let's implement it.
Initial state
  • Memory: 0 0 [array] 0 0 0 0 0 ... where array is a 2 cells block array of nullable integers
  • Pointer: just after array
  • Input: any

Process

  • Generate counter array
    • That's a 2 cells block array of nullable integers, of size 256
    • Generate the first cell
    • Then have 255 in a counter and generate all cells after
  • For each integer N from the list
    • Access item N in array and increment counter
  • Optionally, we can rebuild back the array when sort is completed
    • Define current value (initially: 0)
    • For each counter C in counter array
      • Add current value C times
      • Increment current value

Code - try it

generate counter array: 2 cells array with 256 items
->>>>>+<<<<<[->>>>>[>>]+[<<]<<<]

read integers one by one and store into array
go to first integer and loop
<<[<<]>>
[
  remove cell indicator
  -
  move value to end
  >[->[>>]>+<<<[<<]>]
  go to value and move backward
  >[>>]>[-<+>]
  access array cell given by index
  <[->>>[>>]+>>->[-<<+>>]<<<[<<]<]
  increment count for given value
  >>>[>>]>>>+
  move array back to position
  <<<<<[[->>+<<]>[->>+<<]<<<]
  go to next integer
  <<<[<<]>>
]

rebuild array of values
>>>>>
[
  move cell
  -<<+>>>[-<<+>>]<<
  add value N that many times
  [
    -
    go to current value
    <[<<]<
    copy / move to end of array
    [->+>+<<]>[-<<<[<<]>+>[>>]>]
    set cell flag
    <<<[<<]+[>>]
    restore current value copy
    >>[-<<+>>]
    go back to value counter
    >[>>]<
  ]
  increment current value
  <[<<]<+
  >>>[>>]>>
  go to next cell and loop
]

clear counter array
<<<<[->[-]<<<]

Final state

  • Memory: 0 0 [sorted array] 0 0 0...
  • Cursor: 2 cells after array
  • Input: unchanged
  • Output: unchanged
Notes
  1. Due to our array rebuild, the sort is descending, but this can be easily changed to ascending sort
  2. Despite a shorter algorithm, execution is really longer than Quicksort

mercredi 22 février 2017

Sort: Quicksort

Context

After Bubble sort, let's see how to implement another algorithm : Quicksort.
Quicksort is really efficient, its mechanism is:

  • Select a pivot cell (any cell from the list is fine, we will pick the last one though it has been proven that's the worst case)
  • For each other cell
    • If value is greater than pivot: move to set B
    • Otherwise, move to set A
  • Then, recursively sort A and B, and finally rebuild the concatenation [ sorted A ] + pivot + [ sorted B]
Example: let's sort 4, 5, 3, 1, 2
  • Pivot: 2, and we generate one set [1] and one set [4, 5, 3]
    • Sort [1] -- done
    • Sort [4, 5, 3]: pivot is 3 and generates only one set [4, 5]
      • Sort [4, 5]: pivot is 5 and generates set [4]
        • Sort [4] -- done
      • Merge: [4, 5]
    • Merge: [3, 4, 5]
  • Merge: [1, 2, 3, 4, 5]

Initial state

  • Memory: 0 ... (fifteen times) ... [array length] 0 0 [2 cells array to handle null values] 0 0 ...
  • Initial pointer:  just after array
  • Input: any

Process

  • Note: array length can be either computed (see this post - though it's for 1 cell array only but can be adapted easily), or directly computed while reading input if integers are provided by end-user
  • We will define a queue of ranges to process
    • Memory will looks like 0 0 ... 0 0 [array] 0 0 0 [queue of ranges to process]
    • Range: first item index + range length
    • First range: {1, array length}, because we will process the whole array
    • Therefore, move array length and store value 1 in the queue
  • Pick one range definition from queue
  • Split array to isolate range
    • Items before range start index are moved to the far left
    • Items after range index are moved to the (just a bit less) far left as well until range length is reached
    • Items after that are unchanged
    • Memory : 0 0 [out of range] 0 0 [range to process] 0 ... 0  [out of range] 0 ... 0 [queue]
  • Then
    • Select a pivot (last item in range to process)
    • Store a copy
    • This will be our memory during range processing
      [range to process] 0 0 [processed left] pivot 0 pivot 0 0 0 0 [processed rigth]
    • For each other item to process
      • Store a copy
      • Compare to pivot
        • Pivot is greater than value : move value to processed left
        • otherwise
          • move value to processed right
          • move processed left to the left
          • move pivot and copy to the left as well
        • Note: this allows an in-place processing...
    • Count items in processed left and merge with pivor
    • Merge the whole array
      [out of range] [ processed left] pivot [processed right] [out of range]
    • Compute new range definitions - current range starts at S and has length L
      • If processed left's length L' is not null: we need to process this block, defined by a start at S and this particular length L'
      • Processed right range definition is given by start at S + L' + 1 and length L - L' - 1
      • For both ranges, if length is not null, then enqueue range definitions
  • Finally, shift the queue to the left (as first elements have been removed), and loop on new range definition
  • Stops when no range definition is available (array is sorted)
move count and create first range
<<[<<]<[->>>[>>]>>>>+<<<<<<[<<]<]>>>[>>]>>>+

while there is a range to process
[
  copy range start index and split array at this position
  <+>-[-<<<<<[<<]>>[-<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>]>[-<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>]>[>>]>>+>]

  copy range length and split array for this number of items
  >[-<<<<<<[<<]>>[-<<<<<<<<<<<<<<+>>>>>>>>>>>>>>]>[-<<<<<<<<<<<<<<+>>>>>>>>>>>>>>]>[>>]>>>+>]

  go to array isolated range
  <<<<<<[<<]<<<<<<<<<<<<<<

  copy pivot
  ->[->>>+>>+<<<<<]

  go to first element to process
  <<<

  while there is an element to process
  [
    copy element for save and comparison
    ->[->>>[>>]>>>+>>+<<<<<<<[<<]<]>>>[>>]>>>>
    compare copies
    >>+<<[->[->]>[<<[-]>>->>]<<+<<]>[[-]<+>]>-<+<
    [>-<
      pivot is less than current: move current into the right part
      -<[->>>>>>>+<<<<<<<]>>>>>>+
      move the left part to reuse free space
      <<<<<<<<<<<[<<]>>[[-<<+>>]>[-<<+>>]>]
      move pivot for same reason and copy it
      >>[-<+<+>>]<[->+<]>>
    ]
    >[-
      pivot is greater than current: move current into the left part
      <<[-<<<<<[<<]>+>[>>]>>>]<<<<<[<<]+[>>]
      copy pivot
      >>[->+>+<<]>[-<+>]>>>
    ]
    in all cases current position is 2 cells after second pivot copy
    go to next cell to process
    <<<<<<<<[<<]<<
  ]
  reset pivot copy
  >>>>[>>]>>[-]
  count left part length and merge
  <<<<[
    move
    ->[->>+<<]>+
    increment counter
    >>[>>]>>>>>+<<<<<<<[<<]<<
  ]
  include pivot
  >>>>[>>]+>>[-<+>]
  move left part length outside array
  >>>[->>>>[>>]>>>[>>]>+<<<[<<]<<<[<<]<<]
  rebuild whole array
  move right part of sorted range
  >>>>[>>]<<[->[->>>+<<<]>>+<<<<<]
  move left part of sorted range and pivot
  <<<<<<<[->[->>>>>>>>>>+<<<<<<<<<<]>>>>>>>>>+<<<<<<<<<<<<]
  move left part outside range
  <<<<<<[->[->>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<]>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<]

  compute next range(s) definitions
  got to left part length
  >>>>>>>>>>>>>>>>>>[>>]>
  [
    if not null: add left range definition
    start: same as current start
    length: given by current value

    copy and push start
    >[-<<+>>>>>[>]>+<<[<]<<]<<[->>+<<]
    copy and push length
    >[-<+>>>>>[>]>>+<<<[<]<<<]
    add new range on queue
    >>>>[>]>[[-<+>]>]<<[<]<<<
    move left part length to the left to break loop (which is actually an if)
  ]
  compute second possible range start (current range start increased by left range length and pivot)
  compute as well second possible range length (current range length decreased by left range length and pivot)
  <[->>+>-<<<]>>+>-
  [
    if length is not null: move to queue
    <[->>>[>]>+<<[<]<<]
    >[->>[>]>>+<<<[<]<]
    >>[>]>[[-<+>]>]<<[<]<
  ]
  reset second range length if needed
  <[-]
  shift the queue
  >>>[[-<<+>>]>]
  go to next range definition in queue
  <<<[<]>
]

Final state

  • Memory: [eighteen zeros] [sorted array] 0 0 0 0
  • Cursor: 4 cells after array
  • Input: unchanged
  • Output: unchanged
Note: one can check that this code, even if more complex, is really faster, even in brainfuck, than the bubble sort implementation.