Palamedes Blog

Friday, September 18, 2015

Formatting money in Palamedes

There are no built-in functions for formatting currency, but it's easy to define some. Here are two examples, one simple, one intricate:

/* Quick and dirty */
money ← "$" + commify m

money @ m ← 23500
money @ m ← 138000000
money @ m ← π * B
money @ m ← 8.5 * T

The results look like this:

m ← 23500
money → "$23,500"

m ← 138 * M
money → "$138,000,000"

m ← π * B
money → "$3,141,592,653.589793"

m ← 8.5 * T
money → "$8,500,000,000,000"

This quick-and-dirty solution has the following disadvantages:

We can get rid of the quotion marks using unquote, compress the zeroes by writing M for millions and B for billions, and round to two digits using the round function. Here's the code:

/* Sophisticated */

classify ← if[m<10^6, [m, ""], m>=10^6&&m<10^9,[m / 10^6, "M"], m>=10^9&&m<10^12,[m / 10^9, "B"], m>=10^12&&m<10^15,[m / 10^12, "T"], m>=10^15&&m<10^18,[m / 10^15, "Q"], true, [m, ""]]

money ← unquote("$" + commify(round(classify ∘ 0)) + (classify ∘ 1))

money @ m ← 23500
money @ m ← 138000000
money @ m ← π * B
money @ m ← 8.5 * T

The classify expression outputs an array with two parts: The first part divides out millions, billions, etc. And the second part is a string indicating the size: "M" for millions, "B" for billions, etc.

This results in the output:

m ← 23500
money → $23,500

m ← 138000000
money → $138M

m ← π * B
money → $3.14B

m ← 8.5 * T
money → $8.5T

Stardate: Unknown

Integer Factorization

Palamedes is an array-based language. Here's a practical demonstration of loopless coding.

Factor a number n in Palamedes by Trial division without any loops:

factor ← {N ↤ [2 .. √n]; α ↤ n/N; α≈⌊round α⌋ | N}

We can re-write this in ascii without any unicode characters, if desired:

factor gets {N set [2 .. root n]; alpha set n / N; alpha approx floor(round(alpha)) | N}

This method finds all factors up to √n, not just prime factors. We know we have a factor when division produces an integer result. But division produces numbers with rounding errors like

71.99999999999999
18.000000000000004

which we want rounded to 72 and 18. floor(round(alpha)) gives us the nearest integer to alpha. round actually rounds to 2 decimal places, and we want no decimal places, so we follow round with floor. Due to the rounding errors, we use approx for comparison, rather than eq =.

You can call the procedure like this:

factor@n ← 119
factor@n ← 144

You'll get output like this:

n ← 119
factor → [7]

n ← 144
factor → [2, 3, 4, 6, 8, 9, 12]

Friday, August 14, 2015

FizzBuzz in Palamedes

Rosetta Code describes FizzBuzz like so:

Write a program that prints the integers from 1 to 100. But for multiples of three print "Fizz" instead of the number, and for the multiples of five print "Buzz". For numbers which are multiples of both three and five print "FizzBuzz".

Palamedes version

Most straightforward implementation

Here is the second shortest Palamedes implementation of "FizzBuzz" I could think of--just one line of code with 79 characters. It's a straightforward implementation that uses a conditional expression to test the residue of each number modulo 15, 5 and 3:

map(if[_ mod 15=0⇒"FizzBuzz",_ mod 5=0⇒"Buzz",_ mod 3=0⇒"Fizz",⊤⇒_],1--100)

If you want to print the results as a list with one result per line and without quotes around strings, then do this:

map(if[_ mod 15=0⇒"FizzBuzz",_ mod 5=0⇒"Buzz",_ mod 3=0⇒"Fizz",⊤⇒_]},1--100)//unquote//listify
Shortest implementation

Here is a slightly different approach that replaces the conditional with an array lookup. It shows off Palamedes' ability to do array arithmetic. It's the shortest Palamedes implementation---only 63 characters:

map(["FizzBuzz","Buzz","Fizz",_]∘[2,1].sign(_ mod[5,3]),1--100)

APL version

The Palamedes version is inspired by my own 18%-shorter, 55-character Dyalog APL program, which you can try yourself here. This version is 1-character shorter than the one on Rosetta Code1:

⎕IO←0⋄{'FizzBuzz' 'Buzz' 'Fizz' ⍵[+/1 2××3 5|⍵]}¨1+⍳100

The following alternate version is the same size. Try it here:

⎕IO←0⋄{'FizzBuzz' 'Buzz' 'Fizz' ⍵[1 2+.××3 5|⍵]}¨1+⍳100

Comparison: Palamedes vs APL

I'm a fan of APL's great concision, but I find the Palamedes code more readable. Here is a comparison:


  1. The Rosetta Code version uses 0=3 5|⍵ to compute the sign of the residue array, which may be simplified further to this ×3 5|⍵, shortening the code by 1 character. 



AUTHORS BUGS DISCUSSION LICENSE NAME NEWS README SOURCE TODO TRY VERSION

Last update: Fri Sep 23 2016