Ludicrous Coloured Triangles



    The code computes the result of the combination of two colours together. Notice that, unlike many programming languages, values in JavaScript are written in integer form (0, 1, 2). This makes it easy to work with powers and combinations of integers, which is why this code uses a function to do the work.

    The first part of the code defines the combine function. This function takes two inputs, a and b. It returns a new value that is either a or b depending on whether a and b are equal.

    The next part of the code defines the pow3 function. This function takes a number n and computes the power of 3 less than or equal to n. This calculation is performed very quickly on the current platform, thanks to the way it uses an iterative algorithm.

    The last part of the code defines the rec function. This function takes a level and an offset and calculates the colour corresponding to that offset on the current row. In other words, it returns the result of the combination of the colours at the two positions indicated by level and offset.

    Finally, the code clears the screen and sets the row and column variables to 0. It then sets the offset variable to the length of the input string (in

    function triangle(row) {
      /* Returns the result of the combination of two colours. 
          Note that inputs and output are all integers (0, 1, and 2), not letters (R, G, and B).
      function combine(a, b) {
        return (a === b) ? a : (3-a-b);
      /* Returns the greatest power of 3 less than or equal to n. */
      function pow3(n) {
          This is the most straightforward implementation (it computes iterative 
          multiplications by 3 for each and every call).
          But interestingly enough it runs super fast on the current platform. A lot 
          faster, for instance, than another one I tried using an array of pre-computed powers.
        let i= 1, j= 1;
        while (i <= n) {
          j= i;
          i*= 3;
        return j;
      /* Recursive function computing the *offset*th colour on the *level*th row */
      function rec(level, offset) {
            The technique here comes from the observation that for a string of 4 colours (3+1), 
            only the ends actually have an influence on the result. The two colours in the 
            middle of the string have no impact at all. More precisely: 
            - RxxR always gives R (and GxxG gives G, and BxxB gives B),
            - RxxG always gives B (and this is symetrical for other combinations).
            This obviously scales up: a string of 10 colours (3*3+1) is like 4 times a string
            of 4 (with combined ends), so again only the ends have an impact... and so on for 
            every power of 3 plus 1.
            This property allows to compute large strings very efficiently by ignoring a large 
            part of the input and focusing only on the few chunks that have an actual influence 
            on the final result.
        if (!level) {
              In order to speed things up, we use integers (0, 1, 2) instead of 
              letters for the whole computation. Letters are transformed into indexes 
              only for the first row (level == 0).
          switch (row[offset]) {
          case 'R': return 0;
          case 'G': return 1;
          default: return 2;
        const step= pow3(level);
        return combine(rec(level-step, offset), rec(level-step, offset+step));
      if (!row) return '';
      /* Launch the computation, and convert the result back to a letter */
      return "RGB"[rec(row.length-1, 0)];
    Codiga Logo
    Codiga Hub
    • Rulesets
    • Playground
    • Snippets
    • Cookbooks
    soc-2 icon

    We are SOC-2 Compliance Certified

    G2 high performer medal

    Codiga – All rights reserved 2022.