081.scm 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. ;; Path sum: two ways
  2. (use-modules (rnrs io ports))
  3. ;; TODO: rename array
  4. (define (make-min-sum-matrix array)
  5. (define min-path-array (init-min-path-array array))
  6. (define (rank-loop curr-rank)
  7. (if (>= curr-rank (array-length array)) min-path-array
  8. (begin
  9. (update-array curr-rank)
  10. (rank-loop (1+ curr-rank)))))
  11. ;; using sub-arrays to make indexing easier
  12. ;; TODO: change update-array name
  13. (define (update-array curr-rank)
  14. (let ((sub-array (make-shared-array min-path-array
  15. (lambda (i j)
  16. (list (+ curr-rank i) (+ curr-rank j)))
  17. (- (array-length min-path-array) curr-rank)
  18. (- (array-length min-path-array) curr-rank))))
  19. (do ((i 1 (1+ i)))
  20. ((>= i (array-length sub-array)))
  21. ;; could refactor this (using transpose of array) to not repeat myself
  22. (array-set! sub-array
  23. (+ (array-ref array (1+ curr-rank) (+ i curr-rank))
  24. (find-min-val sub-array i))
  25. 1 i)
  26. (array-set! (transpose-array sub-array 1 0)
  27. (+ (array-ref array (+ i curr-rank) (1+ curr-rank))
  28. (find-min-val (transpose-array sub-array 1 0) i))
  29. 1 i))))
  30. (begin
  31. (rank-loop 0))
  32. min-path-array)
  33. (define (find-min-val array i)
  34. (min (array-ref array 0 i)
  35. (array-ref array 1 (1- i))))
  36. (define (init-min-path-array array)
  37. (let ((min-path-array (make-array #f
  38. (array-length array)
  39. (array-length array))))
  40. (array-set! min-path-array (array-ref array 0 0) 0 0)
  41. ;; could also refactor this
  42. (do ((i 1 (1+ i)))
  43. ((>= i (array-length min-path-array)))
  44. (array-set! min-path-array
  45. (+ (array-ref array 0 i)
  46. (array-ref min-path-array 0 (1- i)))
  47. 0 i)
  48. (array-set! min-path-array
  49. (+ (array-ref array i 0)
  50. (array-ref min-path-array (1- i) 0))
  51. i 0))
  52. min-path-array))
  53. (define (print-array array)
  54. (for-each (lambda (row)
  55. (display row) (newline))
  56. (array->list array)))
  57. (define (make-matrix-from-file file)
  58. (let ((port (open-input-file file)))
  59. (let loop ((line (get-line port)) (lst '()))
  60. (if (eof-object? line) (list->array 2 (reverse lst))
  61. (loop (get-line port) (cons (line->number-list line) lst))))))
  62. (define (line->number-list line)
  63. (map string->number (string-split line #\,)))
  64. ;; for testing purposes
  65. (define default-array
  66. (list->array 2
  67. (list
  68. (list 131 673 234 103 18)
  69. (list 201 96 342 965 150)
  70. (list 630 803 746 422 111)
  71. (list 537 699 497 121 956)
  72. (list 805 732 524 37 331))))
  73. (let* ((min-array (make-min-sum-matrix (make-matrix-from-file "../input/p081.txt")))
  74. (last-index (1- (array-length min-array))))
  75. (display (array-ref min-array
  76. last-index
  77. last-index)))