# Fully-palindromic triangles

## Jelly, ~~14~~ 12 bytes

```
J’Æ²œṗZ⁻¦µU⁼
```

Try it online!

### Background

We start by looking at the 0-based indices of the input string.

```
H H e H H e l e H H e l l l e H H e l l o l l e H
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
```

To get the rows of the triangle, we can split the string before the indices **1**, **1 + 3 = 4**, **1 + 3 + 5 = 9**, and **1 + 3 + 5 + 7 = 16**. Since **(n + 1)² = n² + (2n + 1)**, these sums are precisely the positive, perfect squares in the index list. If we also split the string before **0**, this is as simple as splitting before all 0-based indices that are perfect squares.

After splitting, we get the following strings.

```
""
"H"
"HeH"
"HeleH"
"HellleH"
"HellolleH"
```

Next, we replace the empty string at the beginning with all the characters in the first column.

```
"HHHHH"
"H"
"HeH"
"HeleH"
"HellleH"
"HellolleH"
```

The task is now reduced to checking whether reversing all strings yields the same string array.

### How it works

First `J`

generates all 1-based indices of the input string `J`

, then decrements them with `’`

to yield all 0-based indices. `Æ²`

tests all 0-based indices for squareness. For our example from above, this yields the following Boolean array.

```
1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
```

Next, we call `œṗ`

to partition the input string, e.g.,

```
H H e H H e l e H H e l l l e H H e l l o l l e H
```

before all **1**'s (actually, all truthy elements). For our example, this yields the following string array.

```
['',
'H',
'HeH',
'HeleH',
'HellleH',
'HellolleH'
]
```

`Z⁻¦`

is arguably the most interesting part of this answer. Let's analyze the more straightforward `Z1¦`

first.

`¦`

is the *sparse* quick. It consumes two links from the stack, specifically `1`

and `Z`

in this case. First `Z`

is applied to its argument: the string array from before. `Z`

is the *zip* atom and reads the string array / 2D character array by columns, yielding

```
['HHHHH',
'eeee',
'Hlll',
'ell',
'Hlo',
'el',
'Hl',
'e',
'H'
]
```

What used to be left side of the input string and the first column of the string array now becomes the first *string*.

Now `¦`

peeks at `1`

and finds a single index: **1**. Thus the first string in the original string array is replaced with the first string in the return value of `Z`

; strings at other indices remain unaffected.

```
['HHHHH',
'H',
'HeH',
'HeleH',
'HellleH',
'HellolleH'
]
```

Let's call this array **A**.

We used `Z⁻¦`

instead of `Z1¦`

, but this makes no difference: `⁻`

compares the string array with the input string for inequality, yielding **1** since they're not equal. The difference between the two is that `Z⁻¦`

is dyadic because `⁻`

is, allowing us to write `œṗZ⁻¦`

instead of `œṗ¹Z1¦`

. This is because a dyad (`œṗ`

) followed by a monad (`œṗ¹Z1¦`

) is a *fork* (the monad is applied to the chain's argument / the input string, and the returned value is passed as the right argument to `œṗ`

), while a dyad followed by another dyad (or at the end of the chain) is a *hook*, i.e., its right argument is the chain's argument.

All that's left to do is check for palindromicness. `µ`

begins a new (monadic) chain who's argument is **A**. The *upend* atom `U`

reverses all strings in **A** (but not **A** itself), then `⁼`

compares the result with **A** for equality. The returned Boolean **1** indicates a fully-palindromic triangle; other strings would return **0**.

## Japt, ~~25~~ ~~21~~ 17 bytes

*Saved 2 bytes thanks to @obarakon*

```
ò@°T ¬v1
pUmg)eêP
```

Test it online!

### How it works

```
ò@ ° T ¬ v1 // Implicit: U = input string, T = 0
UòXY{++T q v1} // First line; reset U to the result of this line.
UòXY{ } // Partition U at indices where
++T q // the square root of T incremented
v1 // is divisible by 1.
// This breaks U at square indices, giving rows of 1, 3, 5, ... chars.
pUmg)eêP
UpUmg)eêP
Umg // Take the first char of every item of U.
Up ) // Append this to U.
e // Check that every item in the resulting array
êP // is a palindrome.
// Implicit: output result of last expression
```

Note that we don't need to check *both* sides; if the sides are not the same, At least one of the rows is not a palindrome.

## 05AB1E, 18 bytes

```
gÅÉ£õÜÐíQs€¬āÈÏÂQ*
```

Uses the **05AB1E** encoding. Try it online!