Programeer opdrachtenOpdracht : opdr2_Engelbertus.txt

Terug naar de inzendingen
Opdracht 2,Engelbertus Tijseling
4-Feb-2005
 hierbij mijn "inzending" commentaar in de tekst
 
 oh ja en wederom met dank aan Dirk Gerrits
 
 1 
*****hotellamp.lsp*****
  
 2;;;; Naam van het programma: hotellamp.lsp
 3;;;; Doel van het programma: Saldo berekenen op de bankrekening aan de hand van opgegeven waarden,
 4;;;;                         alsmede het verlies dat geleden wordt door toedoen van de bank.
 5;;;;                         Ook het inkomen (door uitlenen van het geld) van de bank wordt uitgerekend.
 6;;;;                   Dan wordt nog de spaarrente, en de winst van de bank berekend.
 7;;;;
 8;;;; Geschreven door:      - E. Tijseling 
 9;;;;
 10;;;; Dit programma is geschreven naar aanleiding van een programeeropdracht door Pascal Schiks
 11;;;; De opdracht is te lezen op: http://forum.nedlinux.nl/viewtopic.php?p=177811#177811
 12;;;; Deze code is NIET door wat dan ook beschermd en mag door iedereen vrij worden gebruikt
 13;;;;
 14;;;; Gebruik:
 15;;;;
 16;;;; Laad het bestand in je favoriete Commom Lisp implementatie. Met 
 17;;;; CLISP (http://clisp.cons.org/) kun je dit vanaf de commando-prompt
 18;;;; doen op de volgende manier:
 19;;;;
 20;;;; $ clisp hotellamp.lsp
 21;;;;
 22;;;; Na het starten kunt u beginnen met de lampen te bedienen.
 23;;;; Bestudeer de programma-code om de werking te begrijpen en eventueel aan te passen
 24;;;; aan uw situatie
 25;;;;
 26
 27;;(globale) variabelen definieren
 28(defvar *input*)
 29(defvar output)
 30(defvar *plafondlamp*)
 31(defvar *schemerlamp*)
 32
 33;; aan/uit mechanisme voor de opgegeven lamp
 34   ;;; de status van de lamp of het resultaat is hierbij niet belangrijk.
 35(defmacro toggle (lamp)
 36  `(setq ,lamp (* ,lamp -1)))
 37
 38;; alle lampen uitzetten
 39(defun off ()
 40  (setq *plafondlamp* -1)
 41  (setq *schemerlamp* -1))
 42
 43(defun hotellamp ()
 44
 45  ;; situatie na inschakeling van de schakelunit.
 46  ;; uitvoer en de status van de lampen corresponderend, alles uit.
 47  (setq output 0)
 48  (off)
 49  (format t "~&klaar om met de lampen te spelen!")
 50  (format t "~2&(geef voor de simulatie de doorgestuurde integer op.")
 51  (format t "~2&kies een nummer 0 tot 4 of 8 en druk op enter)" )
 52  (format t "~&hieronder de status van de lampen, (. = uit, -x- = aan.)")
 53  (format t "~2&schemerlamp   plafondlamp")
 54 
 55  (show)
 56  ;; van te voren de startsituatie laten zien (simulatie)
 57   
 58  ;; loop starten
 59  (loop
 60   ;; invoer ophalen
 61   (setq *input* (get-input "0-4 of 8: " )) ; input ophalen
 62   ;; input verwerken
 63   (process)
 64   ;; weergeven van de stand van zaken
 65   (show))      ; einde loop
 66  )             ; einde functie
 67
 68(defun show ()                                       ;(format t "~&schemerlamp   plafondlamp")
 69  (if (and (= *schemerlamp* -1) (= *plafondlamp* -1)) (format t "~&     .             .     "))
 70  (if (and (= *schemerlamp* -1) (= *plafondlamp* 1))  (format t "~&     .            -X-    "))
 71  (if (and (= *schemerlamp* 1)  (= *plafondlamp* 1))  (format t "~&    -x-           -X-    "))
 72  (if (and (= *schemerlamp* 1)  (= *plafondlamp* -1)) (format t "~&    -x-            .     ")))
 73 
 74;; input verwerken en output genereren
 75(defun process ()
 76  (when (= *input* 8) (off))
 77  (when (= *input* 4) (check))
 78  (when (= *input* 3) (toggle *plafondlamp*) (toggle *schemerlamp*))
 79  (when (= *input* 2) (toggle *schemerlamp*))
 80  (when (= *input* 1) (toggle *plafondlamp*))
 81  ;; (when (=0 .... ))is niet nodig, omdat er ook geen actie aan gekoppeld is. toch krijgen we de juiste output
 82  ;; input hoeft hier geen variabele te zijn, maar kan een signaal van een apparaat zijn (dus geen integer)
 83  ;; de waarde ervan wordt dus niet door het programma of de hardware onthouden, doch slechts eenmalig beoordeeld
 84
 85  (if (= *schemerlamp* -1)
 86      (if (= *plafondlamp* -1)
 87          (setq output 0)
 88          (setq output 2))
 89      (if (= *plafondlamp* -1)
 90          (setq output 1)
 91          (setq output 3))))
 92
 93;; bepalen wat de "actie" moet zijn op basis van de status van de lampen, en deze verwerken.
 94(defun check()
 95  (cond
 96    ((and (= *schemerlamp* -1) (= *plafondlamp* -1)) (toggle *plafondlamp*)(toggle *schemerlamp*))
 97    ((and (= *schemerlamp* -1) (= *plafondlamp* 1))  (toggle *plafondlamp*))
 98    ((and (= *schemerlamp* 1)  (= *plafondlamp* 1))  (off))
 99    ((and (= *schemerlamp* 1)  (= *plafondlamp* -1)) (toggle *plafondlamp*))))
 100   ;;; ik kies ervoor om de status van de lampen afzonderlijk te beoordelen in plaats van de waarde van output
 101   
 102;; hieronder de routines die invoer ophalen en controleert
 103
 104;; ophalen en kijken of een met de andere routine (hieronder) opgehaalde integer 0,1,2,3,4, of 8 is
 105;; in principe hoef ik niet te kijken of de integer een nul is, omdat daar niets mee wordt gedaan.
 106;; in dit geval sturen we een nul echter wel door naar de rest van het programma, en kost dus extra rekenwerk / tijd
 107;; in de plaats daarvan zou je  bij een 0 ook weer gewoon om nieuwe invoer kunnen vragen.
 108(defun get-input (prompt)
 109  (loop for input = (getint prompt)
 110             then (progn (format t "                         ") (getint prompt))
 111        until (OR (<= 0 input 4) (= input 8)) ;controleert: OF 0<=input<=4 OF input=8 dus moet dus 0, 1, 2, 3, 4 of 8 zijn. niet juist? opnieuw!
 112        finally (return input)))
 113
 114;; ophalen en kijken of de invoer een integer is.
 115(defun getint (prompt)
 116  (loop for line = (progn (format t prompt) (read-line))
 117              then (progn (format t "                         ~A" prompt) (read-line))
 118        for number = (parse-integer line :junk-allowed t)
 119        until (integerp number) ;controleert op een integer. geen integer? opnieuw!
 120        finally (return number)))
 121
 122                                        ;einde
 123
 124;;;;  -------------   knippen of afscheuren  --------------------------------------------------------
 125
 126;;;; Uitleg bij dit programma / overdenkingen.
 127
 128;;; de schakeling gaat uit van een soort van embedded systeem (schakelunit) dat per kamer werkt.
 129;;; er gaat dan per kamer een "draad" naar de balie, of een verdeelsysteem / netwerk
 130;;; dat op zijn beurt de signlen van de balie heeft gekregen.
 131;;; dit scheelt nogal kabels bij een uitgebreid hotel, maar vereist wel weer een extra
 132;;; schakelunit, echter beide is mogelijk met de hier geschreven functie
 133;;; [edit] onlangs heb ik begrepen dat het de bedoeling was dat er 1 computer centraal alle
 134;;; kamers moest regelen. echter zie ik daar met de gegeven specificaties van de integers geen mogelijkheid.
 135;;; er wordt niet voorzien in andere invoer dan het indrukken van knoppen, zonder relatie met en kamernummer.
 136;;; als je uitgaat van 0000 tot 1111 heb je slechts 16 mogelijkheden waarvan al 6 bezet. dan kun je volgens
 137;;; mij met de overgebleven 10 mogelijkheden nog maar 1 kamer extra bedienen. maar dat lijkt me een minimaal
 138;;; hotel zodat er van uitbreiding geen sprake meer kan zijn, het zal dus wel anders bedoeld zijn, maar daarvan
 139;;; heb ik geen specificaties :p met meerdere "poorten" waarop de signalen binnenkomen kun je de hardware een
 140;;; kamernummer mee laten sturen, en het programma deze exacte waarde gewoon weer samen met de uitvoer naar
 141;;; het apparaat sturen dat uiteindelijk de lampen aan en uit zet.
 142;;; mijn programma gaat er voorts vanuit dat de door de lampen gegenereerde 4 bits informatie wordt
 143;;; omgezet in een unteger, voor verdere beoordeling door dit programma. dit zal denk ik ook wel door het door
 144;;; pascal bedoelde printerpoortinterface worden gedaan, en voor het in de opdracht gegeven idee dat je integers
 145;;; vanaf de commandline kon lezen, lijkt het me duidelijk dat de bits -> integer omzetting buiten de software
 146;;; plaatsvindt.
 147;;;
 148;;; een ander probleempje waar ik tegenaanloop is, wat gebeurt er als iemand een knop lang indrukt? bijv
 149;;; die bij de deur. de software zou dit lezen als een hele boel knopdrukken achterelkaar en je zou een knipperlicht
 150;;; effect krijgen. de factor tijd zit nergens in de opdracht, en wordt door het lezen van de commandline uitgesloten.
 151;;; invoer als 4444444444444444, of 444444444444433333333333333333 wordt lastig te hrkennen, en wat stelt een "enter"
 152;;; in dat geval voor in de simulatie. een knopdruk en de duur ervan (begin en eind) moet dus kunnen worden herkend.
 153;;; op de commandline gaat dat lastig.
 154;;;
 155;;; ook zat ik nog te denken, welke integer wordt er aan de software gegeven als er twee knoppen tegelijk
 156;;; ingedrukt worden. er komt dan bijvoorbeeld 1001 binnen, dit is geen 0,1,2,3,4 of 8, en er wordt
 157;;; dan ook niks mee gedaan?
 158;;;
 159;;; bovenstaande heeft dus ook alles te maken met het feit dat ik niet precies een voorstelling
 160;;; kan maken van hoe een en ander inelkaar zit, hardware en zo.
 161
 162;;;; (Uitleg bij de show functie.
 163;;;
 164;;; de show functie is puur voor de gevraagde simulatie
 165;;; echter je kunt nu het systeem wel aanpassen, zodat bij de balie gezien kan
 166;;; worden of er licht brand in de kamer. de specifiecaties van de opdracht
 167;;; verhinderen dit omdat er geen lamp oid is bij de balie, en er ook geen integer
 168;;; voor de output daarvan is gespecificeerd. het was volgens mij de bedoeling dat de
 169;;; specificaties strikt werden gevolgd.
 170
 171;;;; Uitleg bij de hoofdfunctie.
 172;;;
 173;;; ik heb geen functie ingebouwd voor het stoppen of uitschakelen van de schakelunit
 174;;; omdat het niet de bedoeling is dat de loop ooit wordt onderbroken.
 175;;; (een langdurige loop met gesimuleerde stroomstoring doet hetzelfde ;-)
 176;;; de unit die wordt aangestuurd met het output commando zal dus bij storing de dan
 177;;; geldende situatie in stand houden / dan wel een goeie status voor de lampen in noodgevallen
 178;;; aansturen
 179;;;
 180;;; het gerbuik van de ene keer if, de andere keer when en weer een andere keer cond vond ik wel leuk
 181;;; om toch te handhaven als voorbeeld van verschillende manieren om een soortgelijk probleem
 182;;; op te kunnen lossen
 183
 184;;;; Uitleg bij de functie die de uitvoer maakt.
 185;;;
 186;;; ik kies ervoor om de status van de lampen afzonderlijk te beoordelen in plaats van de waarde van output
 187;;; de waarde van output is niet eenvoudig te ontcijferen, maar de status van de lampen wel, en zodoende is de
 188;;; code beter te lezen.
 189;;; ook kan het zijn dat *output* geen waarde is, maar een functie die de hardware aanstuurt, en er dus geen
 190;;; te beoordelen waarde is, of wordt onthouden.
 191;;; de status van de lampen zal dus wel bekend moeten zijn in dat geval (dus onthouden als variabele)
 192;;;
 
 
Mijn commentaar
 
 Haastwerk geweest Engelbert ?
 Welicht dat je nog even zelf naleest wat het doel van je programma is.
 
 Hoewel ik niet de indruk heb dat je optimaal gebruik maakt van de kracht van lisp,
 kan ik je bijdrage wederom ten zeerste waarderen !
 Vooral de de uitvoerige uitleg bij het programma
 (al zijn wij gewend aan je uitvoerige uiteenzettingen).
 
 Erg mooi vind ik dat jij als enige een fout in mijn systeem hebt opgemerkt !
 Inderdaad is het zo dat bij implementatie mbv b.v. mijn lptdriver het systeem moeite heeft een een knopdruk als een enkele knopdruk te herkennen.
 Iemand die het project daadwerkelijk met hardware gaat uitvoeren,
 zal daarvoor dus een oplossing (die overigens vrij eenvoudig is) moeten bedenken.
 
 Ook is je opmerking over het gelijktijdig indrukken van de knoppen opvallend.
 echter, naar de eerste slimme analyse betreffende de knopdruk, had je toch wel zelf kunnen vasstellen dat je programma naar bits moet kijken, niet naar integer waardes.
 
 Zeker niet verkeerd Engelbert !