; .EnTete "Programmer en Ceyx" "" "Annexe III: Les Ensembles Ordonne's"
; .Annexe III "Les Ensembles Ordonne's"
; .Auteur "Jean-Marie Hullot"
; .i
; Ce chapitre est un exemple d'utilisation de mode`les auto-type's
; c'est a` dire de'finis par deftype, ...
;
; Toutes les fonctions de'crites ici sont utilisables sous Ceyx a`
; condition d'avoir charge' le fichier union.ll de la bibliothe`que
; Ceyx, qui n'est d'ailleurs pas autre chose que ce chapitre:
; .r
;
; .DebLL 1
; ? (ceyx-load union)
; = union.ll
; .FinLL
; .pp
;
; Nous pre'sentons ici une structure analogue a` la structure de liste
; mais pour laquelle les ope'rations conc et merge (nconc) sont
; re'alise'es en temps constant. Ceci est re'alise' en conservant
; toujours un pointeur vers la dernie`re cellule de la liste (last).
;
; .Section "De'finition et Cre'ation"
; .ps -2
; .TS
; center box tab (|);
; c s
; c c.
; T{
; .ps +1
; \fBLe Type: Union\fR
; .ps -1
; T}
; |
; ←
; ←
; .T&
; c s
; l l.
; \fBFonction de Cre'ation\fR
; Union|list
; ←
; .T&
; c s
; l l.
; \fBChamps\fR
; list|(List ...)
; last|*
; ←
; .T&
; c s
; l l.
; \fBProprie'te's Se'mantiques\fR
; car|(union)
; clear|(union)
; conc|(union x)
; cons|(union x)
; delete|(union x)
; flat|(union)
; last|obj
; list|obj
; member|(union item)
; merge|(union1 union2)
; pop-down|(union item)
; pop-up|(union item)
; .TE
; .ps +2
; Un \fIensemble ordonne'\fR est une structure a` deux champs \fIlist\fR
; et \fIlast\fR telle que:
; - \fIlist\fR pointe toujours vers une liste Lisp,
; - \fIlast\fR pointe vers (last \fIlist\fR).
(deftrecord Union list~(List *) last)
(defaccess Union)
; Pour construire un ensemble ordonne' dont les n premiers e'le'ments
; sont passe's en arguments:
(de Union list
(omakeq Union list list last (last list)))
(defmake {Union} Union)
; \fBExemples:\fR
;
; .DebLL 1
; ? (setq u (Union 'a 'b 'c))
; = #(Union (a b c) c)
; ? ({Union}:list u)
; = (a b c)
; ? ({Union}:last u)
; = (c)
; .FinLL
; .pp
; .Section "Fonctions de Manipulation"
; Le premier e'le'ment:
(de {Union}:car (union)
(car ({Union}:list union)))
(cxcp-inline {Union}:car)
; Pour vider un ensemble ordonne':
(de {Union}:clear (union)
({Union}:list union ())
({Union}:last union ())
union)
; Pour ajouter un e'le'ment en te↑te:
(de {Union}:cons (union x)
(if ({Union}:last union)
({Union}:list union (cons x ({Union}:list union)))
({Union}:list union (list x))
({Union}:last union ({Union}:list union)))
union)
; Pour ajouter un e'le'ment en queue:
(de {Union}:conc (union x)
(if ({Union}:last union)
(progn
(rplacd ({Union}:last union) (list x))
({Union}:last union (cdr ({Union}:last union))))
({Union}:list union (list x))
({Union}:last union ({Union}:list union)))
union)
; \fBExemples:\fR
;
; .DebLL 1
; ? (send 'clear u)
; = #(Union ())
; ? u
; = #(Union ())
; ? (send 'cons u 'b)
; = #(Union (b) b)
; ? (send 'conc u 'c)
; = #(Union (b c) c)
; ? (send 'cons u 'a)
; = #(Union (a b c) c)
; .FinLL
; .pp
; Pour supprimer un e'le'ment:
(demethod {Union}:delete (union x) (list last)
(when list
(if (neq x (car list))
(when (eq (list-delete list x) last)
({Union}:last union (last list)))
({Union}:list union (cdr list))
(when (eq list last) ({Union}:last union ()))))
union)
(de list-delete (list x)
(when (cdr list)
(if (neq (cadr list) x)
(list-delete (cdr list) x)
(prog1 (cdr list)
(rplacd list (cddr list))))))
; \fBExemples:\fR
;
; .DebLL 1
; ? (send 'delete u 'c)
; = #(Union (a b) b)
; ? (send 'delete u 'a)
; = #(Union (b) b)
; ? (send 'conc u (setq x '(1 2 3)))
; = #(Union (b (1 2 3)) (1 2 3))
; ? (send 'delete u '(1 2 3))
; = #(Union (b (1 2 3)) (1 2 3))
; ? (send 'delete u x)
; = #(Union (b) b)
; .FinLL
; .pp
; L'ope'ration de fusion entre deux ensembles ordonne's, le re'sultat de
; la fusion e'tant stocke' dans le premier argument:
(de {Union}:merge (union1 union2)
(if ({Union}:list union1)
(when ({Union}:list union2)
(rplacd ({Union}:last union1) ({Union}:list union2))
({Union}:last union1 ({Union}:last union2)))
(<- union1 union2))
union1)
; Pour aplatir un ensemble ordonne', c'est a` dire effectuer l'ope'ration:
;
; (Union ... (Union a b c) ...) -> (Union ... a b c ...)
;
; autant que possible:
(demethod {Union}:flat (union) (list)
({Union}:clear union)
(while list
(if (eq (type (car list)) 'Union)
({Union}:merge union ({Union}:flat (nextl list)))
({Union}:conc union (nextl list))))
union)
; \fBExemples:\fR
;
; .DebLL 1
; ? (setq u1 (Union 'a 'b 'c))
; = #(Union (a b c) c)
; ? (setq u2 (Union 1 2 3))
; = #(Union (1 2 3) 3)
; ? (send 'merge u1 u2)
; = #(Union (a b c 1 2 3) 3)
; ? u1
; = #(Union (a b c 1 2 3) 3)
; ? u2
; = #(Union (1 2 3) 3)
; ? (setq u3 (Union 'a1 'a2 'a3))
; = #(Union (a1 a2 a3) a3)
; ? (send 'conc u1 u3)
; = #(Union (a b c 1 2 3 #(Union (a1 a2 a3) a3)) #(Union (a1 a2 a3) a3))
; ? (send 'flat u1)
; = #(Union (a b c 1 2 3 a1 a2 a3) a3)
; .FinLL
; .pp
(demethod {Union}:member (union item) (list)
(tag found
(while list (when (eq (nextl list) item) (exit found t)))))
(de {Union}:pop-up (union item)
(when ({Union}:member union item)
({Union}:delete union item)
({Union}:conc union item))
union)
(de {Union}:pop-down (union item)
(when ({Union}:member union item)
({Union}:delete union item)
({Union}:cons union item))
union)