2015-07-21.scm 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. ;; A Number Puzzle
  2. ;; Find a 10-digit number with:
  3. ;; - All digits unique
  4. ;; - First n digits are divisible by n
  5. ;; Example: 345
  6. ;; 3 is divisible by 1
  7. ;; 34 is divisible by 2
  8. ;; 345 is divisible by 3
  9. ;; Some notes before I get started, based on well-known divisibility rules:
  10. ;; (Indexed by 1)
  11. ;; The tenth digit is 0.
  12. ;; The fifth digit is 5.
  13. ;; Even-indexed digits are even.
  14. ;; Odd-indexed digits are odd.
  15. ;; With this information, we will only need 4! * 4! trials.
  16. (import (scheme base)
  17. (scheme write)
  18. (srfi 1))
  19. (define (check? digits)
  20. (let loop ((i 1)
  21. (n (car digits))
  22. (in-list (cdr digits)))
  23. (if (= 0 (modulo n i))
  24. (if (null? in-list)
  25. #t
  26. (loop (+ i 1)
  27. (+ (* n 10) (car in-list))
  28. (cdr in-list)))
  29. #f)))
  30. (define (puzzle)
  31. (define (all-permutations l)
  32. ;; Only works if l has no repeated elements
  33. (if (null? l)
  34. '(())
  35. (let loop ((out-list '())
  36. (in-list l))
  37. (if (null? in-list)
  38. out-list
  39. (loop (append (map (lambda (x) (cons (car in-list) x))
  40. (all-permutations (delete (car in-list) l)))
  41. out-list)
  42. (cdr in-list))))))
  43. (define odd-perms (all-permutations '(1 3 7 9)))
  44. (define even-perms (all-permutations '(2 4 6 8)))
  45. (define (combine-digits odds evens)
  46. (list (first odds)
  47. (first evens)
  48. (second odds)
  49. (second evens)
  50. 5
  51. (third evens)
  52. (third odds)
  53. (fourth evens)
  54. (fourth odds)))
  55. (let loop ((i 0)
  56. (next-odds odd-perms)
  57. (next-evens even-perms))
  58. (define result (combine-digits (car next-odds) (car next-evens)))
  59. (if (check? result)
  60. ;; Return the result as a number
  61. (let loop ((n 0)
  62. (in-list (append result '(0))))
  63. (if (null? in-list)
  64. n
  65. (loop (+ (* n 10) (car in-list))
  66. (cdr in-list))))
  67. (if (< i 23)
  68. (loop (+ i 1) next-odds (cdr next-evens))
  69. (loop 0 (cdr next-odds) even-perms)))))
  70. (display (puzzle))
  71. (newline)