3

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     
MBaas
  • 7,248
  • 6
  • 44
  • 61
zeynel
  • 177
  • 1
  • 1
  • 12

3 Answers3

3

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!

Adám
  • 6,573
  • 20
  • 37
MBaas
  • 7,248
  • 6
  • 44
  • 61
3

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!

ngn
  • 7,763
  • 6
  • 26
  • 35
  • Thanks! Even `↑Months P` works (without leader dots). But why is it that we don't have to apply Mix to `P`, like this: `↑Months ↑P` Because `P` is same shape as Months? There is a lot I don't understand here. I have to practice. – zeynel Oct 25 '18 at 16:11
  • @zeynel `'CI11'⎕fmt P` is already a character matrix - that's what `⎕fmt` returns for a vector `P`. On the other hand, `Months` is a vector of character vectors, so you need to "mix" it before sticking it to the left of `'CI11'⎕fmt P`. Only the leading dimensions (the heights) need to match, not necessarily the whole shapes. – ngn Oct 25 '18 at 16:25
  • @zeynel by the way, this expression: `↑Months ↑P` parses as `↑(Months ↑ P)` - the second `↑` becomes dyadic, so you may want to use some parentheses there, e.g. `(↑Months) , ↑P` or `(↑Months)(↑P)` (I'm not sure which one you had in mind) – ngn Oct 25 '18 at 16:29
  • Thanks for noticing that first month's value was not the initial amount. Starting the index with zero solved it: `M←0 1 2 3 4 5 6 7 8 9 10 11 12` – zeynel Oct 25 '18 at 17:33
  • @zeynel do you know about `⍳`? it generates a vector of consecutive integers. the comments here are piling up... do you mind joining our [apl chat room](https://chat.stackexchange.com/rooms/52405/the-apl-orchard) so i can explain it in more detail? – ngn Oct 25 '18 at 18:20
  • ...or if i'm not in, i'm sure others will be happy to help, too – ngn Oct 25 '18 at 18:43
  • Ok. We'll continue there. But first I want to read more about `⎕fmt`... – zeynel Oct 26 '18 at 08:43
2

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.

Adám
  • 6,573
  • 20
  • 37
  • `⊃` was necessary to catenate the month names properly; i didn't know about `R<.>` - nice – ngn Oct 25 '18 at 12:41
  • `Thanks!` So, I assume I need to put the right argument of the function first, as you did: `T Money W;M;Months;P` And not do something like this: `T Money Months;W;M;P`. – zeynel Oct 25 '18 at 17:42
  • @zeynel Correct. You could also use a [dfn](http://help.dyalog.com/latest/Content/Language/Defined%20Functions%20and%20Operators/DynamicFunctions/MultiLine%20Dynamic%20Functions.htm) which auto-localises: [Try it online!](https://tio.run/##SyzI0U2pTMzJT///X8E3Py@18lHbhGouBRDwBTINFYwUjBVMFEwVzBTMFSwULBUMDRQMDRUMjRQMjaHK8vNKMoqBatX98svUFdRdUpOBpFdiHpB0S00Ckr6JRUDSsaAIzK4EyZbmgckckHhpOpAMTi0Akv7JJUASZA7E7ACgsbr6j3p3afgenv6od6smRFjjUdtEiLWaOurOQTZ6dp6GhuqP@qa6@YYoBHAp1P7/b2gAAhAvKRgDmQA "APL (Dyalog Unicode) – Try It Online") – Adám Oct 25 '18 at 18:00