How can I format a number vector and a string vector? (Dyalog APL)

Viewed 332

I've been studying APL only a few weeks but I really like it. I tried to write simple functions to practice what I learn. This one tells me how much money I'm left with next 13 months if I withdraw W every month from initial capital of T.

 R←T Money W
 M←1 2 3 4 5 6 7 8 9 10 11 12 13
 Months←'Nov' 'Dec' 'Jan' 'Feb' 'Mar' 'Apr' 'May' 'Jun' 'Jul' 'Aug' 'Sep' 'Oct' 'Nov'
 P←-/T(M×W)
 R←Months,P

This gives two correct numbers but I could not format them like

Nov....100,000
Dec.....97,000
Jan.....92,000
        ...

How can I do this? Thorn does not work because it only works with numbers.

Something like,

R←13 2 ⍴ Months,P

does not work either:

 Nov  Dec                                                                           
 Jan  Feb                                                                           
 Mar  Apr                                                                           
 May  Jun                                                                           
 Jul  Aug                                                                           
 Sep  Oct                                                                           
 Nov  97000 94000 91000 88000 85000 82000 79000 76000 73000 70000 67000 64000 61000 
 Nov  Dec                                                                           
 Jan  Feb                                                                           
 Mar  Apr                                                                           
 May  Jun                                                                           
 Jul  Aug                                                                           
 Sep  Oct     
3 Answers

From your questions is not totally obvious how the function Money should be called, so I'll leave that out. I think the big error you made is

R←13 2 ⍴ Months,P

because as you as this created something unexpected.

Basically you'll have to index Monthswith the no of the corresponding month so that Months[someIndex] has the same shape as the result of your calculations P. As simple solution would then be to do Months[someIndex],[1.5]P which glues the two together but will as an axis (columns). That might be usable for further processing, i.e. number formatting.

Personally I rarely use ⍕ for number formatting, but use ⎕FMT instead, as if gives you more control over the desired format.

Sample usage:

          'CF12.2'⎕fmt 1000×⍳12
    1,000.00
    2,000.00
    3,000.00
    4,000.00
    5,000.00
    6,000.00
    7,000.00
    8,000.00
    9,000.00
   10,000.00
   11,000.00
   12,000.00

Try it online!

You should disclose (⊃) P after the reduction: P←⊃-/T(M×W) or use the simpler P←T-M×W

Format the numbers as MBaas said in his answer: 'CF12.2'⎕fmt P or without the fractional part: 'CI11'⎕fmt P

If you mix (↑) the month names as a 12-by-3 char matrix, it's easier to catenate (,) them on the left: (↑Months),'CI11'⎕fmt P

To replace spaces with dots: '.'@{⍵=' '}

Note that the result for November here ended up as 97000, not 100000, but that should be easy to fix.

∇R←T Money W
 M←1 2 3 4 5 6 7 8 9 10 11 12 13
 Months←'Nov' 'Dec' 'Jan' 'Feb' 'Mar' 'Apr' 'May' 'Jun' 'Jul' 'Aug' 'Sep' 'Oct' 'Nov'
 P←T-M×W
 R←(↑Months),'.'@{' '=⍵}'CI11'⎕fmt P
∇

Try it online!

As MBaas has answered, ⎕FMT "format by specification" is what you are looking for. I just want to add that the entire formatting can be handled by a single application of ⎕FMT, including filling with dots:

 R←T Money W
 M←1 2 3 4 5 6 7 8 9 10 11 12 13
 Months←'Nov' 'Dec' 'Jan' 'Feb' 'Mar' 'Apr' 'May' 'Jun' 'Jul' 'Aug' 'Sep' 'Oct' 'Nov'
 P←-/T(M×W)
 R←(↑Months),'CR<.>I11'⎕FMT P

The parts of the format specification CR<.>I11 are as follows:
 C inserts commas between triads of digits starting from the rightmost digit of the integer part of the result.
 R<.> presets the field with . which is repeated as necessary to fill the field.
 I11 integer format with the total field width per column of 11.

Try it online! (For good practice, I've taken the freedom to localise your variables with ;M;Months;P)

⎕FMT's full documentation is available here

Note that ⎕FMT can handle nested arrays, so you don't actually have to disclose after the reduction, as suggested by ngn, but his advice applies in general.

Related