Uppgift 6A - Frekvenstabell (defstruct par element antal) (defun unika-element (lista) (reduce #'(lambda (x y) (if (listp x) (if (find y x) x (cons y x)) (if (eq x y) x (list x y)))) lista)) (defun sortera-tabell (tabell) (sort tabell #'(lambda (x y) (> (par-antal x) (par-antal y))))) (defun frekvens (lista) (let* ((unika (unika-element lista)) (array (make-array (length unika)))) (dotimes (i (length unika)) (setf (aref array i) (make-par :element (nth i unika) :antal (count (nth i unika) lista)))) (sortera-tabell array))) Körexempel CL-USER(5): (frekvens '(a b a c d b a b d a)) #(#S(PAR :ELEMENT A :ANTAL 4) #S(PAR :ELEMENT B :ANTAL ) #S(PAR :ELEMENT D :ANTAL 2) #S(PAR :ELEMENT C :ANTAL 1)) CL-USER(6): (frekvens '(a b c d r d a c b a d c a)) #(#S(PAR :ELEMENT A :ANTAL 4) #S(PAR :ELEMENT D :ANTAL ) #S(PAR :ELEMENT C :ANTAL ) #S(PAR :ELEMENT B :ANTAL 2) #S(PAR :ELEMENT R :ANTAL 1)) 2007-01-11! 1
Uppgift 6B - Ändra representation på almanackan ; ============ Klockslag ============ (defstruct klockslag timme minut) (defun skapa-klockslag (timme minut) "timme x minut -> klockslag" (typkontroll timme #'timme?) (typkontroll minut #'minut?) (cond ((> (heltal timme) 2) (error "~&SKAPA-KLOCKSLAG: Timmen ~s är ej giltig." (packa-upp timme))) ((> (heltal minut) 59) (error "~&SKAPA-KLOCKSLAG: Minuten ~s är ej giltig." (packa-upp minut))) (t (packa-ihop 'klockslag (make-klockslag :timme timme :minut minut))))) (defun timdel (tidsrymd/klockslag) "tidsrymd U klockslag -> timme" (cond ((tidsrymd? tidsrymd/klockslag) (first (packa-upp tidsrymd/klockslag))) ((klockslag? tidsrymd/klockslag) (klockslag-timme (packa-upp tidsrymd/klockslag))) (t (error "~&TIMDEL: Argument ska vara tidsrymd eller klockslag.")))) (defun minutdel (tidsrymd/klockslag) "tidsrymd U klockslag -> minut" (cond ((tidsrymd? tidsrymd/klockslag) (second (packa-upp tidsrymd/klockslag))) ((klockslag? tidsrymd/klockslag) (klockslag-minut (packa-upp tidsrymd/klockslag))) (t (error "~&MINUTDEL: Argument ska vara tidsrymd el. klockslag.")))) ; ============ Tidsperiod ============ (defstruct tidsperiod start slut) (defun skapa-tidsperiod (kl1 kl2) "klockslag x klockslag -> tidsperiod" (typkontroll kl1 #'klockslag?) (typkontroll kl2 #'klockslag?) (cond ((samma-klockslag? kl1 kl2) (error "~&SKAPA-TIDSPERIOD: Klockslagen är samma.")) ((not (före-klockslag? kl1 kl2)) (error "~&SKAPA-TIDSPERIOD: Klockslagen är i fel ordning.")) 2007-01-11! 2
(t (packa-ihop 'tidsperiod (make-tidsperiod :start kl1 :slut kl2))))) (defun start-klockslag (tidsperiod) "tidsperiod -> klockslag" (typkontroll tidsperiod #'tidsperiod?) (tidsperiod-start (packa-upp tidsperiod))) (defun slut-klockslag (tidsperiod) "tidsperiod -> klockslag" (typkontroll tidsperiod #'tidsperiod?) (tidsperiod-slut (packa-upp tidsperiod))) ; ============ Månadsalmanacka ============ (defun skapa-månadsalmanacka () "-> månadsalmanacka" (packa-ihop 'månadsalmanacka (make-array 1))) (defun tom-månadsalmanacka? (månalma) "månadsalmanacka -> sanningsvärde" (typkontroll månalma #'månadsalmanacka?) (notany #'(lambda (x) x) (packa-upp månalma))) ; Ändrade från (not (some)). veeerkar funka.. (defun lägg-in-dagalmanacka (dag dagalma månalma) "dag x dagalmanacka x månadsalmanacka -> månadsalmanacka" (typkontroll dag #'dag?) (typkontroll dagalma #'dagalmanacka?) (typkontroll månalma #'månadsalmanacka?) (setf (aref (packa-upp månalma) (1- (dagnummer dag))) dagalma) månalma) (defun dagalmanacka (dag månalma) "dag x månadsalmanacka -> dagalmanacka" (typkontroll dag #'dag?) (typkontroll månalma #'månadsalmanacka?) (let ((dag (aref (packa-upp månalma) (1- (dagnummer dag))))) (if (null dag) (skapa-dagalmanacka) dag))) 2007-01-11!
; Otroligt jobbig funktion. borde finnas bättre lösning...! (defun sista-tomma-elementindex (sekv) (let* ((rsekv (reverse sekv)) (icketomma (remove-if-not #'(lambda (x) x) rsekv))) (if (= (length icketomma) 0) -1 (- (length sekv) (position (elt icketomma 0) rsekv) 1)))) (defun sista-dagnummer (månalma) "månadsalmanacka -> heltal" (typkontroll månalma #'månadsalmanacka?) (1+ (sista-tomma-elementindex (packa-upp månalma)))) ; ============ Årsalmanacka ============ (defun tom-årsalmanacka? (årsalma) "årsalmanacka -> sanningsvärde" (typkontroll årsalma #'årsalmanacka?) (not (some #'(lambda (x) x) (packa-upp årsalma)))) (defun skapa-årsalmanacka () "-> årsalmanacka" (packa-ihop 'årsalmanacka (make-array 12))) (defun lägg-in-månadsalmanacka (mån månalma årsalma) "månad x månadsalmanacka x årsalmanacka -> årsalmanacka" (typkontroll mån #'månad?) (typkontroll månalma #'månadsalmanacka?) (typkontroll årsalma #'årsalmanacka?) (cond ((tom-månadsalmanacka? månalma) årsalma) ((> (sista-dagnummer månalma) (antal-dagar-i-månad mån)) (error "~&LÄGG-IN-MÅNADSALMANACKA: För få dagar i ~a." (månadsnamn mån))) (t (progn (setf (aref (packa-upp årsalma) (1- (månadsnummer mån))) månalma) årsalma)))) 2007-01-11! 4
(defun månadsalmanacka (mån årsalma) "månad x årsalmanacka -> månadsalmanacka" (typkontroll mån #'månad?) (typkontroll årsalma #'årsalmanacka?) (let ((månadsalma (aref (packa-upp årsalma) (1- (månadsnummer mån))))) (if (null månadsalma) (skapa-månadsalmanacka) månadsalma))) Körexempel CL-USER(68): (skapa 'tomasf) En ny almanacka med namnet TOMASF har skapats. CL-USER(69): (boka 'tomasf 14 'sep "10:00" "12:00" "Koda") Mötet är bokat. CL-USER(70): (visa 'tomasf 14 'sep) 14 SEPTEMBER ============ 10:00-12:00 Koda CL-USER(71): (boka 'tomasf 14 'sep "1:00" ":00" "Koda MERA") Mötet är bokat. CL-USER(72): (ledigt 'tomasf 14 'sep "08:00" "17:00") 08:00-10:00 12:00-1:00 :00-17:00 CL-USER(7): (avboka 'tomasf 14 'sep "10:00") Mötet är avbokat. CL-USER(74): (visa 'tomasf 14 'sep) 14 SEPTEMBER ============ 1:00-:00 Koda MERA 2007-01-11! 5
Uppgift 6C - Makro för setlistq (defmacro setlistq-1 (vars val) (list 'let (list (list 'värde val)) (cons 'prog1 (mapcar #'(lambda (x) (list 'setq x 'värde)) vars)))) (defmacro setlistq-2 (vars val) (list 'let (list (list 'värde val)) `(dolist (var ',vars) (set var värde)))) (defmacro setlistq- (vars val) (if (endp vars) nil (list 'let (list (list 'värde val)) `(progn (setq,(first vars) värde) (setlistq-,(rest vars) värde))))) Körexempel CL-USER(11): (setlistq-1 (a b c) ) CL-USER(12): a CL-USER(1): b CL-USER(14): c CL-USER(): (setlistq-1 (a b c) (progn (format t "Värde: ") (read))) Värde: CL-USER(16): a CL-USER(17): b CL-USER(18): c CL-USER(19): (macroexpand-1 '(setlistq-1 (a b c) (progn (format t "Värde: ") ad)))) (LET ((VäRDE (PROGN (FORMAT T "Värde: ") (READ)))) (PROG1 (SETQ A VäRDE) (SETQ B VäRDE) (SETQ C VäRDE))) T - - - - - - - - - - 2007-01-11! 6
CL-USER(20): (setlistq-2 (a b c) ) CL-USER(21): a CL-USER(22): b CL-USER(2): c CL-USER(24): (setlistq-2 (a b c) (progn (format t "Värde: ") (read))) Värde: CL-USER(25): a CL-USER(26): b CL-USER(27): c CL-USER(28): (macroexpand-1 '(setlistq-2 (a b c) (progn (format t "Värde: ") ad)))) (LET ((VäRDE (PROGN (FORMAT T "Värde: ") (READ)))) (DOLIST (VAR '(A B C)) (SET VAR VäRDE))) T - - - - - - - - - - CL-USER(29): (setlistq- (a b c) ) CL-USER(0): a CL-USER(1): b CL-USER(2): c CL-USER(): (setlistq- (a b c) (progn (format t "Värde: ") (read))) Värde: CL-USER(4): a CL-USER(5): b CL-USER(6): c CL-USER(7): (macroexpand-1 '(setlistq- (a b c) (progn (format t "Värde: ") ad)))) (LET ((VäRDE (PROGN (FORMAT T "Värde: ") (READ)))) (PROGN (SETQ A VäRDE) (SETLISTQ- (B C) VäRDE))) T 2007-01-11! 7
Uppgift 6D - Det elektroniska minnet (defun empty-symbol-table () (cons nil nil)) (defun is-empty? (symbol-table) (or (endp symbol-table) (and (null (car symbol-table)) (null (cdr symbol-table))))) (defun has-value? (variable symbol-table) (not (null (assoc variable symbol-table)))) (defun add-binding! (variable value symbol-table) (let ((cell (list (cons variable value)))) (if (is-empty? symbol-table) (setf (car symbol-table) (car cell)) (setf (cdr (last symbol-table)) cell)))) (defun set-value! (variable value symbol-table) (if (has-value? variable symbol-table) (setf (cdr (assoc variable symbol-table)) value) (error "~a does not exist in the symbol table." variable))) (defun get-value (variable symbol-table) (cdr (assoc variable symbol-table))) (defun delete-bindings! (variable symbol-table) (let ((new (remove-if #'(lambda (x) (eq (first x) variable)) symbol-table))) (if (endp new) (progn (setf (car symbol-table) nil) (setf (cdr symbol-table) nil)) (progn (setf (car symbol-table) (car new)) (setf (cdr symbol-table) (cdr new))))) variable) (defun print-all-bindings (symbol-table) (if (is-empty? symbol-table) 'done (progn (format t "~a = ~a~%" (car (first symbol-table)) (cdr (first symbol-table))) (print-all-bindings (rest symbol-table))))) 2007-01-11! 8
Körexempel CL-USER(68): (setq tab (empty-symbol-table)) () CL-USER(69): (has-value? 'x tab) CL-USER(70): (add-binding! 'x 17 tab) (X. 17) CL-USER(71): (has-value? 'x tab) T CL-USER(72): (get-value 'x tab) 17 CL-USER(7): (add-binding! 'q 5 tab) (Q. 5) CL-USER(74): (get-value 'q tab) 5 CL-USER(75): (print-all-bindings tab) X = 17 Q = 5 DONE CL-USER(76): (add-binding! 'x 99 tab) (X. 99) CL-USER(77): (get-value 'x tab) 17 CL-USER(81): (set-value! 'x 77 tab) 77 CL-USER(82): (print-all-bindings tab) X = 77 Q = 5 X = 99 DONE CL-USER(8): (delete-bindings! 'x tab) X CL-USER(84): (has-value? 'x tab) - - - - - - - - - - CL-USER(85): (setq tab-one (empty-symbol-table)) () CL-USER(86): (setq tab-two (empty-symbol-table)) () CL-USER(87): (add-binding! 'x 10 tab-two) (X. 10) CL-USER(88): (get-value 'x tab-one) - - - - - - - - - - 2007-01-11! 9
CL-USER(89): (setq tab-list (list (empty-symbol-table) (empty-symbol-table))) (() ()) CL-USER(90): (add-binding! 'w 100 (first tab-list)) (W. 100) CL-USER(91): (add-binding! 'q 10 (second tab-list)) (Q. 10) CL-USER(92): (mapc #'(lambda (tab) (print-all-bindings tab)) tab-list) W = 100 Q = 10 (((W. 100)) ((Q. 10))) 2007-01-11! 10
Initiellt läge för 'tab' ((a. 5) (b. 10)) a 5 b 10 (add-binding! 'c tab) ((a. 5) (b. 10) (c. )) a 5 b 10 c (delete-bindings! 'b tab) ((a. 5) (c. )) a 5 c 2007-01-11! 11