686f62d102f5

Problem 17
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Mon, 13 Feb 2017 13:32:08 +0000
parents 4a9353c06f29
children 1ae69146e0e2
branches/tags (none)
files src/euler.lisp

Changes

--- a/src/euler.lisp	Mon Feb 13 13:20:22 2017 +0000
+++ b/src/euler.lisp	Mon Feb 13 13:32:08 2017 +0000
@@ -48,9 +48,11 @@
           (not (dividesp n 11))) nil)
     (t (definitely-palindrome-p n))))
 
-(defun sum (sequence)
+(defun sum (sequence &key key)
   (iterate (for n :in-whatever sequence)
-           (sum n)))
+           (sum (if key
+                  (funcall key n)
+                  n))))
 
 (defun divisors (n)
   (sort (iterate (for i :from 1 :to (sqrt n))
@@ -449,6 +451,30 @@
   ;; What is the sum of the digits of the number 2^1000?
   (sum (digits (expt 2 1000))))
 
+(defun problem-17 ()
+  ;; 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, which is awful.
+  (labels ((letters (n)
+             (-<> n
+               (format nil "~R" <>)
+               (count-if #'alpha-char-p <>)))
+           (has-british-and (n)
+             (or (< n 100)
+                 (zerop (mod n 100))))
+           (silly-british-letters (n)
+             (+ (letters n)
+                (if (has-british-and n) 0 3))))
+    (sum (range 1 (1+ 1000))
+         :key #'silly-british-letters)))
+
 
 ;;;; Tests --------------------------------------------------------------------
 (def-suite :euler)
@@ -470,6 +496,7 @@
 (test p14 (is (= 837799 (problem-14))))
 (test p15 (is (= 137846528820 (problem-15))))
 (test p16 (is (= 1366 (problem-16))))
+(test p17 (is (= 21124 (problem-17))))
 
 
 ;; (run! :euler)