solution.scm 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. ;; https://projecteuler.net/problem=22
  2. ;; Names scores
  3. ;; Problem 22
  4. ;; Using names.txt (right click and 'Save Link/Target As...'), a 46K
  5. ;; text file containing over five-thousand first names, begin by
  6. ;; sorting it into alphabetical order. Then working out the
  7. ;; alphabetical value for each name, multiply this value by its
  8. ;; alphabetical position in the list to obtain a name score.
  9. ;; For example, when the list is sorted into alphabetical order,
  10. ;; COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name
  11. ;; in the list. So, COLIN would obtain a score of 938 × 53 = 49714.
  12. ;; What is the total of all the name scores in the file?
  13. (import
  14. (except (rnrs base) let-values map)
  15. (only (guile) lambda* λ)
  16. (srfi srfi-1)
  17. (lib fileio)
  18. (contract)
  19. (prefix (lib math) math:))
  20. (define-with-contract read-names
  21. (require (string? file-name))
  22. (ensure (list? <?>)
  23. (not (null? <?>)))
  24. (λ (file-name)
  25. (let* ([file-content
  26. (get-string-from-file
  27. (string-join (list (dirname (current-filename)) "names.txt")
  28. "/"))])
  29. (map
  30. (λ (name-with-quotes)
  31. (string-trim-both name-with-quotes
  32. (λ (char) (char=? char #\"))))
  33. (string-split file-content
  34. (λ (char)
  35. (char=? char #\,)))))))
  36. (define-with-contract letter-score
  37. (require (char? letter))
  38. (ensure (integer? <?>)
  39. (positive? <?>))
  40. (λ (letter)
  41. (+ (- (char->integer letter)
  42. (char->integer #\A))
  43. 1)))
  44. (define-with-contract name-score
  45. (require (string? name))
  46. (ensure (integer? <?>)
  47. (positive? <?>))
  48. (λ (name)
  49. (math:sum (map letter-score (string->list name)))))
  50. (let* ([file-name (second (command-line))]
  51. [sorted-names (sort (read-names file-name)
  52. string-ci<)])
  53. (let iter ([index 0]
  54. [remaining-names sorted-names]
  55. [sum 0])
  56. (cond
  57. [(null? remaining-names) sum]
  58. [else
  59. (iter (+ index 1)
  60. (cdr remaining-names)
  61. (+ sum (* (name-score (first remaining-names))
  62. (+ index 1))))]))
  63. (display
  64. (simple-format
  65. #f "~s\n"
  66. (let iter ([index 0]
  67. [remaining-names sorted-names]
  68. [sum 0])
  69. (cond
  70. [(null? remaining-names) sum]
  71. [else
  72. (iter (+ index 1)
  73. (cdr remaining-names)
  74. (+ sum (* (name-score (first remaining-names))
  75. (+ index 1))))])))))