solution.scm 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. ;; https://projecteuler.net/problem=24
  2. ;; Lexicographic permutations
  3. ;; Problem 24
  4. ;; A permutation is an ordered arrangement of objects. For
  5. ;; example, 3124 is one possible permutation of the digits
  6. ;; 1, 2, 3 and 4. If all of the permutations are listed
  7. ;; numerically or alphabetically, we call it lexicographic
  8. ;; order. The lexicographic permutations of 0, 1 and 2 are:
  9. ;; 012 021 102 120 201 210
  10. ;; What is the millionth lexicographic permutation of the
  11. ;; digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
  12. (import
  13. (except (rnrs base) let-values map)
  14. (only (guile)
  15. lambda* λ)
  16. (ice-9 match)
  17. (srfi srfi-1) ; list stuff
  18. (contract)
  19. (prefix (lib math) math:)
  20. (lib list-helpers))
  21. ;; 0123456789 + 9 (9*1)
  22. ;; 0123456798 + 81 (9*9)
  23. ;; 0123456879 + 18 (9*2)
  24. ;; 0123456897 + 81 (9*9)
  25. ;; 0123456978 + 9 (9*1)
  26. ;; 0123456987 + 702 (9*9*9 - 9*3 = 9*78)
  27. ;; 0123457689 ...
  28. ;; There seems to be some pattern there, but not sure what
  29. ;; it is exactly.
  30. ;; I guess one has to really implement permutating a list so
  31. ;; that the permutations are in order.
  32. ;; idea: stream of permutations? If I can find the function
  33. ;; to generate them ...
  34. ;; '(0 1 2 3 4 5 6 7 8 9)
  35. ;; - - rotate last 2
  36. ;; go until numbers no longer become bigger
  37. ;; then swap the last numbers
  38. ;; '(0 1 2 3 4 5 6 7 9 8)
  39. ;; '(0 1 2 3 4 5 6 8 7 9)
  40. ;; '(0 1 2 3 4 5 6 8 9 7)
  41. ;; '(0 1 2 3 4 5 6 9 7 8)
  42. ;; '(0 1 2 3 4 5 6 9 8 7)
  43. ;; '(0 0 0 0 0 0 0 0 0 0)
  44. ;; '(0 0 0 0 0 0 0 0 0 1)
  45. ;; '(0 0 0 0 0 0 0 0 1 0)
  46. ;; '(0 0 0 0 0 0 0 0 1 1)
  47. ;; '(0 0 0 0 0 0 0 1 0 0)
  48. ;; *
  49. ;; / \
  50. ;; 0 *
  51. ;; / \
  52. ;; 1 *
  53. ;; / \
  54. ;; 2 3
  55. ;; '(0 1 2)
  56. ;; '(0 2 1)
  57. ;; '(1 0 2)
  58. ;; '(1 2 0)
  59. ;; '(2 0 1)
  60. ;; '(2 1 0)
  61. ;; if the smallest number is the last -> something must be
  62. ;; swapped further at the front
  63. (define permutations
  64. (sort (permute math:+decimal-digits+)
  65. (make-list-comparator <)))
  66. (simple-format (current-output-port)
  67. "millionth permutation: ~a\n"
  68. (list-ref permutations (- (expt 10 6) 1)))