---
name: "Math::PlanePath::PyramidRows"
section: "3pm"
platform: "linux"
package: "libmath-planepath-perl"
version: "129-1"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/Math::PlanePath::PyramidRows"
---

# Math::PlanePath::PyramidRows(3pm)

## 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/\>.
