4
votes

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.

1
Welcome to Stack Overflow. We can give you better answers if you specify which implementation and version of APL you use.Adám
Your matrix has trailing spaces. Is this intentional?Adám

1 Answers

5
votes

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!