Provided by: libmath-planepath-perl_129-1_all bug

NAME

       Math::PlanePath::PyramidRows -- points stacked up in a pyramid

SYNOPSIS

        use Math::PlanePath::PyramidRows;
        my $path = Math::PlanePath::PyramidRows->new;
        my ($x, $y) = $path->n_to_xy (123);

DESCRIPTION

       This path arranges points in successively wider rows going upwards so as to form an
       upside-down pyramid.  The default step is 2, ie. each row 2 wider than the preceding, an
       extra point at the left and the right,

           17  18  19  20  21  22  23  24  25       4
               10  11  12  13  14  15  16           3     step => 2
                    5   6   7   8   9               2
                        2   3   4                   1
                            1                  <- Y=0

           -4  -3  -2  -1  X=0  1   2   3   4 ...

       The right end N=1,4,9,16,etc is the perfect squares.  The vertical 2,6,12,20,etc at x=-1
       is the pronic numbers s*(s+1), half way between those successive squares.

       The step 2 is the same as the "PyramidSides", "Corner" and "SacksSpiral" paths.  For the
       "SacksSpiral", spiral arms going to the right correspond to diagonals in the pyramid, and
       arms to the left correspond to verticals.

   Step Parameter
       A "step" parameter controls how much wider each row is than the preceding, to make wider
       pyramids.  For example step 4

           my $path = Math::PlanePath::PyramidRows->new (step => 4);

       makes each row 2 wider on each side successively

          29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45      4
                16 17 18 19 20 21 22 23 24 25 26 27 28            3
                       7  8  9 10 11 12 13 14 15                  2
                             2  3  4  5  6                        1
                                   1                        <-  Y=0

                -6 -5 -4 -3 -2 -1 X=0 1  2  3  4  5  6 ...

       If the step is an odd number then the extra is at the right, so step 3 gives

           13  14  15  16  17  18  19  20  21  22       3
                6   7   8   9  10  11  12               2
                    2   3   4   5                       1
                        1                         <-  Y=0

           -3  -2  -1  X=0  1   2   3   4 ...

       Or step 1 goes solely to the right.  This is equivalent to the Diagonals path, but columns
       shifted up to make horizontal rows.

           11  12  13  14  15         4
            7   8   9  10             3       step => 1
            4   5   6                 2
            2   3                     1
            1                   <-  Y=0

           X=0  1   2   3   4 ...

       Step 0 means simply a vertical, each row 1 wide and not increasing.  This is consistent
       but unlikely to be much use.  The Rows path with "width" 1 does this too.

            5         4
            4         3     step => 0
            3         2
            2         1
            1    <- Y=0

           X=0

       Various number sequences fall in regular patterns positions depending on the step.  Large
       steps are not particularly interesting and quickly become very wide.  A limit might be
       desirable in a user interface, but there's no limit in the code as such.

   Align Parameter
       An optional "align" parameter controls how the points are arranged relative to the Y axis.
       The default shown above is "centre".

       "right" means points to the right of the axis,

           align=>"right"

           26  27  28  29  30  31  32  33  34  35  36        5
           17  18  19  20  21  22  23  24  25                4
           10  11  12  13  14  15  16                        3
            5   6   7   8   9                                2
            2   3   4                                        1
            1                                            <- Y=0

           X=0  1   2   3   4   5   6   7   8   9  10

       "left" is similar but to the left of the Y axis, ie. into negative X.

           align=>"left"

           26  27  28  29  30  31  32  33  34  35  36        5
                   17  18  19  20  21  22  23  24  25        4
                           10  11  12  13  14  15  16        3
                                    5   6   7   8   9        2
                                            2   3   4        1
                                                    1    <- Y=0

           -10 -9  -8  -7  -6  -5  -4  -3  -2  -1  X=0

       The step parameter still controls how much longer each row is than its predecessor.

   N Start
       The default is to number points starting N=1 as shown above.  An optional "n_start" can
       give a different start, in the same rows sequence.  For example to start at 0,

           n_start => 0

           16 17 18 19 20 21 22 23 24        4
               9 10 11 12 13 14 15           3
                  4  5  6  7  8              2
                     1  2  3                 1
                        0                <- Y=0
           --------------------------
           -4 -3 -2 -1 X=0 1  2  3  4

   Step 3 Pentagonals
       For step=3 the pentagonal numbers 1,5,12,22,etc, P(k) = (3k-1)*k/2, are at the rightmost
       end of each row.  The second pentagonal numbers 2,7,15,26, S(k) = (3k+1)*k/2 are the
       vertical at x=-1.  Those second numbers are obtained by P(-k), and the two together are
       the "generalized pentagonal numbers".

       Both these sequences are composites from 12 and 15 onwards, respectively, and the
       immediately preceding P(k)-1, P(k)-2, and S(k)-1, S(k)-2 are too.  They factorize simply
       as

           P(k)   = (3*k-1)*k/2
           P(k)-1 = (3*k+2)*(k-1)/2
           P(k)-2 = (3*k-4)*(k-1)/2
           S(k)   = (3*k+1)*k/2
           S(k)-1 = (3*k-2)*(k+1)/2
           S(k)-2 = (3*k+4)*(k-1)/2

       Plotting the primes on a step=3 "PyramidRows" has the second pentagonal S(k),S(k)-1,S(k)-2
       as a 3-wide vertical gap of no primes at X=-1,-2,-3.  The the plain pentagonal
       P(k),P(k-1),P(k)-2 are the endmost three N of each row non-prime.  The vertical is much
       more noticeable in a plot.

              no primes these three columns         no primes these end three
                except the low 2,7,13                     except low 3,5,11
                      |  |  |                                /  /  /
            52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
               36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
                  23 24 25 26 27 28 29 30 31 32 33 34 35
                     13 14 15 16 17 18 19 20 21 22
                         6  7  8  9 10 11 12
                            2  3  4  5
                               1
            -6 -5 -4 -3 -2 -1 X=0 1  2  3  4  5  6  7  8  9 10 11 ...

       With align="left" the end values can be put into columns,

                                       no primes these end three
           align => "left"                  except low 3,5,11
                                                   |  |  |
           36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51        5
                    23 24 25 26 27 28 29 30 31 32 33 34 35        4
                             13 14 15 16 17 18 19 20 21 22        3
                                       6  7  8  9 10 11 12        2
                                                2  3  4  5        1
                                                         1    <- Y=0
                     ... -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 X=0

       In general a constant offset S(k)-c is a column and from P(k)-c is a diagonal sloping up
       dX=2,dY=1 right.  The simple factorizations above using the roots of the quadratic P(k)-c
       or S(k)-c is possible whenever 24*c+1 is a perfect square.  This means the further columns
       S(k)-5, S(k)-7, S(k)-12, etc also have no primes.

       The columns S(k), S(k)-1, S(k)-2 are prominent because they're adjacent.  There's no other
       adjacent columns of this type because the squares after 49 are too far apart for 24*c+1 to
       be a square for successive c.  Of course there could be other reasons for other columns or
       diagonals to have few or many primes.

FUNCTIONS

       See "FUNCTIONS" in Math::PlanePath for behaviour common to all path classes.

       "$path = Math::PlanePath::PyramidRows->new ()"
       "$path = Math::PlanePath::PyramidRows->new (step => $integer, align => $str, n_start =>
       $n)"
           Create and return a new path object.  The default "step" is 2.  "align" is a string,
           one of

               "centre"    the default
               "right"     points aligned right of the Y axis
               "left"      points aligned left of the Y axis

           Points are always numbered from left to right in the rows, the alignment changes where
           each row begins (or ends).

       "($x,$y) = $path->n_to_xy ($n)"
           Return the X,Y coordinates of point number $n on the path.

           For "$n <= 0" the return is an empty list since the path starts at N=1.

       "$n = $path->xy_to_n ($x,$y)"
           Return the point number for coordinates "$x,$y".  $x and $y are each rounded to the
           nearest integer, which has the effect of treating each point in the pyramid as a
           square of side 1.  If "$x,$y" is outside the pyramid the return is "undef".

       "($n_lo, $n_hi) = $path->rect_to_n_range ($x1,$y1, $x2,$y2)"
           The returned range is exact, meaning $n_lo and $n_hi are the smallest and biggest in
           the rectangle.

   Descriptive Methods
       "$x = $path->sumxy_minimum()"
       "$x = $path->sumxy_maximum()"
           Return the minimum or maximum values taken by coordinate sum X+Y reached by integer N
           values in the path.  If there's no minimum or maximum then return "undef".

           The path is right and above the X=-Y diagonal, thus giving a minimum sum, in the
           following cases.

               align      condition for sumxy_minimum=0
               ------     -----------------------------
               centre              step <= 3
               right               always
               left                step <= 1

       "$x = $path->diffxy_minimum()"
       "$x = $path->diffxy_maximum()"
           Return the minimum or maximum values taken by coordinate difference X-Y reached by
           integer N values in the path.  If there's no minimum or maximum then return "undef".

           The path is left and above the X=Y leading diagonal, thus giving a minimum X-Y
           difference, in the following cases.

               align      condition for diffxy_minimum=0
               ------     -----------------------------
               centre              step <= 2
               right               step <= 1
               left                always

OEIS

       Entries in Sloane's Online Encyclopedia of Integer Sequences related to this path include

           <http://oeis.org/A023531> (etc)

           step=1
             A002262    X coordinate, runs 0 to k
             A003056    Y coordinate, k repeated k+1 times
             A051162    X+Y sum
             A025581    Y-X diff, runs k to 0
             A079904    X*Y product
             A069011    X^2+Y^2, n_to_rsquared()
             A080099    X bitwise-AND Y
             A080098    X bitwise-OR  Y
             A051933    X bitwise-XOR Y
             A050873    GCD(X+1,Y+1) greatest common divisor by rows
             A051173    LCM(X+1,Y+1) least common multiple by rows

             A023531    dY, being 1 at triangular numbers (but starting n=0)
             A167407    dX-dY, change in X-Y (extra initial 0)
             A129184    turn 1=left, 0=right or straight

             A079824    N total along each opposite diagonal
             A000124    N on Y axis (triangular+1)
             A000217    N on X=Y diagonal, extra initial 0
           step=1, n_start=0
             A109004    GCD(X,Y) greatest common divisor starting (0,0)
             A103451    turn 1=left or right,0=straight, but extra initial 1
             A103452    turn 1=left,0=straight,-1=right, but extra initial 1

           step=2
             A196199    X coordinate, runs -n to +n
             A000196    Y coordinate, n appears 2n+1 times
             A053186    X+Y, being distance to next higher square
             A010052    dY,  being 1 at perfect square row end
             A000290    N on X=Y diagonal, extra initial 0
             A002522    N on X=-Y North-West diagonal (start row), Y^2+1
             A004201    N for which X>=0, ie. right hand half
             A020703    permutation N at -X,Y
           step=2, n_start=0
             A005563    N on X=Y diagonal, Y*(Y+2)
             A000290    N on X=-Y North-West diagonal (start row), Y^2
           step=2, n_start=2
             A059100    N on north-west diagonal (start each row), Y^2+2
             A053615    abs(X), runs k..0..k
           step=2, align=right, n_start=0
             A196199    X-Y, runs -k to +k
             A053615    abs(X-Y), runs k..0..k
           step=2, align=left, n_start=0
             A005563    N on Y axis, Y*(Y+2)

           step=3
             A180447    Y coordinate, n appears 3n+1 times
             A104249    N on Y axis, Y*(3Y+1)/2+1
             A143689    N on X=-Y North-West diagonal
           step=3, n_start=0
             A005449    N on Y axis, second pentagonals Y*(3Y+1)/2
             A000326    N on diagonal north-west, pentagonals Y*(3Y-1)/2

           step=4
             A084849    N on Y axis
             A001844    N on X=Y diagonal (North-East)
             A058331    N on X=-Y North-West diagonal
             A221217    permutation N at -X,Y
           step=4, n_start=0
             A014105    N on Y axis, the second hexagonal numbers
             A046092    N on X=Y diagonal, 4*triangular numbers
           step=4, align=right, n_start=0
             A060511    X coordinate, amount n exceeds hexagonal number
             A000384    N on Y axis, the hexagonal numbers
             A001105    N on X=Y diagonal, 2*squares

           step=5
             A116668    N on Y axis

           step=6
             A056108    N on Y axis
             A056109    N on X=Y diagonal (North-East)
             A056107    N on X=-Y North-West diagonal

           step=8
             A053755    N on X=-Y North-West diagonal

           step=9
             A006137    N on Y axis
             A038764    N on X=Y diagonal (North-East)

SEE ALSO

       Math::PlanePath, Math::PlanePath::PyramidSides, Math::PlanePath::Corner,
       Math::PlanePath::SacksSpiral, Math::PlanePath::MultipleRings

       Math::PlanePath::Diagonals, Math::PlanePath::DiagonalsOctant, Math::PlanePath::Rows

HOME PAGE

       <http://user42.tuxfamily.org/math-planepath/index.html>

LICENSE

       Copyright 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Kevin Ryde

       This file is part of Math-PlanePath.

       Math-PlanePath is free software; you can redistribute it and/or modify it under the terms
       of the GNU General Public License as published by the Free Software Foundation; either
       version 3, or (at your option) any later version.

       Math-PlanePath is distributed in the hope that it will be useful, but WITHOUT ANY
       WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
       PURPOSE.  See the GNU General Public License for more details.

       You should have received a copy of the GNU General Public License along with Math-
       PlanePath.  If not, see <http://www.gnu.org/licenses/>.