hanoi-model.scm 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. (define-module (hanoi-model))
  2. (define-public create-hanoi
  3. (λ (source spare dest)
  4. (list source spare dest)))
  5. (define-public rest-of-towers cdr)
  6. (define-public first-of-towers car)
  7. (define-public rest-of-disks cdr)
  8. (define-public first-of-disks car)
  9. (define-public first-tower first-of-towers)
  10. (define-public second-tower (λ (hanoi) (first-of-towers (rest-of-towers hanoi))))
  11. (define-public third-tower (λ (hanoi) (first-of-towers (rest-of-towers (rest-of-towers hanoi)))))
  12. (define-public create-tower
  13. (λ (id disk-sizes)
  14. "This is a procedure for creating a tower and assuring, that the tower has a
  15. valid stacking of disks."
  16. (let check-disk-sizes ([remaining-disks disk-sizes] [previous-disk-size -inf.0])
  17. (cond
  18. [(null? remaining-disks) (cons id disk-sizes)]
  19. [(> (first-of-disks remaining-disks) previous-disk-size)
  20. (check-disk-sizes (rest-of-disks remaining-disks) (first-of-disks remaining-disks))]
  21. [else
  22. (raise (cons 'invalid-disk-placement disk-sizes))]))))
  23. ;; A tower shall be a list whose first element is a symbol indicating the tower
  24. ;; position.
  25. (define-public tower-disks
  26. (λ (tower)
  27. (cdr tower)))
  28. (define-public tower-id
  29. (λ (tower)
  30. (car tower)))
  31. (define-public get-tower-basis
  32. (λ (tower)
  33. (let loop ([disks (tower-disks tower)])
  34. (cond
  35. [(null? disks)
  36. (error (list 'empty-disks tower))]
  37. [(null? (rest-of-disks disks))
  38. (first-of-disks disks)]
  39. [else
  40. (loop (rest-of-disks disks))]))))
  41. (define-public find-largest-disk
  42. (λ (tower)
  43. (get-tower-basis tower)))
  44. (define-public print-tower
  45. (λ (id hanoi)
  46. ((λ (towers)
  47. (if (not (null? towers))
  48. (display (simple-format #f "Tower: ~a\n" (first-of-towers towers)))
  49. (error (list 'tower-id-not-found id hanoi))))
  50. (filter (λ (tower) (eq? (tower-id tower) id))
  51. hanoi))))
  52. (define-public print-hanoi
  53. (λ (hanoi)
  54. (display (simple-format #f "Towers of Hanoi:\n"))
  55. (print-tower 'SO hanoi)
  56. (print-tower 'SP hanoi)
  57. (print-tower 'DE hanoi)))
  58. (define-public find-tower-by-id
  59. (λ (hanoi id)
  60. (cond
  61. [(null? hanoi)
  62. (error (list 'tower-id-not-found id hanoi))]
  63. [(eq? (tower-id (first-of-towers hanoi)) id)
  64. (first-of-towers hanoi)]
  65. [else
  66. (find-tower-by-id (rest-of-towers hanoi) id)])))
  67. (define-public take-disk
  68. (λ (tower)
  69. (first-of-disks tower)))
  70. (define-public take-disk-from-tower
  71. (λ (hanoi id)
  72. (take-disk (find-tower-by-id hanoi id))))
  73. (define-public remove-disk
  74. (λ (tower)
  75. (create-tower (tower-id tower)
  76. (rest-of-disks (tower-disks tower)))))
  77. (define-public stack-disks cons)