Number Triangles

11

Credit

My thanks to Rand Al'Thor's letter-based question for the inspiration for this code-golf challenge.

Background

The nature of this challenge is based off the algorithm mentioned by Rand in his "A Triangle Formed of Three Letters":

  • Start with a sequence of 10 letters each of which is X, Y, or Z.
  • Under each row, construct the next row as follows. If two adjacent letters are the same, write the same letter beneath them; if they're different, write the third letter beneath them.

You would then repeat the previous step until you have one letter in your tenth row.

Challenge

We're going to put a mathematical spin on the above algorithm:

  • Let's start with a sequences of 10 digits, each separated by a space, and each of which is either 1, 2 or 3.
  • Under each row, construct the next row as follows. If two adjacent digits are the same, write the same digit beneath them; if they're different, write the third digit beneath them.
  • Repeat the previous step until you have one final number.

So, following this algorithm, if starting with the row 1 2 3 3 1 3 1 3 1 2, for example, the following triangle is generated:

Input: 1 2 3 3 1 3 1 3 1 2

Output:

1 2 3 3 1 3 1 3 1 2
 3 1 3 2 2 2 2 2 3 
  2 2 1 2 2 2 2 1  
   2 3 3 2 2 2 3   
    1 3 1 2 2 1    
     2 2 3 2 3     
      2 1 1 1      
       3 1 1       
        2 1        
         3         

I'm also curious to know the sum of all the digits in the number triangle, so add all these digits, and put this total in an eleventh row, right-justified to the last digit in the first row. So, our number triangle will look something like the following (spaces in my example are represented below by the . character to show formatting.)

Input: 1 2 3 3 1 3 1 3 1 2

Output:

1.2.3.3.1.3.1.3.1.2
.3.1.3.2.2.2.2.2.3.
..2.2.1.2.2.2.2.1..
...2.3.3.2.2.2.3...
....1.3.1.2.2.1....
.....2.2.3.2.3.....
......2.1.1.1......
.......3.1.1.......
........2.1........
.........3.........
................109

Your challenge is to write code that can start with an inputted string/array/etc. of ten digits, as per my example, and then apply the algorithm to generate the ten rows that would create the number triangle, followed by an 11th row that would display the total of all digits with right-justification.

Testing

Testing of this string can be performed with a randomly generated string of ten digits of your choosing, or one generated from the snippet below...

c1=()=>('1331123221'+(Math.random()*(1<<24)|0).toString(4)).replace(/0/g, "").slice(-10).split("").join(" ");

$("#btn").click(function(){
  $("#str").val(c1());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="str"><button id="btn">Get numbers</button>
<br>
Please use this snippet to generate a starting row for testing your code. Alternatively, you can also use a string of your choice, so long as it's ten digits (ranging from 1 to 3), separated by single spaces.

Rules

  1. Code-golf rules apply, so lowest number of bytes wins the challenge. In the event that there are two entries with the same low score, the winner will be awarded based on the number of up-votes.
  2. What we're basically after is 11 rows, 19 characters long... How you render your final output is entirely up to you: array, console, file output, STDOUT, etc., so please use whatever output method you like that will work to your advantage. The only rule in the output is that we have 11 rows with 19 characters in each row in a similar format to above...
  3. If it helps your code, use whatever separator for the digits... Just remember that legibility may be a contributing factor.
  4. No silly loopholes.
  5. Hard-coding of the input is not allowed. The purposes of this code is such that it can be used to produce different results each time with varying input. Hard-coding of 1 1 1 1 1 1 1 1 1 1 for example, completely negates the whole point of the algorithm.

Look forward to seeing what you all can come up with!

WallyWest

Posted 2016-09-26T00:14:09.303

Reputation: 6 949

Sorta related – James – 2016-09-26T00:24:36.843

@DJMcMayhem Not related, the triangle in your referenced question has differences used to populating the next row. There's nothing like that in this question. The next row is populated through two specifc rules (A: if the two parents are the same, the child is the same; and B: if the two parents are different, the child is the third from the set) – WallyWest – 2016-09-26T01:27:05.057

1Do I need a separator if my triangle is center-aligned (which is thus legible)? – JungHwan Min – 2016-09-26T03:44:50.800

@JHM... It sounds like in your case it may be optional... Let's take a look – WallyWest – 2016-09-26T03:52:14.147

1

It looks like this without the space (my answer has space, which takes 10 bytes).

– JungHwan Min – 2016-09-26T03:55:03.457

So is it okay if I remove the spaces? – JungHwan Min – 2016-09-26T05:14:23.503

2Permission granted – WallyWest – 2016-09-26T05:21:26.637

1Note that for a string of 10 (or any number 1 greater than a power of 3) digits, the final digit is trivially calculated from the first and last digit in the string; the other digits make no difference. – Neil – 2016-09-26T13:42:47.457

Answers

1

05AB1E, 32 26 bytes

DvÐOˆðýðN×.ø,ü+3%3^}\¯O19j

Explanation

D                 # duplicate input
v                 # for y,N in input,len(input): (10 times do)
 Ð                # triplicate current list
 Oˆ               # sum one copy and add it to global array
 ðý               # merge one copy on spaces
   ðN×.ø          # surround it with N spaces
        ,         # and print it
 ü+               # reduce one copy by addition
   3%             # modulus 3
     3^           # XOR 3
                  # this is the list sent to the next iteration
}                 # end loop
\                 # drop empty list left over from last iteration of loop
 ¯O               # sum the global array giving the triangles total sum
   19j            # join with spaces up to 19 chars

Try it online!

Emigna

Posted 2016-09-26T00:14:09.303

Reputation: 50 798

7

Mathematica, 104 97 90 94 bytes

{Grid[List@*Row/@#],#~Total~2}~Column~Right&[NestList[3-Mod[+##,3]&@@@Partition[#,2,1]&,#,9]]&

Explanation

Partition[#,2,1]

Partitions the input into length 2, offset 1 partitions.

3-Mod[+##,3]&@@@

Takes each partition, and calculates the corresponding output.

A trick involved here. I added up the two numbers, took mod 3, and subtracted that result from 3. That gives the desired number. (e.g. 3 - ((2 + 1) mod 3) = 3)

NestList[ ... ,9]

Repeats the above process nine times, giving all iterations as the output.

Grid[List@*Row/@#]

Format each iteration into rows, and put the entire thing in one column (center aligned), creating a triangle.

#~Total~2

Take the total of all numbers.

{...}~Column~Right

Combine the triangle and the total, and right align the entire thing (triangle is already aligned, so its alignment is not affected).

JungHwan Min

Posted 2016-09-26T00:14:09.303

Reputation: 13 290

1Inspired approach with a single function that takes care of both the identical and different parent types... I like it! – WallyWest – 2016-09-26T04:07:06.477

3

JavaScript (ES6), 143 142 bytes

Saved 1 byte thanks to @Neil

a=>a.map((_,i)=>(q=" ".repeat(i))+(a=a.map(c=>(x+=r=i&&p^(p=c)||c,r),p=i&&a.shift())).join` `+q,x=0).join`
`+`
`+(" ".repeat(18)+x).slice(-19)

I tried combining various parts, but it ended up 5 bytes longer:

a=>[...a.map((_,i)=>(a=a.map(c=>(x+=r=i&&p^(p=c)||c,r),p=i&&a.shift())).join` `+" ".repeat(i),x=0),x].map(q=>(" ".repeat(18)+q).slice(-19)).join`
`

ETHproductions

Posted 2016-09-26T00:14:09.303

Reputation: 47 880

Great work! Could JHM's trick of 3-((x+y)%3) be of any help reducing this code? – WallyWest – 2016-09-26T04:15:33.127

2Nope. p^c||p is already quite a bit shorter :-) – ETHproductions – 2016-09-26T04:17:27.197

Now, how the hell did I miss that? Of course! XOR functions work well here! – WallyWest – 2016-09-26T04:24:51.853

1XOR?! I couldn't have thought of that. That being said, sadly, using XOR makes my code longer :P – JungHwan Min – 2016-09-26T05:13:27.920

For i?p^(p=c)||p:c can you use i&&p^(p=c)||c? – Neil – 2016-09-26T13:50:15.623

@Neil Thanks, I think that will work! – ETHproductions – 2016-09-26T14:30:01.267

2

Ruby, 134 101 bytes

Using JHM's modulo trick.

->a{b=*a
(0..8).map{|i|[" "*i,a=a.each_cons(2).map{|x,y|b<<n=3-(x+y)%3
n}]*" "}<<"%19d"%b.reduce(:+)}

See it on eval.in: https://eval.in/649993

Jordan

Posted 2016-09-26T00:14:09.303

Reputation: 5 001

2

CJam,  44  40 bytes

l~{S*\_S*\2ew{:+3%3^}%2$N@}A%_s:~:+sJSe[

Try it online!

Explanation

l~       e# Read and evaluate input.
{        e# Map this block over i in the range [0 1 ... 9].
  S*     e#   Get a string of i spaces (the indentation).
  \_     e#   Swap with the current line of trits and duplicate it.
  S*     e#   Join the trits with spaces.
  \2ew   e#   Swap with the other copy of the trits and get all consecutive pairs.
  {      e#   Map this block over the pairs...
    :+   e#     Sum the pair.
    3%   e#     Modulo 3.
    3^   e#     XOR 3.
         e#     This expression (x+y)%3 ^ 3 computes the required mapping.
  }%     e#   Now this is the next line.
  2$     e#   Copy the indentation (to pad the lines to equal length).
  N      e#   Push a linefeed.
  @      e#   Pull up the next line.
}A%      e# The result of this is a nested array whose string representation is
         e# the required triangle.
_s       e# Duplicate and flatten into a string.
:~       e# Eval each character which gives a list of all the trits.
:+       e# Sum that.
s        e# Turn the sum into a string.
JSe[     e# Left-pad it with spaces to width 19.

Martin Ender

Posted 2016-09-26T00:14:09.303

Reputation: 184 808

As always, very impressive! You're in the lead so far! – WallyWest – 2016-09-26T07:53:43.567

1@WallyWest Thanks. :) Just wait Pyth, Jelly and MATL. ;) – Martin Ender – 2016-09-26T07:54:14.023

Actually, I'm curious to know what the GolfScript solution will look like... ;) – WallyWest – 2016-09-26T07:58:51.037

Oh, anyone up to posting an SQL solution? ;) – WallyWest – 2016-09-26T07:59:29.890

1

Python 2, 164 bytes

A relatively simple iterative solution.

L=input()
s=0
for i in range(len(L)):
    print" "*-~i+" ".join(`L`[1::3]);s+=sum(L);N=L;L=[]
    for a,b in zip(N,N[1:]):L+=[list({1,2,3}-{a,b}),[a]][a==b]
print"%19s"%s

Try it online

mbomb007

Posted 2016-09-26T00:14:09.303

Reputation: 21 944

1

PHP, 143 Bytes

<?for($t=$_GET[t];$i<181;$s+=$v,$i+=2)$t[$i+20]=($v=$t[$i])*($z=$t[$i+2])>0&$i!=18?($v+$z)%3^3:" ";echo chunk_split($t.str_pad($s,8," ",0),19);

Jörg Hülsermann

Posted 2016-09-26T00:14:09.303

Reputation: 13 026

0

JavaScript (ES6), 112 100 96 bytes

Takes an array as input and recursively builds a comma-separated triangle.

f=(s,p=`
`,S=0)=>p+(s[0]?s+f(s.map((v,i)=>(S+=v,v^s[i-1]||v)).slice(1),p+' ',S):(p+S).slice(-9))

console.log(f([1,2,3,3,1,3,1,3,1,2])); // reference example
console.log(f([3,3,2,1,3,1,2,1,2,1])); // random example
console.log(f([1,1,1,1,1,1,1,1,1,1])); // all ones (test case for sum < 100)

Arnauld

Posted 2016-09-26T00:14:09.303

Reputation: 111 334