Search code examples
palindromeapl

APL. How to find palindrome numbers in a given product list


The particular question asks to find all palindrome numbers between 900 and 1000.

new_set ← (900 + ⍳100)
901, 902, 903, 904, ..., 999, 1000

⍕¨(new_set ∘.× new_set)
{⍵≡⌽⍵} ⍕¨(new_set ∘.× new_set)

The first line creates the new set of numbers.

The second line multiplies all numbers in new_set by every other number including itself. Creates a sort of outer product multiplication table, then converts the numbers into strings.

Last line attempts to find all palindromes, but fails and returns 0..

Any and all help is appreciated!


Solution

  • ⍕¨(new_set ∘.× new_set) has shape 100 100, and Match () compares entire arrays, so your final dfn there is comparing a 100 by 100 array against the Reverse () of the whole array.

    What it looks like you're wanting is to reverse individual strings. Trying to copy your style, we get something like this:

    {(⊃⍵)≡⌽⊃⍵}¨ ⊂∘⍕¨ (new_set ∘.× new_set)
    

    Notice the double usage of Each (¨) and needing to Enclose () the strings just for the second Each and then immediately Disclose () in the dfn. This should probably feel dirty.

    We can do better.

    First, why not merge the two Each iterations?

    {(⊃⍵)≡⌽⊃⍵}∘⊂∘⍕¨ (new_set ∘.× new_set)
    

    But, in fact, Outer Product (∘.×) is already operating on exactly the items we want, so it make sense to just do everything there:

    new_set ∘.{(⊢≡⌽)⍕⍺×⍵} new_set
    

    N.B. Instead of repeating new_set on the left and right, it's probably more idiomatic to use Commute (). I'll also throw in another spelling of (⊢≡⌽), just for fun:

    ∘.{≡∘⌽⍨⍕⍺×⍵}⍨ new_set
    

    Turning this binary mask into the actual set of palindromes is pretty straightforward, so I'll not spoil that fun.