nani/website/modules/nani/trie.scm

trie.scm

1
;;; Nani Project website
2
;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
3
;;;
4
;;; This file is part of the Nani Project website.
5
;;;
6
;;; The Nani Project website is free software; you can redistribute it and/or modify it
7
;;; under the terms of the GNU Affero General Public License as published by
8
;;; the Free Software Foundation; either version 3 of the License, or (at
9
;;; your option) any later version.
10
;;;
11
;;; The Nani Project website is distributed in the hope that it will be useful, but
12
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
;;; GNU Affero General Public License for more details.
15
;;;
16
;;; You should have received a copy of the GNU Affero General Public License
17
;;; along with the Nani Project website.  If not, see <http://www.gnu.org/licenses/>.
18
19
(define-module (nani trie)
20
  #:use-module (srfi srfi-9)
21
  #:export (make-trie
22
            trie?
23
            trie-position
24
            trie-position-set!
25
            trie-vals
26
            trie-vals-set!
27
            trie-transitions
28
            trie-transitions-set!
29
            
30
            make-empty-trie
31
            add-to-trie!
32
            compress-trie))
33
34
(define-record-type trie
35
  (make-trie position vals transitions)
36
  trie?
37
  (position trie-position trie-position-set!) ; integer
38
  (vals trie-vals trie-vals-set!) ; list
39
  (transitions trie-transitions trie-transitions-set!)) ; array or alist
40
41
(define (make-empty-trie)
42
  (make-trie 0 '() (make-array #f 16)))
43
44
(define (add-to-trie! trie key value)
45
  (if (null? key)
46
    (trie-vals-set! trie (cons value (trie-vals trie)))
47
    (let ((next-trie (array-ref (trie-transitions trie) (car key))))
48
      (if next-trie
49
          (add-to-trie! next-trie (cdr key) value)
50
          (let ((next-trie (make-empty-trie)))
51
            (array-set! (trie-transitions trie) next-trie (car key))
52
            (add-to-trie! next-trie (cdr key) value))))))
53
54
(define (convert-trie-transitions! trie)
55
  (define (get-new-transitions transitions)
56
    (let loop ((i 0) (tr '()))
57
      (if (= i 16)
58
        tr
59
        (let ((elem (array-ref transitions i)))
60
          (if elem
61
            (begin
62
              (convert-trie-transitions! elem)
63
              (loop (+ i 1) (cons (cons i elem) tr)))
64
            (loop (+ i 1) tr))))))
65
  (let* ((transitions (trie-transitions trie))
66
         (transitions (get-new-transitions transitions)))
67
    (trie-transitions-set! trie transitions)))
68
69
(define (compress-trie trie)
70
  (define (compress-aux trie)
71
    (make-trie
72
      (trie-position trie)
73
      (trie-vals trie)
74
      (apply append
75
        (map
76
          (lambda (tr)
77
            (let ((trie (cdr tr)))
78
              (map
79
                (lambda (tr2)
80
                  (cons (+ (car tr2) (* 16 (car tr)))
81
                        (compress-aux (cdr tr2))))
82
                (trie-transitions trie))))
83
          (trie-transitions trie)))))
84
  (convert-trie-transitions! trie)
85
  (compress-aux trie))
86