5

I can't figure out how to take a matrix and count the amount of the alphanumerical values for each row. I will only be taking in matrices with the values I'm counting. For example, if I got:

ABA455  
7L9O36G                                 
DZLFPEI

I would get something like A:2 B:1 4:1 5:2 for the first row and each row would be counted independently. I would most like to understand the operators used if you could please explain them too. Thank you.

Adám
  • 6,573
  • 20
  • 37
JTP
  • 85
  • 4
  • 1
    Welcome to Stack Overflow. We can give you better answers if you specify which implementation and version of APL you use. – Adám Oct 14 '20 at 06:53
  • Your matrix has trailing spaces. Is this intentional? – Adám Oct 14 '20 at 06:54

1 Answers1

6

The following should work in any mainstream APL implementation.

Let's start with a simple vector of characters:

      m ← 3 7⍴'ABA455 7L9O36GDZLFPEI'
      v ← m[1;]
      v
ABA455 

We can find the unique characters by filtering to keep only elements that have the same index as the first occurrence of themselves:

      v ⍳ v
1 2 1 4 5 5 7
      ⍳ ⍴ v
1 2 3 4 5 6 7
      ( v ⍳ v ) = ⍳ ⍴ v
1 1 0 1 1 0 1
      ⎕ ← unique ← ( (v ⍳ v) = ⍳ ⍴ v ) / v
AB45 

Now we compare the unique elements to every element:

      unique ∘.= v
1 0 1 0 0 0 0
0 1 0 0 0 0 0
0 0 0 1 0 0 0
0 0 0 0 1 1 0
0 0 0 0 0 0 1

Summing this table horizontally gives us the occurrence count for each unique element:

      +/ unique ∘.= v
2 1 1 2 1

Now we just need to pair up the unique elements with their respective counts:

       unique ,[1.5] +/ unique ∘.= v
A 2
B 1
4 1
5 2
  1

Let's put that into a utility function:

      ∇ c ← Counts v; u
        u ← ( (v ⍳ v) = ⍳ ⍴ v ) / v
        c ← u ,[1.5] +/ u ∘.= v
      ∇ 
      Counts v
A 2
B 1
4 1
5 2
  1

Now we need to apply this function on each row of the matrix. We start by splitting the matrix into a vector of vectors:

      ⊂[2] m
┌───────┬───────┬───────┐
│ABA455 │7L9O36G│DZLFPEI│
└───────┴───────┴───────┘

Then we apply the utility function to each vector:

      Counts¨ ⊂[2] m
┌───┬───┬───┐
│A 2│7 1│D 1│
│B 1│L 1│Z 1│
│4 1│9 1│L 1│
│5 2│O 1│F 1│
│  1│3 1│P 1│
│   │6 1│E 1│
│   │G 1│I 1│
└───┴───┴───┘

Try it online!


If you're using Dyalog APL, then the Key operator () is very much what you need:

      {⍺ ⍵}⌸ 'ABA455'
┌─┬───┐
│A│1 3│
├─┼───┤
│B│2  │
├─┼───┤
│4│4  │
├─┼───┤
│5│5 6│
└─┴───┘

It takes a single operand and calls it once per unique value, with the specific value as left argument and the list of occurrence indices as right argument. However, we're not interested in the actual occurrences, only in their counts:

      {⍺ (≢⍵)}⌸ 'ABA455'
A 2
B 1
4 1
5 2

Now we simply have to apply this function on each row. We can do this by splitting the matrix and applying the function with Each:

      {⍺ (≢⍵)}⌸¨ ↓ m
┌───┬───┬───┐
│A 2│7 1│D 1│
│B 1│L 1│Z 1│
│4 1│9 1│L 1│
│5 2│O 1│F 1│
│  1│3 1│P 1│
│   │6 1│E 1│
│   │G 1│I 1│
└───┴───┴───┘

Try it online!

Adám
  • 6,573
  • 20
  • 37
  • I wonder about why you defined `Counts` as a tradfn and not a dfn? Are dfns particular to Dyalog APL? – RGS Oct 14 '20 at 08:32
  • 1
    @RGS They are only fully implemented in Dyalog APL, NARS2000 and newer implementations. Though GNU APL has them, they are very limited in that they do not allow multiple statements, nor localise variables upon assignment. Major implementations like APL2, APL+Win, and APLX do not support dfns. – Adám Oct 14 '20 at 08:36
  • Hey Adám, I am using Dyalog APL and no the trailing spaces were not intentional. Thanks a lot this has helped me tremendously. My new issue is that I can get to the point where I have them all counted but it stores the result in a nested array but each one is a scalar? I would like to be able to use the results of each row to manipulate it further. So once I get the number of repeats I need to be able to multiply the number of repeats and a number corresponding with each alphanumerical value but I can't seem to manipulate the results. Thanks again for helping. Hope to be hearing from you soon. – JTP Oct 14 '20 at 23:46