list-utils.scm 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. (library (lib utils list-utils)
  2. (export list-prefix?
  3. list-suffix?
  4. multirember*-with-equal-proc
  5. multirember-with-equal-proc
  6. multirember-equal
  7. multirember*-equal
  8. list-prefixes
  9. list-prefixes-long-to-short)
  10. (import
  11. (rnrs base)
  12. (only (guile) lambda* λ)
  13. ;; SRFIs
  14. ;; list procs
  15. (srfi srfi-1)
  16. ;; custom modules
  17. (prefix (logging) log:)))
  18. (define rest
  19. (λ (lst)
  20. (cdr lst)))
  21. (define list-prefix?
  22. (λ (lst lst-prefix)
  23. (cond
  24. [(null? lst-prefix) #t]
  25. [(null? lst) #f]
  26. [else
  27. (cond
  28. [(equal? (first lst) (first lst-prefix))
  29. (list-prefix? (rest lst) (rest lst-prefix))]
  30. [else #f])])))
  31. (define list-suffix?
  32. (λ (lst maybe-suffix)
  33. (cond
  34. [(null? maybe-suffix) #t]
  35. [(null? lst) #f]
  36. [else
  37. (cond
  38. [(equal? (first lst) (first maybe-suffix))
  39. (equal? lst maybe-suffix)]
  40. [else
  41. (list-suffix? (rest lst) maybe-suffix)])])))
  42. (define multirember*-with-equal-proc
  43. (λ (equal-proc)
  44. (λ (lst unwanted)
  45. (let loop ([remaining-list lst])
  46. (cond
  47. [(null? remaining-list)
  48. '()]
  49. ;; case for finding the unwanted element in the list
  50. [(equal-proc (first remaining-list) unwanted)
  51. (loop (rest remaining-list))]
  52. ;; case for handling nested lists
  53. [(pair? (first remaining-list))
  54. (cons (loop (first remaining-list))
  55. (loop (rest remaining-list)))]
  56. [else
  57. (cons (first remaining-list)
  58. (loop (rest remaining-list)))])))))
  59. (define multirember-with-equal-proc
  60. (λ (equal-proc)
  61. (λ (lst unwanted)
  62. (let loop ([remaining-list lst])
  63. (cond
  64. [(null? remaining-list)
  65. '()]
  66. [(equal-proc (first remaining-list) unwanted)
  67. (loop (rest remaining-list))]
  68. [else
  69. (cons (first remaining-list)
  70. (loop (rest remaining-list)))])))))
  71. (define multirember-equal
  72. (multirember-with-equal-proc equal?))
  73. (define multirember*-equal
  74. (multirember*-with-equal-proc equal?))
  75. ;; TODO: Can this function be optimized for better time or space behavior?
  76. ;; Probably the current runtime is: O(n^2 + (2 * (n - 1))) = O(n^2)
  77. (define list-prefixes
  78. (λ (lst)
  79. ;; O(n) * ... for iterating over all list elements
  80. (let iter ([remaining lst] [prefixes '()] [acc-prefix '()])
  81. (cond
  82. [(null? remaining) '()]
  83. ;; + O(2 * (n - 1)) for reversing all n-1 prefixes. Elements appear in
  84. ;; multiple prefixes.
  85. [(null? (rest remaining)) (reverse prefixes)]
  86. [else
  87. (let ([updated-acc-prefix
  88. ;; append is O(n). This is done for each iteration to a longer
  89. ;; and longer accumulated prefix. This means that this O(n) is
  90. ;; multiplied with the O(n) of the iteration.
  91. (append acc-prefix (list (first remaining)))])
  92. (iter (rest remaining)
  93. (cons updated-acc-prefix prefixes)
  94. updated-acc-prefix))]))))
  95. (define list-prefixes-long-to-short
  96. (λ (lst)
  97. ;; O(n) * ... for iterating over all list elements
  98. (let iter ([remaining lst] [prefixes '()] [acc-prefix '()])
  99. (cond
  100. [(null? remaining) '()]
  101. [(null? (rest remaining)) prefixes]
  102. [else
  103. (let ([updated-acc-prefix
  104. ;; append is O(n). This is done for each iteration to a longer
  105. ;; and longer accumulated prefix. This means that this O(n) is
  106. ;; multiplied with the O(n) of the iteration.
  107. (append acc-prefix (list (first remaining)))])
  108. (iter (rest remaining)
  109. (cons updated-acc-prefix prefixes)
  110. updated-acc-prefix))]))))