**Advent Calendar 2019**

### | **Day 2** | **Day 3** | **Day 4** |

The gift is presented by **Joelle Maslak**. Today she is talking about her solutions to **Task #1: Decimal to Roman** of **“The Weekly Challenge - 010”**.

#### Write a script to encode/decode Roman numerals. For example, given Roman numeral CCXLVI, it should return 246. Similarly, for decimal number 39, it should return XXXIX. Checkout wikipedia page for more informaiton.

To start with, I read the Wikipedia page referenced in the challenge, and realized there were several different systems for writing Roman numerals – it wasn’t as standardized as I thought! That said, I stuck with the style used in the description of the challenge, specifically **“subtractive”** notation. Essentially, the symbols are written from the largest value to the smallest value, left to right, with no more than **3** of any symbol used. When four of a symbol would normally be used (for instance, **IIII** to mean **4**), instead it would be written as **IV**, meaning one less than **4** (you see this because the smaller number is before the bigger number).

So that’s what I’ll talk about below – the part of the code that converts an integer to a Roman number.

```
1 sub decimal-to-roman(UInt:D $decimal is copy -->Str:D) {
2 my $str = '';
3
4 my @conversions =
5 M => 1000,
6 CM => 900,
7 D => 500,
8 CD => 400,
9 C => 100,
10 XC => 90,
11 L => 50,
12 XL => 40,
13 X => 10,
14 IX => 9,
15 V => 5,
16 IV => 4,
17 I => 1,
18 ;
19
20 for @conversions -> $pair {
21 while $decimal ≥ $pair.value {
22 $decimal -= $pair.value;
23 $str ~= $pair.key;
24 }
25 }
26
27 return $str;
28 }
```

I haven’t talked about a lot of the syntax of the basic language in past posts about the **Perl Weekly Challenge**, but I’ll mention a bit here.

In **line 1** above, we define a function named decimal-to-roman. Yes, you can use “-” in function names, which is probably anxiety provoking to most people familiar with Algol-based languages, but is unambiguous in **Raku** syntax – and thus allowed (indeed, **Lisp**, among many others allow hyphens too).

This function takes one parameter, *$decimal*. This variable has a type – UInt:D. The **UInt** part is relatively straightforward to most developers, whether or not they use **Raku** – must be an unsigned integer. The **:D** part is unusual to most non-Raku developers, but is simple – it simply indicates the **UInt** passed must be defined, I.E. it has to be an actual value. This **line 1** also makes this parameter, *$decimal*, a copy. By default, **Raku** parameters are read only, so they can’t be modified. This saves the overhead of making a copy when calling functions. Finally, the function returns a **Str:D** – a defined string.

You don’t have to define types in **Raku** – but when you do, you get some automatic error checking, so it’s sometimes a good thing to do. For instance, if I tried to return a **UInt** rather than a String, or returned an undefined variable, I would get an error that indicating where the assignment happened, not some far away module that expected a String and didn’t get it.

We’re using *$str* to build a string that will be returned by this function, so we initialize it to zero character long string. We’ll be building this string left to right later in the function.

We then build an array of **Pair**. In **Raku**, pairs are built-in to the language. **Pairs** are simply two values stored together, typically referred to as a key and a value. We use these pairs to represent some symbols and their decimal values. You can define a pair with the **X => Y** notation (X is the key, Y is the value).

We start with the largest values – for instance, **“M”**, which represents 1,000 (this is the largest symbol in widespread usage.

The next value is **“CM”**. **“C”** means **100**, so **“CM”** means **100** less than **1000**, or **900**.

We then represent the rest of the pairs of Roman numeral **“digits”** and their associated decimal values.

The loops are where it gets interesting. For each pair, we see if that pair is less than the current value of *$decimal*. For instance, if *$decimal* is **8**, the first time through this outer loop we have the pair representing **“M”** and **1000**. The inner loop only runs while *$decimal* is equal or greater than **1000** (my editor automatically changes >= to ≥, a Unicode character, to save characters on my screen – and let me keep more state on the screen). Of course, it’s not ≥ 1000, so we go on to the next symbol, **“CM”**, which is still bigger than **8**, etc.

Eventually we get to **“V”**, representing **5**. So the first (and only) time through the inner loop with a pair of **V => 5**, we subtract 5 from *$decimal* (so *$decimal* is now 3), and add the symbol **“V”** to the end of *$str* (which now contains **“V”**).

We then move to **“IV”**, representing **4**, which is not ≥ the value of *$decimal* (3).

Then we get to I => 1. The inner loop runs 3 times, subtracting 1 from *$decimal* each time and appending an **“I”** to *$src* each time. After the **3rd** run through this inner loop, *$decimal* is 0, which is no longer greater or equal to 1. So we’re done.

If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.