0

I am currently working on finding a palindrome of made from multiplying numbers of length 3 together (from 900 to 1000). I am able to generate a table of palindromes in binary (1/0). However, the compress function (/) is giving me an error regarding storage. I am not sure why compressing the given binary table would cause such an issue.

new_set ← (900 + ⍳100)
{(⊃⍵)≡⌽⊃⍵}¨ ⊂∘⍕¨ (new_set ∘.× new_set)
{(⊃⍵)≡⌽⊃⍵}¨ ⊂∘⍕¨ (new_set ∘.× new_set) / ∘⍕¨(new_set ∘.× new_set)
WS FULL: Maximum workspace is 512 kilobytes.

Edit: Changing new_set to (⍳10) produces the same solution on the third line as the line before it (binary).. Really need help with the compress function. Any help greatly appreciated.

ArbIn
  • 43
  • 5
  • you can set MAXWS to a much larger value in configuration file, see the manual section corresponding to your platform. – LdBeth Oct 17 '22 at 21:13
  • https://help.dyalog.com/latest/Content/UserGuide/Installation%20and%20Configuration/Configuration%20Parameters.htm#Configuration_Parameter_Table – LdBeth Oct 17 '22 at 21:15
  • Alright. I thought there may be a nice way that I can run the command it on https://tryapl.org. However, their online web server may not allow the changes. Thank you, @LdBeth. – ArbIn Oct 17 '22 at 21:29
  • I actually tried the function on a smaller subset of new_set and it produces the same binary table... Ugh – ArbIn Oct 18 '22 at 00:01

2 Answers2

2

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

Remember, in APL every function is evaluated right-associatively. This means that the left argument to /∘⍕¨ above is actually (new_set ∘.× new_set). You will need to use parenthesis to force the order of evaluation you want. Better yet, try to find a different spelling that avoids parentheses altogether.

However, the Each (¨) here means that /∘⍕ is getting called for every pair of items in new_set ∘.× new_set, meaning that for every element of new_set left argument to / ends up being some number on the order of 500,000 and the right argument a string representation of that number. In other words, you're replicating each digit ~500,000 times, for every one of these numbers. That's roughly 300e9 = 6×500,000×100,000 bytes or 300GB. Even my local machine with a 12GB workspace limit can't handle that!

At this point, I would like to give you some small, pointed tips to fix the above issue, but honestly, I'm not quite sure what your intent is in the above snippet of code.

Check out the docs for Replicate, and notice that the left argument needs to be a vector. However, your left argument is a 100 by 100 array. If you don't actually need the shape information anymore, then Enlisting () the arguments first might get you where you want.

B. Wilson
  • 66
  • 3
  • Thanks again, @B. Wilson!! Check this out: ∪({(⊃⍵)≡⌽⊃⍵}¨ ⊂∘⍕¨ (new_set ∘.× new_set)) / ∘⍕¨(new_set ∘.× new_set). This is "sorta-exactly" what I need.. It's not super pretty, but it definitely does the job. Enlisting makes it crunched together... But this uniqueness (u), although not aesthetic, does the job. Do you think that will suffice? – ArbIn Oct 18 '22 at 02:03
  • Nice! Glad you were able to wrangle something out. About using Unique (`∪`), I don't think it's too bad. As awagga points out below, since multiplication is commutative, any solution using outer product will have to deal with duplicates somehow, and Unique is an obvious, straightforward way to eliminate those. If it suffices it suffices! This particular solution doesn't scale all that well to larger datasets, but hey, this problem doesn't use a large dataset, so we're all good. – B. Wilson Oct 18 '22 at 07:09
1

Expanding on the answer by B. Wilson,

So, the problem - We want to return the palindromes found in a multiplication table of the integers in the range of 900 to 1000.

We can start with the range:

   n ← (900 + ⍳100)

Straight-forward and as stated APL is right-associative, meaning functions apply to everything on the right, and one argument to the left. Given that, those parenthesis are superfluous and we can remove them.

Next, to produce the table:

   n ∘.× n

Great. Everyone loves outer product and as this problem is inherently O(n^2), there's not much we can do to avoid WS FULLs on larger arguments.

Here's where a subtly is introduced - do we want the unique multiplications? For example, should we include 901×901, as well as both 902×901 and 901×902, if not - there are a few things we can do to reduce space.

   ⊃,/(1↓n)×,\¯1↓n

This expression is one approach to avoid precisely those cases.

Now for the palindromes. In APL, as identified, it's idiomatic to use boolean masks to filter elements.

Your approach was

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

Works well! I'll note that the ⊂ is superfluous as we immediately perform the inverse operation upon function invocation.

So, we can write:

   {⍵≡⌽⍵}∘⍕¨

Finally, the filter. You noticed that each element of the mask isn't paired up with each element of the table. Right, For non-singleton masks / will filter along major cells. For example:

   1 0 1 / 3 3⍴⍳9
1 3
4 6
7 9      

So, to get around your issue, we can ravel (flatten) both sides beforehand:

   {(,{⍵≡⌽⍵}∘⍕¨⍵)/,⍵} n ∘.× n

The complete solution! I'll posit some alternatives (minor changes) for investigation.

   {⍵/⍨(≡∘⌽⍨⍕)¨⍵}⊃,/(1↓n)×,\¯1↓n
   {⍵/⍨⍥,(≡∘⌽⍨⍕)¨⍵}∘.×⍨
  • Nice. I've tried your solution and it works! The very last one, however, is giving me problems. I entered ({⍵/⍨⍥,(≡∘⌽⍨⍕)¨⍵}∘.×⍨) / ∘⍕¨(new_set ∘.× new_set). TryAPL is giving me a "Domain Error" error. However, I have went ahead and accepted your solution. Thank you! – ArbIn Oct 18 '22 at 14:56