├── .github ├── auto-assign-config.yml └── workflows │ ├── auto-assign.yml │ └── ci.yml ├── .gitignore ├── .travis.yml ├── LICENSE-MIT ├── README.md ├── info.rkt ├── main.rkt └── scribblings └── algorithms.scrbl /.github/auto-assign-config.yml: -------------------------------------------------------------------------------- 1 | # Set to true to assign PR author as assignee 2 | addAssignees: author 3 | 4 | # Set to true to add reviewers to the PR 5 | addReviewers: true 6 | 7 | # Set reviewers 8 | reviewers: 9 | - codereport 10 | 11 | # A number of reviewers added to the PR 12 | # numberOfReviewers: 0 means all reviewers from the list will be added. 13 | numberOfReviewers: 1 14 | -------------------------------------------------------------------------------- /.github/workflows/auto-assign.yml: -------------------------------------------------------------------------------- 1 | name: Auto Assign 2 | on: 3 | issues: 4 | types: [opened] 5 | pull_request: 6 | types: [opened] 7 | pull_request_target: 8 | types: [opened] 9 | 10 | permissions: 11 | issues: write 12 | pull-requests: write 13 | contents: read 14 | 15 | jobs: 16 | assign: 17 | runs-on: ubuntu-latest 18 | steps: 19 | # Handle Issues 20 | - if: github.event_name == 'issues' 21 | uses: pozil/auto-assign-issue@v2 22 | with: 23 | assignees: codereport 24 | numOfAssignee: 1 25 | 26 | # Handle PRs - use one action that can handle both assignments and reviews 27 | - if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' 28 | uses: kentaro-m/auto-assign-action@v1.2.5 29 | with: 30 | configuration-path: .github/auto-assign-config.yml 31 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | 16 | - uses: actions/cache@v4.2.3 17 | name: Cache installed packages 18 | with: 19 | path: | 20 | ~/.cache/racket 21 | ~/.local/share/racket 22 | key: ${{ runner.os }}-raco-${{ hashFiles('**/info.rkt') }} 23 | 24 | - name: Set up Racket 25 | uses: Bogdanp/setup-racket@v1.12 26 | with: 27 | architecture: 'x64' 28 | distribution: 'full' 29 | variant: 'CS' 30 | version: 'stable' 31 | 32 | - name: Run tests 33 | run: raco test main.rkt 34 | 35 | # - name: Coverage report 36 | # if: success() 37 | # run: | 38 | # raco setup --check-pkg-deps --pkgs algorithms 39 | # raco pkg install --auto cover cover-coveralls 40 | # raco cover -b -f coveralls -d ${{ github.workspace }}/coverage . 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | \#* 3 | .\#* 4 | .DS_Store 5 | compiled/ 6 | /doc/ 7 | scribblings/* 8 | !scribblings/*.scrbl 9 | *.kate-swp 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | # Based on: https://github.com/greghendershott/travis-racket 4 | 5 | env: 6 | global: 7 | # Supply a global RACKET_DIR environment variable. This is where 8 | # Racket will be installed. A good idea is to use ~/racket because 9 | # that doesn't require sudo to install. 10 | - RACKET_DIR=~/racket 11 | matrix: 12 | # Supply at least one RACKET_VERSION environment variable. This is 13 | # used by the install-racket.sh script (run at before_install, 14 | # below) to select the version of Racket to download and install. 15 | # 16 | # Supply more than one RACKET_VERSION (as in the example below) to 17 | # create a Travis-CI build matrix to test against multiple Racket 18 | # versions. 19 | - RACKET_VERSION=6.12 20 | - RACKET_VERSION=7.0 21 | - RACKET_VERSION=7.1 22 | - RACKET_VERSION=7.2 23 | - RACKET_VERSION=HEAD 24 | 25 | matrix: 26 | allow_failures: 27 | # - env: RACKET_VERSION=HEAD 28 | fast_finish: true 29 | 30 | before_install: 31 | - git clone https://github.com/greghendershott/travis-racket.git ~/travis-racket 32 | - cat ~/travis-racket/install-racket.sh | bash # pipe to bash not sh! 33 | - export PATH="${RACKET_DIR}/bin:${PATH}" #install-racket.sh can't set for us 34 | 35 | install: 36 | - raco pkg install --auto --name algorithms 37 | 38 | before_script: 39 | 40 | # Here supply steps such as raco make, raco test, etc. You can run 41 | # `raco pkg install --deps search-auto` to install any required 42 | # packages without it getting stuck on a confirmation prompt. 43 | script: 44 | - raco test -x -p algorithms 45 | 46 | after_success: 47 | - raco setup --check-pkg-deps --pkgs algorithms 48 | - raco pkg install --auto cover cover-coveralls 49 | - raco cover -b -f coveralls -d $TRAVIS_BUILD_DIR/coverage . 50 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | algorithms 2 | 3 | MIT License 4 | 5 | Copyright (c) 2020 Conor Hoekstra 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #
algorithms
2 | 3 | 17 | 18 | A package containing many useful algorithms (borrowed from many other programming languages). 19 | 20 | There is a GNU Guile scheme [version of this package](https://guile-algorithms.lajszczak.dev/). -------------------------------------------------------------------------------- /info.rkt: -------------------------------------------------------------------------------- 1 | #lang info 2 | (define collection "algorithms") 3 | (define deps '("base")) 4 | (define build-deps '("scribble-lib" "racket-doc" "rackunit-lib")) 5 | (define license 'MIT) 6 | (define scribblings '(("scribblings/algorithms.scrbl" ()))) 7 | (define pkg-desc "A package containing many useful algorithms (borrowed from many other programming languages).") 8 | (define version "0.3") 9 | (define pkg-authors '(cph)) 10 | -------------------------------------------------------------------------------- /main.rkt: -------------------------------------------------------------------------------- 1 | ; MIT License 2 | ; 3 | ; Copyright (c) 2020 Conor Hoekstra 4 | ; 5 | ; Permission is hereby granted, free of charge, to any person obtaining a copy 6 | ; of this software and associated documentation files (the "Software"), to deal 7 | ; in the Software without restriction, including without limitation the rights 8 | ; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | ; copies of the Software, and to permit persons to whom the Software is 10 | ; furnished to do so, subject to the following conditions: 11 | ; 12 | ; The above copyright notice and this permission notice shall be included in all 13 | ; copies or substantial portions of the Software. 14 | ; 15 | ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | ; SOFTWARE. 22 | 23 | #lang racket 24 | 25 | (module+ test 26 | (require rackunit)) 27 | 28 | (provide 29 | adjacent-map 30 | all? 31 | any? 32 | chunk-by 33 | chunks-of 34 | generate 35 | increasing? 36 | init 37 | juxt 38 | repeat 39 | replicate 40 | product 41 | scanl 42 | scanr 43 | sliding 44 | sorted? 45 | sum 46 | tail 47 | zip 48 | zip-with) 49 | 50 | 51 | (define (adjacent-map f lst) 52 | (zip-with f (init lst) (tail lst))) 53 | 54 | 55 | (define (all? lst) 56 | (andmap identity lst)) 57 | 58 | 59 | (define (any? lst) 60 | (ormap identity lst)) 61 | 62 | 63 | (define (chunk-by pred lst) 64 | (letrec ([aux (λ (lst chunk result) 65 | (cond [(null? lst) (reverse (cons (reverse chunk) result))] 66 | [(null? (cdr lst)) (reverse (cons (reverse (cons (car lst) chunk)) result))] 67 | [(pred (car lst) (cadr lst)) (aux (cdr lst) (cons (car lst) chunk) result)] 68 | [else (aux (cdr lst) '() (cons (reverse (cons (car lst) chunk)) result))]))]) 69 | (aux lst '() '()))) 70 | 71 | 72 | (define (chunks-of lst k) 73 | (sliding lst k k)) 74 | 75 | 76 | (define (generate n proc) 77 | (for/list ((_ n)) (proc))) 78 | 79 | 80 | (define (increasing? lst) 81 | (all? (adjacent-map < lst))) 82 | 83 | 84 | (define (init lst) 85 | (drop-right lst 1)) 86 | 87 | 88 | (define (juxt . procs) 89 | (λ args 90 | (map (λ (proc) (apply proc args)) procs))) 91 | 92 | 93 | (define (product lst) 94 | (foldl * 1 lst)) 95 | 96 | 97 | (define repeat make-list) 98 | 99 | 100 | (define (replicate lst lst2) 101 | (flatten (zip-with make-list lst lst2))) 102 | 103 | 104 | (define (sliding lst size [step 1]) 105 | (cond [(> step (length lst)) 106 | (error "step has to be equal to or smaller than length of the list")] 107 | [(= step (length lst)) 108 | (list lst)] 109 | [(let recur ([lst lst] 110 | [len (length lst)]) 111 | (if (>= size len) 112 | (if (empty? lst) empty (list lst)) 113 | (cons (take lst size) 114 | (recur (drop lst step) 115 | (- len step)))))])) 116 | 117 | 118 | (define (scanl proc lst) 119 | (foldl 120 | (λ (val acc) 121 | (append acc (list (proc val (last acc))))) 122 | (list (first lst)) 123 | (rest lst))) 124 | 125 | 126 | (define (scanr proc lst) 127 | (foldl 128 | (λ (a acc) 129 | (cond ((null? acc) (cons a acc)) 130 | (else (cons (proc a (car acc)) acc)))) 131 | '() 132 | (reverse lst))) 133 | 134 | 135 | (define (sorted? lst) 136 | (all? (adjacent-map <= lst))) 137 | 138 | 139 | (define (sum lst) 140 | (foldl + 0 lst)) 141 | 142 | 143 | (define tail cdr) 144 | 145 | 146 | (define (zip lst . lsts) 147 | (apply map list lst lsts)) 148 | 149 | 150 | (define (zip-with proc list1 . lists) 151 | (apply map proc list1 lists)) 152 | 153 | 154 | (module+ test 155 | ;; Any code in this `test` submodule runs when this file is run using DrRacket 156 | ;; or with `raco test`. The code here does not run when this file is 157 | ;; required by another module. 158 | 159 | ;; Unit tests for adjacent-map 160 | (check-equal? (adjacent-map + (range 5)) '(1 3 5 7)) 161 | (check-equal? (adjacent-map - (range 5)) (repeat 4 -1)) 162 | (check-equal? (adjacent-map * (range 5)) '(0 2 6 12)) 163 | 164 | ;; Unit tests for all? 165 | (check-equal? (all? '()) #t) 166 | (check-equal? (all? '(#t)) #t) 167 | (check-equal? (all? '(#t #t #t #t)) #t) 168 | (check-equal? (all? '(#t #t #t #f)) #f) 169 | (check-equal? (all? (map positive? '(1 2 3))) #t) 170 | (check-equal? (all? (map positive? (range 3))) #f) 171 | 172 | ;; Unit tests for any? 173 | (check-equal? (any? '()) #f) 174 | (check-equal? (any? '(#t)) #t) 175 | (check-equal? (any? '(#f #f #f #t)) #t) 176 | (check-equal? (any? '(#f #f)) #f) 177 | (check-equal? (any? (map positive? '(-1 -2 3))) #t) 178 | (check-equal? (any? (map positive? (range 2))) #t) 179 | 180 | ;; Unit tests for chunk-by 181 | (check-equal? (chunk-by eq? '(1 1 3 2 2)) '((1 1) (3) (2 2))) 182 | (check-equal? (chunk-by < '(1 2 1 3 4 3)) '((1 2) (1 3 4) (3))) 183 | 184 | ;; Unit tests for chunks-of 185 | (check-equal? (chunks-of '(1 2 1 3 4 3) 2) '((1 2) (1 3) (4 3))) 186 | (check-equal? (chunks-of '(1 2 1 3 4 3) 3) '((1 2 1) (3 4 3))) 187 | 188 | ;; Unit tests for generate 189 | (check-equal? (generate 3 (λ () 1)) '(1 1 1)) 190 | (check-equal? (generate 0 (λ () 1)) '()) 191 | 192 | ;; Unit tests for increasing? 193 | (check-equal? (increasing? '(1)) #t) 194 | (check-equal? (increasing? '(1 2)) #t) 195 | (check-equal? (increasing? '(1 1)) #f) 196 | (check-equal? (increasing? (range 10)) #t) 197 | (check-equal? (increasing? '(2 1 2 1)) #f) 198 | 199 | ;;Unit tests for init 200 | (check-equal? (init '(1 2 3 4)) '(1 2 3)) 201 | (check-equal? (init '(1)) '()) 202 | 203 | ;;Unit tests for juxt 204 | (check-equal? ((juxt + *) 2 3) '(5 6)) 205 | (check-equal? ((juxt first last) '(1 2 3)) '(1 3)) 206 | (check-equal? ((juxt zip append) '(1 2 3) '(4 5 6)) '(((1 4) (2 5) (3 6)) (1 2 3 4 5 6))) 207 | 208 | ;; Unit tests for product 209 | (check-equal? (product '(3 2 1)) 6) 210 | (check-equal? (product (range 1 11)) 3628800) 211 | (check-equal? (product (range 1 6)) 120) 212 | 213 | ;; Unit tests for repeat 214 | (check-equal? (repeat 3 1) '(1 1 1)) 215 | (check-equal? (repeat 4 2) '(2 2 2 2)) 216 | (check-equal? (repeat 2 "abc") '("abc" "abc")) 217 | (check-equal? (repeat 2 '(1 2)) '((1 2) (1 2))) 218 | 219 | ;; Unit tests for replicate 220 | (check-equal? (replicate '(1 0 1) '(a b c)) '(a c)) 221 | (check-equal? (replicate '(0 1 2) '(a b c)) '(b c c)) 222 | (check-equal? (replicate (range 5) '(a b c d e)) '(b c c d d d e e e e)) 223 | (check-equal? (replicate (repeat 5 2) '(a b c d e)) '(a a b b c c d d e e)) 224 | (check-equal? (replicate (repeat 5 3) '(a b c d e)) '(a a a b b b c c c d d d e e e)) 225 | 226 | ;; Unit tests for scanl 227 | (check-equal? (scanl + '(1 2 3 4)) '(1 3 6 10)) 228 | (check-equal? (scanl * '(1 2 3 4)) '(1 2 6 24)) 229 | 230 | ;; Unit tests for scanr 231 | (check-equal? (scanr + '(1 2 3 4)) '(10 9 7 4)) 232 | (check-equal? (scanr * '(1 2 3 4)) '(24 24 12 4)) 233 | 234 | ;; Unit tests for sliding 235 | (check-equal? (sliding '(1 2 3 4) 2) '((1 2) (2 3) (3 4))) 236 | (check-equal? (sliding '(1 2 3 4 5) 2 3) '((1 2) (4 5))) 237 | (check-equal? (sliding '(1 2) 2 2) '((1 2))) 238 | (check-equal? (sliding '(1 2 3) 1 3) '((1 2 3))) 239 | (check-exn 240 | #rx"step has to be equal to or smaller than length of the list" 241 | (thunk (sliding '(1 2 3) 1 4))) 242 | 243 | ;; Unit tests for sorted? 244 | (check-equal? (sorted? '(1)) #t) 245 | (check-equal? (sorted? '(1 2)) #t) 246 | (check-equal? (sorted? '(1 1)) #t) 247 | (check-equal? (sorted? (range 10)) #t) 248 | (check-equal? (sorted? '(2 1 2 1)) #f) 249 | 250 | ;; Unit tests for sum 251 | (check-equal? (sum '(3 2 1)) 6) 252 | (check-equal? (sum (range 11)) 55) 253 | (check-equal? (sum (range 1 7)) 21) 254 | 255 | ;; Unit tests for tail 256 | (check-equal? (tail (range 3)) '(1 2)) 257 | (check-equal? (tail (range 4)) '(1 2 3)) 258 | (check-equal? (tail '(10 9)) '(9)) 259 | 260 | ;; Unit tests for zip 261 | (check-equal? (zip '(0 2) '(1 3)) (chunks-of (range 4) 2)) 262 | (check-equal? (zip '(0 1) '(2 3)) '((0 2) (1 3))) 263 | (check-equal? (zip '(0 1) '(2 3) '(5 7)) '((0 2 5) (1 3 7))) 264 | (check-equal? (zip '() '() '()) '()) 265 | (check-equal? (zip (range 4)) '((0) (1) (2) (3))) 266 | 267 | ;; Unit tests for zip-with 268 | (check-equal? (zip-with + '(0 2) '(1 3)) '(1 5)) 269 | (check-equal? (zip-with + '(0 1) '(2 3)) '(2 4)) 270 | (check-equal? (zip-with * '(0 1) '(2 3) '(4 5)) '(0 15)) 271 | (check-equal? (zip-with - '(0 1) '(2 3) '(4 5)) '(-6 -7))) 272 | -------------------------------------------------------------------------------- /scribblings/algorithms.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | @(require (for-label racket 3 | (only-in algorithms))) 4 | 5 | @title{algorithms} 6 | @author{Conor Hoekstra} 7 | 8 | @defmodule[algorithms] 9 | 10 | A package containing many useful algorithms (borrowed from many other programming languages). 11 | 12 | There is a GNU Guile scheme @hyperlink["https://guile-algorithms.lajszczak.dev/"]{version of this package}. 13 | 14 | @defproc[(adjacent-map [proc (-> any/c any/c any/c)] [lst list?]) (listof any/c)]{ 15 | @margin-note{This algorithm is similar to Haskell's 16 | @hyperlink["https://hackage.haskell.org/package/utility-ht-0.0.15/docs/Data-List-HT.html#v:mapAdjacent"]{mapAdjacent}.} 17 | Returns a list of elements after apply @racket[proc] to adjacent elements. 18 | 19 | Examples: 20 | @codeblock|{ 21 | > (adjacent-map * '(1 2 3 4 5 6)) 22 | '(2 6 12 20 30) 23 | > (adjacent-map < '(1 2 1 3 4 3)) 24 | '(#t #f #t #t #f) 25 | }|} 26 | 27 | @defproc[(all? [lst (listof boolean?)]) (boolean?)]{ 28 | @margin-note{This algorithm is similar to Python's 29 | @hyperlink["https://docs.python.org/3/library/functions.html#all"]{all}.} 30 | Returns @racket[#t] if all the elements of @racket[lst] are @racket[#t], otherwise returns @racket[#f]. 31 | 32 | Examples: 33 | @codeblock|{ 34 | > (all? '(#t #t #t)) 35 | #t 36 | > (all? '(#t #t #f)) 37 | #f 38 | }|} 39 | 40 | @defproc[(any? [lst (listof boolean?)]) (boolean?)]{ 41 | @margin-note{This algorithm is similar to Python's 42 | @hyperlink["https://docs.python.org/3/library/functions.html#any"]{any}.} 43 | Returns @racket[#t] if any of the elements of @racket[lst] are @racket[#t], otherwise returns @racket[#f]. 44 | 45 | Examples: 46 | @codeblock|{ 47 | > (any? '(#f #t #f)) 48 | #t 49 | > (any? '(#f #f #f)) 50 | #f 51 | }|} 52 | 53 | @defproc[(chunk-by [pred (-> any/c any/c boolean?)] [lst list?]) list?]{ 54 | @margin-note{This algorithm is similar to C++'s 55 | @hyperlink["https://en.cppreference.com/w/cpp/ranges/chunk_by_view"]{chunk_by_view}.} 56 | Takes a binary predicate @racket[pred] and a list @racket[lst], and partitions @racket[lst] into sublists (chunks) based 57 | on the predicate. The list is split between each pair of adjacent elements for which @racket[pred] returns @racket[#f]. 58 | The first element of each such pair belongs to the current chunk, and the second element starts the next chunk. 59 | 60 | Examples: 61 | @codeblock|{ 62 | > (chunk-by eq? '(1 1 3 2 2)) 63 | '((1 1) (3) (2 2)) 64 | > (chunk-by < '(1 2 1 3 4 3)) 65 | '((1 2) (1 3 4) (3)) 66 | }|} 67 | 68 | @defproc[(chunks-of [lst list?] [k exact-nonnegative-integer?]) (listof list?)]{ 69 | @margin-note{This algorithms is the same as Haskell's 70 | @hyperlink["https://hackage.haskell.org/package/split-0.2.3.4/docs/Data-List-Split.html#v:chunksOf"]{chunksOf}. 71 | and similar to Python's @hyperlink["https://docs.python.org/3/library/itertools.html#itertools.batched"]{itertools.batched}} 72 | Returns a list of lists of @racket[k] elements each. 73 | Note that this is a specialization of @racket[sliding] where @racket[size] is equal to @racket[step]. 74 | 75 | Examples: 76 | @codeblock|{ 77 | > (chunks-of '(1 2 1 3 4 3) 2) 78 | '((1 2) (1 3) (4 3)) 79 | > (chunks-of '(1 2 1 3 4 3) 3) 80 | '((1 2 1) (3 4 3)) 81 | }|} 82 | 83 | @defproc[(generate [n exact-nonnegative-integer?] [proc (-> any/c)]) (listof any/c)]{ 84 | @margin-note{This algorithm is similar to C++'s 85 | @hyperlink["https://en.cppreference.com/w/cpp/algorithm/generate"]{generate}.} 86 | Returns a list of @racket[n] elements generated from invoking @racket[proc] @racket[n] times. 87 | 88 | Examples: 89 | @codeblock|{ 90 | > (generate 3 *) 91 | '(1 1 1) 92 | > (generate 3 +) 93 | '(0 0 0) 94 | }|} 95 | 96 | @defproc[(increasing? [lst (listof real?)]) (boolean?)]{ 97 | Returns @racket[#t] if all the elements of @racket[lst] are strictly increasing, 98 | otherwise returns @racket[#f]. 99 | 100 | Examples: 101 | @codeblock|{ 102 | > (increasing? '(1 2 3 4)) 103 | #t 104 | > (increasing? '(1 2 3 5)) 105 | #t 106 | > (increasing? '(1 2 2 3)) 107 | #f 108 | }|} 109 | 110 | @defproc[(init [lst list?]) list?]{ 111 | @margin-note{This algorithm comes from Haskell's 112 | @hyperlink["https://hackage.haskell.org/package/base-4.14.0.0/docs/Prelude.html#v:init"]{init}.} 113 | Return all the elements of a list except the last one. 114 | 115 | Examples: 116 | @codeblock|{ 117 | > (init '(1 2 3 4)) 118 | '(1 2 3) 119 | > (init '((1 2) (3 4) (5 6))) 120 | '((1 2) (3 4)) 121 | }|} 122 | 123 | @defproc[(juxt [proc (procedure?)] ...) procedure?]{ 124 | @margin-note{This algorithm comes from Clojure's 125 | @hyperlink["https://clojuredocs.org/clojure.core/juxt"]{juxt}.} 126 | Takes variable number of procedures and returns a procedure that is the juxtaposition 127 | of those procedures. The returned procedure takes a variable number of arguments, and 128 | returns a list containing the result of applying each procedures to the 129 | arguments. 130 | 131 | Examples: 132 | @codeblock|{ 133 | > ((juxt first last) '(1 2 3)) 134 | '(1 3) 135 | > ((juxt + *) 1 2 3 4) 136 | '(10 24) 137 | > ((juxt zip append) '(1 2 3) '(4 5 6)) 138 | '(((1 4) (2 5) (3 6)) (1 2 3 4 5 6)) 139 | }|} 140 | 141 | @defproc[(product [lst (listof real?)]) real?]{ 142 | Returns the product of the elements in @racket[lst]. 143 | 144 | Examples: 145 | @codeblock|{ 146 | > (product '(1 2 3)) 147 | 6 148 | > (product '(1 2 3 4)) 149 | 24 150 | }|} 151 | 152 | @defproc[(repeat [n exact-nonnegative-integer?] [val any/c?]) list?]{ 153 | @margin-note{This algorithms is the same as Clojures's 154 | @hyperlink["https://clojuredocs.org/clojure.core/repeat"]{repeat} and D's 155 | @hyperlink["https://dlang.org/library/std/range/repeat.html#0"]{repeat}.} 156 | Returns a list of @racket[val] repeated @racket[n] times. 157 | 158 | Examples: 159 | @codeblock|{ 160 | > (repeat 5 #t) 161 | '(#t #t #t #t #t) 162 | > (repeat 5 '()) 163 | '(() () () () ()) 164 | }|} 165 | 166 | @defproc[(replicate [lst (listof exact-nonnegative-integer?)] [lst2 list?]) list?]{ 167 | @margin-note{This algorithms is the similar to APL's 168 | @hyperlink["https://microapl.com/apl_help/ch_020_020_840.htm"]{replicate.}} 169 | Returns a list of of the @racket[lst2] values each repeated n times where n is the corresponding element in @racket[lst]. 170 | 171 | Examples: 172 | @codeblock|{ 173 | > (replicate '(1 0 1) '(a b c)) 174 | '(a c) 175 | > (replicate '(0 1 2) '(a b c)) 176 | '(b c c) 177 | }|} 178 | 179 | @defproc[(scanl [lst list?]) list?]{ 180 | @margin-note{This algorithm originally comes from APL's monadic 181 | @hyperlink["http://microapl.com/apl_help/ch_020_020_820.htm"]{\ scan} operator. It is more similar to Haskell's 182 | @hyperlink["https://hackage.haskell.org/package/base-4.14.0.0/docs/Prelude.html#v:scanl1"]{scanl1} however.} 183 | @racket[scanl] is similar to @racket[foldl], but returns a list of successive reduced values from the left. 184 | 185 | Examples: 186 | @codeblock|{ 187 | > (scanl + '(1 2 3 4)) 188 | '(1 3 6 10) 189 | > (scanl * '(1 2 3 4)) 190 | '(1 2 6 24) 191 | }|} 192 | 193 | @defproc[(scanr [lst list?]) list?]{ 194 | @margin-note{This algorithm originally comes from APL's monadic 195 | @hyperlink["http://microapl.com/apl_help/ch_020_020_820.htm"]{\ scan} operator. It is more similar to Haskell's 196 | @hyperlink["https://hackage.haskell.org/package/base-4.14.0.0/docs/Prelude.html#v:scanr1"]{scanr1} however.} 197 | @racket[scanr] is similar to @racket[foldr], but returns a list of successive reduced values from the right. 198 | 199 | Examples: 200 | @codeblock|{ 201 | > (scanr + '(1 2 3 4)) 202 | '(10 9 7 4) 203 | > (scanr * '(1 2 3 4)) 204 | '(24 24 12 4) 205 | }|} 206 | 207 | @defproc[(sliding [lst list?] [size exact-nonnegative-integer?] [step exact-nonnegative-integer? 1]) (listof list?)]{ 208 | @margin-note{This algorithm is the same as Haskell's 209 | @hyperlink["https://hackage.haskell.org/package/split-0.2.3.4/docs/Data-List-Split.html#v:divvy"]{divvy}, Clojure's 210 | @hyperlink["https://clojuredocs.org/clojure.core/partition"]{partition} and D's 211 | @hyperlink["https://dlang.org/library/std/range/slide.html"]{slide}.} 212 | Returns a list of lists of @racket[size] elements each, at offset @racket[step] apart. 213 | 214 | @racket[step] has to be equal to or smaller than length of the @racket[lst]. 215 | 216 | Examples: 217 | @codeblock|{ 218 | > (sliding '(1 2 3 4) 2) 219 | '((1 2) (2 3) (3 4)) 220 | > (sliding '(1 2 3 4 5) 2 3) 221 | '((1 2) (4 5)) 222 | > (sliding '(1 2) 2 2) 223 | '((1 2)) 224 | }|} 225 | 226 | @defproc[(sorted? [lst list?]) (boolean?)]{ 227 | @margin-note{This algorithm is similar to C++'s 228 | @hyperlink["https://en.cppreference.com/w/cpp/algorithm/is_sorted"]{std::is_sorted}.} 229 | Returns @racket[#t] if all the elements of @racket[lst] are in sorted order, otherwise returns @racket[#f]. 230 | 231 | Examples: 232 | @codeblock|{ 233 | > (sorted? '(1 2 3 4)) 234 | #t 235 | > (sorted? '(1 2 3 3)) 236 | #t 237 | > (sorted? '(1 2 3 2)) 238 | #f 239 | }|} 240 | 241 | @defproc[(sum [lst (listof real?)]) real?]{ 242 | Returns the sum of the elements in @racket[lst]. 243 | 244 | Examples: 245 | @codeblock|{ 246 | > (sum '(1 2 3 4)) 247 | 10 248 | > (sum '()) 249 | 0 250 | }|} 251 | 252 | @defproc[(tail [lst list?]) list?]{ 253 | @margin-note{This algorithm comes from Haskell's 254 | @hyperlink["https://hackage.haskell.org/package/base-4.14.0.0/docs/Prelude.html#v:tail"]{tail}.} 255 | Return all the elements of a list except the first one. 256 | 257 | Note: this is the same as Racket's @racket[cdr] and @racket[rest] and therefore isn't really necessary. 258 | 259 | Examples: 260 | @codeblock|{ 261 | > (tail '(1 2 3)) 262 | '(2 3) 263 | > (tail '(1)) 264 | '() 265 | }|} 266 | 267 | @defproc[(zip [lst list?] ...) (listof list?)]{ 268 | @margin-note{This algorithm is similar to Haskell's 269 | @hyperlink["https://hackage.haskell.org/package/base-4.14.0.0/docs/Prelude.html#v:zip"]{zip} 270 | and Python's @hyperlink["https://docs.python.org/3/library/functions.html#zip"]{zip}.} 271 | Returns a list of lists of elements from each of lists passed to the procedure. 272 | 273 | Another way to think of @racket[zip] is that it turns rows into columns, and columns into rows. 274 | This is similar to @hyperlink["https://en.wikipedia.org/wiki/Transpose"]{transposing a matrix}. 275 | 276 | Examples: 277 | @codeblock|{ 278 | > (zip '(1 2 3) '(4 5 6)) 279 | '((1 4) (2 5) (3 6)) 280 | > (zip '() '()) 281 | '() 282 | > (zip '(0 1) '(2 3) '(5 7)) 283 | '((0 2 5) (1 3 7)) 284 | }|} 285 | 286 | @defproc[(zip-with [proc (-> any/c ... any/c)] [lst list?] ...) (listof any/c)]{ 287 | @margin-note{This algorithm is similar to Haskell's 288 | @hyperlink["https://hackage.haskell.org/package/base-4.14.0.0/docs/Prelude.html#v:zipWith"]{zipWith}.} 289 | Returns a list after zipping together the variadic number of @racket[lst]s and applying @racket[proc] 290 | to each of the "zipped together" elements. 291 | 292 | Examples: 293 | @codeblock|{ 294 | > (zip-with + '(1 2 3) '(4 5 6)) 295 | '(5 7 9) 296 | > (zip-with + '(1 2 3) '(4 5 6) '(7 8 9)) 297 | '(12 15 18) 298 | }|} 299 | --------------------------------------------------------------------------------