Visualize a Difference Pyramid

15

2

A difference pyramid is a pyramid where each new diagonal is the absolute value of the differences between the elements of the last diagonal. For example, if we start with the array

2 5 4 9 3 4

Now, we arrange these in a diagonal column:

     2
      5
       4
        9
         3
          4

Now, we fill in the next diagonal. The absolute differences between the consecutive elements of this array are:

3 1 5 6 1

So that is our next diagonal.

     2
    3 5
     1 4
      5 9
       6 3
        1 4

Repeat until the pyramid is filled in:

     2
    3 5
   2 1 4
  2 4 5 9
 1 3 1 6 3
0 1 4 5 1 4

The Challenge

Given a list of positive integers in the range [0, 9], generate this ASCII-art representation of the difference pyramid for that particular array. The input is guaranteed to contain at least two elements. You may take these numbers in any reasonable format. (Array/list/whatever you call it, a string, command line arguments, etc.) Trailing spaces on each line and up to one trailing newline are allowed.

Test IO

[1, 2, 3, 4, 5, 6, 7, 8, 9]

        1
       1 2
      0 1 3
     0 0 1 4
    0 0 0 1 5
   0 0 0 0 1 6
  0 0 0 0 0 1 7
 0 0 0 0 0 0 1 8
0 0 0 0 0 0 0 1 9

[4, 7]

 4
3 7

[3, 3, 3]

  3
 0 3
0 0 3

[1, 3, 6, 3, 4, 9]

     1
    2 3
   1 3 6
  1 0 3 3
 1 2 2 1 4
1 0 2 4 5 9


[8, 7, 3, 2, 4, 5, 9, 1, 6]

        8
       1 7
      3 4 3
     0 3 1 2
    2 2 1 2 4
   0 2 0 1 1 5
  0 0 2 2 3 4 9
 1 1 1 1 1 4 8 1
0 1 0 1 0 1 3 5 6

As usual, this is code-golf, so standard loopholes apply, and shortest answer in bytes wins!


Inspired by this OEIS and this conjecture.

James

Posted 2016-07-19T00:02:36.660

Reputation: 54 537

Answers

8

Jelly, 16 bytes

IA$ṖпUṚz”@ṚGḟ”@

Try it online!

Background

Generating the differences is quite straightforward. For input

[1, 2, 3, 4, 5, 6, 7, 8, 9]

IA$Ṗп (absolute value of increments while there is more than one element) yields the following ragged 2D array.

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 1, 1, 1, 1, 1, 1, 1]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0]
[0, 0]
[0]

U reverses the order of the columns and the order of the rows, yielding the following.

[0]
[0, 0]
[0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 1, 1, 1]
[9, 8, 7, 6, 5, 4, 3, 2, 1]

Now, we transpose rows and columns with z”@, which pads all rows to the same length before transposing. The result is the following.

[0, 0, 0, 0, 0, 0, 0, 1, 9]
[@, 0, 0, 0, 0, 0, 0, 1, 8]
[@, @, 0, 0, 0, 0, 0, 1, 7]
[@, @, @, 0, 0, 0, 0, 1, 6]
[@, @, @, @, 0, 0, 0, 1, 5]
[@, @, @, @, @, 0, 0, 1, 4]
[@, @, @, @, @, @, 0, 1, 3]
[@, @, @, @, @, @, @, 1, 2]
[@, @, @, @, @, @, @, @, 1]

Reversing the rows gives

[@, @, @, @, @, @, @, @, 1]
[@, @, @, @, @, @, @, 1, 2]
[@, @, @, @, @, @, 0, 1, 3]
[@, @, @, @, @, 0, 0, 1, 4]
[@, @, @, @, 0, 0, 0, 1, 5]
[@, @, @, 0, 0, 0, 0, 1, 6]
[@, @, 0, 0, 0, 0, 0, 1, 7]
[@, 0, 0, 0, 0, 0, 0, 1, 8]
[0, 0, 0, 0, 0, 0, 0, 1, 9]

To turn the 2D array into a whitespace-separated string, we use the built-in grid atom (G). It joins columns by spaces and rows by linefeeds, yielding the following result.

@ @ @ @ @ @ @ @ 1
@ @ @ @ @ @ @ 1 2
@ @ @ @ @ @ 0 1 3
@ @ @ @ @ 0 0 1 4
@ @ @ @ 0 0 0 1 5
@ @ @ 0 0 0 0 1 6
@ @ 0 0 0 0 0 1 7
@ 0 0 0 0 0 0 1 8
0 0 0 0 0 0 0 1 9

All that's left to do is removing the padding character with ḟ”@, yielding

        1
       1 2
      0 1 3
     0 0 1 4
    0 0 0 1 5
   0 0 0 0 1 6
  0 0 0 0 0 1 7
 0 0 0 0 0 0 1 8
0 0 0 0 0 0 0 1 9

which is the desired output.

Dennis

Posted 2016-07-19T00:02:36.660

Reputation: 196 637

2

J, 46 42 39 36 bytes

(#\-#)|."_1#{.[:":@|./.<@#2&(|@-/\)]

A straight-forward implementation. Generates a table of successive differences between each pair and repeats it a number of times equal to the length of the input array. Then traverses each diagonal of that table to form the rows of the triangle. The rest is formatting the rows into a pyramid.

Usage

   f =: (#\-#)|."_1#{.[:":@|./.<@#2&(|@-/\)]
   f 2 5 4 9 3 4
     2     
    3 5    
   2 1 4   
  2 4 5 9  
 1 3 1 6 3 
0 1 4 5 1 4
   f 4 7
 4 
3 7
   f 8 7 3 2 4 5 9 1 6
        8        
       1 7       
      3 4 3      
     0 3 1 2     
    2 2 1 2 4    
   0 2 0 1 1 5   
  0 0 2 2 3 4 9  
 1 1 1 1 1 4 8 1 
0 1 0 1 0 1 3 5 6

Explanation

(#\-#)|."_1#{.[:":@|./.<@#2&(|@-/\)]  Input: list A
                         #            Get len(A)
                       <@             Box it
                                   ]  Get A
                          2&(     )   Repeat len(A) times on A initially
                          2      \      Get each iverlapping sublist of size 2
                                /       Reduce it using
                             |@-          The absolute value of the difference

                                      This will form a table where each row contains the
                                      successive differences
              [:     /.               Operate on the diagonals of that table
                   |.                 Reverse each diagonal
                ":@                   Format each into a string
           #                          Get len(A)
            {.                        Take that many from the strings of diagonals
 #\                                   Get the length of each prefix of A
                                      Makes the range [1, 2, ..., len(A)]
    #                                 Get len(A)
   -                                  Subtract the len(A) from each in the prefix range
                                      Makes [-len(A)+1, ..., -1, 0]
      |."_1                           Rotate each string left using each value
                                      A negative rotate left = rotate right
                                      Output the pyramid

miles

Posted 2016-07-19T00:02:36.660

Reputation: 15 654

2

CJam, 29 bytes

q~{_2ew::-:z}h]W%zzeeSff*W%N*

Try it online! (The first and last line enable a linefeed-separated test suite.)

This uses the triangle-rotation and layouting code from this answer and the triangle itself is generated with the same principle as in this answer.

Martin Ender

Posted 2016-07-19T00:02:36.660

Reputation: 184 808

1

Pyth, 22 bytes

jmX-jN_Pd;N;_.t_M.uaVt

Try it online!

Leaky Nun

Posted 2016-07-19T00:02:36.660

Reputation: 45 011

1

Python 3, 144 bytes

def f(x):
 y=[x]
 for i in range(len(x)-1):y+=[['']*-~i+[abs(y[i][j]-y[i][j+1])for j in range(i,len(y[i])-1)]]
 for i in zip(*y):print(*i[::-1])

A function that takes input of a list x via argument and prints the result to STDOUT.

How it works

The program takes input of a list x, and initialises a nested list y such that y[0] = x. The absolute differences for the last list in y (initially x) are then generated and appended as a list to y until a list of length 1 is reached; at each stage, the list is pre-padded with spaces such that all lists in y have the same length as x. Next, y is transposed, leaving it containing a tuple for each output line, but reversed. Each tuple in the transpose is unpacked, reversed and printed, leaving the difference pyramid on STDOUT.

Try it on Ideone

TheBikingViking

Posted 2016-07-19T00:02:36.660

Reputation: 3 674