# Project Euler in PL/SQL: Problem 17

Switching back to PL/SQL for Problem 17 of Project Euler.

## Problem 17:

### Number Letter Counts

If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?

NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of “and” when writing out numbers is in compliance with British usage.

This problem required quit a bit more code than what we’ve done so far. I had to manually handle for each case of numbers, 1-19, and each interval of 10 (20, 30, 40, etc.) since they don’t follow a reusable rule. The cool thing is once those were taken care of, I could handle all numbers up to 9999.

I use one function for all numbers 1-19, and a main function that processes all numbers and calls the `handle_LT_twenty` function when required.

```DECLARE
total INTEGER := 0;
FUNCTION handle_LT_twenty(x INTEGER) RETURN INTEGER --handle "less than" twenty
IS
char_count INTEGER;
BEGIN
IF x IN (1,2,6,10)
THEN
char_count := 3;
ELSIF x IN (4,5,9)
THEN
char_count := 4;
ELSIF x IN (3,7,8)
THEN
char_count := 5;
ELSIF x IN (11,12)
THEN
char_count := 6;
ELSIF x IN (15,16)
THEN
char_count := 7;
ELSIF x IN (13,14,18,19)
THEN
char_count := 8;
ELSIF x IN (17)
THEN
char_count := 9;
END IF;

return char_count;
END;
FUNCTION count_chars(x INTEGER) RETURN INTEGER
IS
char_count INTEGER := 0;
ones_digit INTEGER := SUBSTR(x,-1,1); -- right-most digit
tens_digit INTEGER := SUBSTR(x,-2,1);
hundreds_digit INTEGER := SUBSTR(x,-3,1);
thousands_digit INTEGER := SUBSTR(x,-4,1);
BEGIN

--handle for cases of 19 and less
IF tens_digit IN (1) OR length(x) < 2
THEN
char_count := handle_LT_twenty(tens_digit||ones_digit);
ELSE
--handle the tens digit for 20 and higher
IF tens_digit IN (2,3,8,9) THEN -- "twenty", "thirty", etc.
char_count := 6;
ELSIF tens_digit IN (4,5,6) THEN -- "forty", "fifty", etc.
char_count := 5;
ELSIF tens_digit IN (7) THEN -- "seventy"
char_count := 7;
END IF;

IF ones_digit != 0
THEN
char_count := char_count + handle_LT_twenty(ones_digit);
END IF;

END IF;

IF length(x) >= 3 AND hundreds_digit != 0 THEN --dealing with hundreds
char_count := char_count + handle_LT_twenty(hundreds_digit); --hundred digit follows same rules as single digit, "one" hundred

IF tens_digit+ones_digit = 0
THEN
char_count := char_count + length('hundred'); -- 100 = "onehundred"
ELSE

char_count := char_count + length('hundredand'); --no spaces! 101 = "onehundredandone"
END IF;

ELSIF length(x) = 4 THEN --dealing with thousands
char_count := char_count + handle_LT_twenty(thousands_digit); --thousands digit follows same rules as single digit, "one" thousand

IF hundreds_digit+tens_digit+ones_digit = 0
THEN
char_count := char_count + length('thousand'); -- 1000 = "onethousand"
ELSE
char_count := char_count + length('thousandand'); --no spaces! 1001 = "onethousandandone"
END IF;
END IF;

return char_count;
END;
BEGIN
FOR i IN 1..1000
LOOP
total := total + count_chars(i);
END LOOP;

dbms_output.put_line(total);
END;

--output: 21124
```

Questions or comments? Feel free to leave them below or reach out to me on Twitter!