ΠΑΝΕΠΙΣΤΗΜΙΟ ΙΩΑΝΝΙΝΩΝ ΤΜΗΜΑ ΜΗΧΑΝΙΚΩΝ Η/Υ ΚΑΙ ΠΛΗΡΟΦΟΡΙΚΗΣ ΜΑΘΗΜΑ: ΑΡΧΕΣ ΓΛΩΣΣΩΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ ΑΚΑΔ. ΕΤΟΣ: 20189 ΔΙΔΑΣΚΩΝ: Χ.ΝΟΜΙΚΟΣ 1η Σειρά Εργαστηριακών Ασκήσεων Οι εργαστηριακές ασκήσεις είναι ατομικές. Οι απαντήσεις θα πρέπει να υποβληθούν με turnin, το αργότερο μέχρι την Παρασκευή 15 Μαρτίου 2019. Για τη συγγραφή των προγραμμάτων επιτρέπεται να χρησιμοποιήσετε μόνο τις προκαθοριμένες συναρτήσεις και τους προκαθορισμένους τελεστές που αναφέρονται στις σημειώσεις του μαθήματος. Δεν επιτρέπεται η χρήση του import. Οι ώρες οι οποίες έχουν δεσμευτεί για το εργαστήριο του μαθήματος είναι την Τετάρτη 12-2μμ. Η παρουσία στο εργαστήριο τις παραπάνω ώρες δεν είναι υποχρεωτική. Μπορείτε να έρχεστε στο εργαστήριο τις ώρες αυτές για όποια βοήθεια χρειάζεστε σχετικά με την εκπόνηση των εργαστηριακών ασκήσεων και γενικότερα τον προγραμματισμό στη γλώσσα Haskell, καθώς και για την επίλυση προβλημάτων που παρουσιάζονται κατά τη συγγραφή των προγραμμάτων στο πλαίσιο των εργαστηριακών ασκήσεων. Σημειώνεται ότι σε καμία περίπτωση δεν θα παρέχεται σχετική βοήθεια μέσω e-mail. Για μεγαλύτερη ευκολία στην εκπόνηση αυτής και της επόμενης εργαστηριακής άσκησης σας συνιστώ: 1. να δημιουργήσετε έναν κατάλογο Haskell κάτω από το home directory σας. 2. να χρησιμοποιήτε αυτόν τον κατάλογο για αποθήκευση των αρχείων με τα προγράμματα Haskell που θα γράψετε. 3. να μεταβαίνετε σε αυτόν τον κατάλογο πριν εκτελέσετε τον διερμηνέα hugs της Haskell. Αν θέλετε να χρησιμοποιήσετε τη Haskell στο δικό σας υπολογιστή, μπορείτε να κατεβάσετε το διερμηνέα hugs από το σύνδεσμο https://www.haskell.org/hugs/pages/downloading-may2006.htm Συνοπτικές οδηγίες για τη χρήση του hugs υπάρχουν στις σημειώσεις. Πριν ξεκινήσετε να γράφετε τα προγράμματα που ζητούνται στις παρακάτω ασκήσεις, θα ήταν χρήσιμο να γράψετε σε ένα αρχείο ορισμένες από τις συναρτήσεις των σημειώσεων, να φορτώσετε το αρχείο στον hugs και να αποτιμήσετε παραστάσεις που χρησιμοποιούν τις συναρτήσεις αυτές, έτσι ώστε να εξοικειωθείτε με την γλώσσα Haskell και το διερμηνέα της. Για τη συγγραφή των συναρτήσεων συνίσταται να χρησιμοποιήσετε το αρχείο πρότυπο Lab1.hs (που υπάρχει στην ιστοσελίδα του μαθήματος), στο οποίο υπάρχουν έτοιμες οι δηλώσεις τύπων των συναρτήσεων που θα πρέπει να κατασκευάσετε καθώς και μία ισότητα που ορίζει τις συναρτήσεις ώστε να επιστρέφουν την τιμή -2019 για όλες τις τιμές των ορισμάτων. Για να απαντήσετε
σε μία άσκηση μπορείτε να αντικαταστήσετε την παραπάνω ισότητα με τις κατάλληλες ισότητες που ορίζουν την τιμή της συνάρτησης. Δεν θα πρέπει να τροποποιήσετε το τύπο ούτε το όνομα της συνάρτησης. Μπορείτε να χρησιμοποιήσετε όσες βοηθητικές συναρτήσεις θέλετε, οι οποίες θα καλούνται από τις συναρτήσεις που σας ζητείται να υλοποιήσετε. Σε καμία περίπτωση δεν θα πρέπει να προσθέσετε άλλα ορίσματα στις συναρτήσεις που σας ζητούνται (καθώς αυτό συνεπάγεται αλλαγή του τύπου τους). Αν χρησιμοποιήσετε προκαθοριμένες συναρτήσεις ή τελεστές που δεν αναφέρονται στις σημειώσεις του μαθήματος ή αν χρησιμοποιήσετε το import για να ενσωματώσετε έτοιμο κώδικα, η αντίστοιχη άσκηση δεν θα βαθμολογηθεί. Ο έλεγχος της ορθότητας των απαντήσεων θα γίνει με ημι-αυτόματο τρόπο. Σε καμία περίπτωση δεν θα πρέπει ο βαθμολογητής να χρειάζεται να κάνει παρεμβάσεις στο αρχείο που θα υποβάλετε. Συνεπώς θα πρέπει να λάβετε υπόψη τα παρακάτω: 1. Κάθε μία από τις συναρτήσεις που σας ζητείται να υλοποιήσετε θα πρέπει να έχει το συγκεκριμένο όνομα και το συγκεκριμένο τύπο που περιγράφεται στην εκφώνηση της αντίστοιχης άσκησης και που υπάρχει στο αρχείο πρότυπο Lab1.hs. Αν σε κάποια άσκηση το όνομα ή ο τύπος της συνάρτησης δεν συμφωνεί με αυτόν που δίνεται στην εκφώνηση, η άσκηση δεν θα βαθμολογηθεί. 2. Το αρχείο που θα παραδώσετε δεν θα πρέπει να περιέχει συντακτικά λάθη. Αν υπάρχουν τμήματα κώδικα που περιέχουν συντακτικά λάθη, τότε θα πρέπει να τα διορθώσετε ή να τα αφαιρέσεται πριν από την παράδοση. Αν το αρχείο που θα υποβάλετε περιέχει συντακτικά λάθη, τότε ολόκληρη η εργαστηριακή άσκηση θα μηδενιστεί. 3. Οι συναρτήσεις θα πρέπει να επιστρέφουν αποτέλεσμα για όλες τις τιμές των ορισμάτων που δίνονται για έλεγχο στο τέλος κάθε άσκησης. Αν κάποιες από τις τιμές που επιστρέφουν οι συναρτήσεις δεν είναι σωστές, αυτό θα ληφθεί υπόψη στη βαθμολογία, ωστόσο η άσκηση θα βαθμολογηθεί κανονικά. Αν ωστόσο οι συναρτήσεις δεν επιστρέφουν τιμές για κάποιες από τις τιμές ελέγχου (π.χ. προκαλούν υπερχείλιση στοίβας, ατέρμονο υπολογισμό ή κάποιο σφάλμα χρόνου εκτέλεσης) τότε η αντίστοιχη άσκηση δεν θα βαθμολογηθεί. 4. Κατα τη διόρθωση των ασκήσεων οι βαθμολογητές δεν θα κάνουν κλήσεις στις βοηθητικές συναρτήσεις που ενδεχομένως θα χρησιμοποιήσετε. Η χρήση των βοηθητικών συναρτήσεων θα πρέπει να γίνεται μέσα από τις συναρτήσεις που σας ζητείται να υλοποιήσετε. Μετά το τέλος της εκφώνησης κάθε άσκησης δίνονται τιμές που μπορείτε να χρησιμοποιήσετε για έλεγχο της ορθότητας των συναρτήσεων. Για υποβολή με turnin γράψτε (υποθέτοντας ότι έχετε γράψει το πρόγραμμα στο αρχείο Lab1.hs): turnin Haskell@myy401 Lab1.hs
Ασκηση 1. Γράψτε μία συνάρτηση area σε Haskell, η οποία θα δέχεται ως ορίσματα τρία ζεύγη πραγματικών αριθμών τα οποία αναπαριστούν σημεία του επιπέδου και θα επιστρέφει το εμβαδό του τριγώνου που ορίζουν αυτά τα τρία σημεία. Ο τύπος της συνάρτησης θα πρέπει να είναι (Double,Double)->(Double,Double)->(Double,Double)->Double. Για τον υπολογισμό του εμβαδού E του τριγώνου χρησιμοποιήστε τον τύπο του Ηρωνα E = t (t a) (t b) (t c) όπου a, b, c είναι τα μήκη των τριών πλευρών του τριγώνου και t = a+b+c είναι η ημιπερίμετρος του 2 τριγώνου. Το μήκος του ευθύγραμμου τμήματος που συνδέει δύο σημεία (x 1, y 1 ) και (x 2, y 2 ) είναι (x1 x 2 ) 2 + (y 1 y 2 ) 2. Main> area (1.5,2.5) (3.5,2.5) (1.5,5.5) 3.0 Main> area (5.3,7.4) (1.3,4.4) (9.3,7.4) 6.000000 Main> area (.01,-0.02) (0.99,-0.02) (-0.01,1.71) 1.73 Main> area (25.45,37.19) (1.47,-71.08) (45.33,-64.48) 2953.032 Main> area (7.1,.6) (-3.3,-5.8) (17.5,2.6) 0.0
Ασκηση 2. Ενα ξενοδοχείο διαθέτει μονόκλινα, δίκλινα και τρίκλινα δωμάτια και λειτουργεί τους μήνες από Μάρτιο έως και Σεπτέμβριο. Οι τιμές των δωματίων καθορίζονται από το πλήθος των κλινών και την χρονική περίοδο, σύμφωνα με την παρακάτω πολιτική χρέωσης: Οι τιμές των δωματίων για ημερομηνίες εκτός Ιουλίου και Αυγούστου είναι 50 ευρώ για τα μόνοκλινα δωμάτια, 80 ευρώ για τα δίκλινα δωμάτια και 100 ευρώ για τα τρίκλινα δωμάτια. Οι παραπάνω τιμές κατά τους μήνες Ιούλίο και Αύγουστο προσαυξάνονται κατά 30%. Ενα ταξιδιωτικό πρακτορείο συνεργάζεται με το ξενοδοχείο και κάνει κρατήσεις δωματίων για γκρουπ επισκεπτών. Οι ημερομηνίες άφιξης και αναχώρησης είναι η ίδια για όλους τους συμμετέχοντες στο γκρουπ. Ορισμένοι συμμετέχοντες στο γκρουπ επιλέγουν μονόκλινο δωμάτιο. Οι υπόλοιποι, εφόσον είναι τουλάχιστον δύο, τοποθετούνται σε δίκλινα και τρίκλινα δωμάτια, έτσι ώστε ο συνολικός αριθμός των δωματίων να είναι ο ελάχιστος δυνατός. Φυσικά αν όλοι οι επισκέπτες πλην ενός επιλέξουν μονόκλινο δωμάτιο τότε και αυτός που απομένει θα τοποθετηθεί σε μονόκλινο. Γράψτε μία συνάρτηση cost σε Haskell, η οποία θα δέχεται ως ορίσματα δύο ζεύγη ακεραίων που περιγράφουν τις ημερομηνίες άφιξης και αναχώρησης του γκρουπ, έναν ακέραιο που καθορίζει το συνολικό πλήθος των ατόμων στο γκρουπ και έναν ακέραιο που καθορίζει το πλήθος των ατόμων που επιθυμούν μονόκλινο δωμάτιο και θα επιστρέφει το συνολικό κόστος της κράτησης για το γκρουπ. Μια ημερομηνία περιγράφεται ως ένα ζεύγος ακεραίων αριθμών, όπου το πρώτο στοιχείο του είναι ένας αριθμός ανάμεσα στο 1 και στο 31 και το δεύτερο ένας αριθμός ανάμεσα στο 1 και στο 12 (υπάρχουν ωστόσο κάποια τέτοια ζεύγη που δεν αναπαριστούν έγκυρες ημερομηνίες, όπως για παράδειγμα το (30,2) και το (31,9)). Ο τύπος της συνάρτησης θα πρέπει να είναι (Int,Int)->(Int,Int)->Int->Int->Int (οι τιμές των δωματίων που προκύπτουν με βάση την πολιτική χρέωσης είναι πάντα ακέραιοι αριθμοί και δεν απαιτείται η χρήση πραγματικών αριθμών). Η συνάρτηση θα πρέπει να ελέγχει την εγκυρότητα των δεδομένων και να επιστρέφει την τιμή αν τα δεδομένα δεν είναι έγκυρα. Για να είναι έγκυρα τα δεδομένα θα πρέπει: τα δύο ζεύγη ακεραίων να καθορίζουν έγκυρες ημερομηνίες, εντός του διαστήματος λειτουργίας του ξενοδοχείου, η ημερομηνία άφιξης να είναι προγενέστερη της ημερομηνίας αναχώρησης, το συνολικό πλήθος ατόμων στο γκρουπ να είναι θετικός αριθμός, το πλήθος των επισκεπτών που επιθυμούν μονόκλινο δωμάτιο να μην είναι αρνητικός αριθμός και να μην υπερβαίνει το συνολικό πλήθος των ατόμων στο γκρουπ.
Main> cost (4,9) (5,9) 2 0 80 Main> cost (8,3) (17,3) 3 0 900 Main> cost (4,8) (25,8) 5 5 6825 Main> cost (25,5) (7,6) 1 1 650 Main> cost (30,3) (1,4) 8 7 800 Main> cost (2,5) (3,5) 25 4 900 Main> cost (30,6) (1,7) 30 16 1280 Main> cost (31,8) (1,9) 32 7 1573 Main> cost (21,6) (5,7) 6 2 3952 Main> cost (15,8) (14,9) 7 1 8775 Main> cost (10,5) (10,9) 8 5 49560 Main> cost (20,7) (24,9) 10 0 28404 Main> cost (2,6) (7,8) 11 0 29298 Main> cost (31,4) (31,9) 3 0 Main> cost (8,9) (4,5) 2 0 Main> cost (7,2) (5,3) 1 1 Main> cost (4,9) (20,10) 2 1 Main> cost (13,3) (13,3) 8 0 Main> cost (1,9) (10,9) 0 0 Main> cost (2,5) (3,5) 5 7
Ασκηση 3. Γράψτε μία συνάρτηση product σε Haskell, η οποία θα δέχεται ως όρισμα έναν ακέραιο n και αν ο n είναι θετικός θα επιστρέφει το γινόμενο όλων των αριθμών μεταξύ 1 και n που είναι σχετικά πρώτοι με τον n, αλλιώς θα επιστρέφει την τιμή 0. Δύο αριθμοί ονομάζονται σχετικά πρώτοι αν ο μέγιστος κοινός διαιρέτης τους είναι το 1. Ο τύπος της συνάρτησης θα πρέπει να είναι Integer->Integer. Main> product 1 1 Main> product 7 720 Main> product 12 385 Main> product 32 191898783962510625 Main> product 100 426252881942771063138176712755660145456313428952105524817872601
Ασκηση 4. Γράψτε μία συνάρτηση join σε Haskell, η οποία θα δέχεται ως ορίσματα δύο ακέραιους αριθμούς a και b και θα επιστρέφει τον μη αρνητικό ακέραιο αριθμό c του οποίου το i-οστό ψηφίο c i προκύπτει από τα i-οστά ψηφία a i και b i των a και b σύμφωνα με το παρακάτω τύπο: c i = (a i (9 b i )) mod 10. Η αρίθμηση των ψηφίων των ακεραίων γίνεται από τα δεξιά προς τα αριστερά. Αν κάποιος αριθμός από τους a και b έχει λιγότερα ψηφία από τον άλλο, τότε θεωρούμε ότι συμπληρώνεται στα αριστερά με κατάλληλο πλήθος ψηφίων 0. Ο τύπος της συνάρτησης θα πρέπει να είναι Integer->Integer->Integer. Main> join 87341 20965 63024 Main> join 20965 87341 20400 Main> join 731679 34 379425 Main> join 34 731679 60 Main> join (-87341) (-20965) 63024 Main> join (2^62) (3^31) 6499842028401182008
Ασκηση 5. Γράψτε μία συνάρτηση count σε Haskell, η οποία θα δέχεται ως όρισμα έναν ακέραιο αριθμό n και θα επιστρέφει το πλήθος των ζευγών θετικών ακέραιων αριθμών (a, b) για τα οποία ισχύει n = a 2 b 3. Ο τύπος της συνάρτησης θα πρέπει να είναι Int->Int. Δεν επιτρέπεται να χρησιμοποιήσετε λίστες. Main> count 24 0 Main> count 72 1 Main> count 256 2 Main> count 4096 3 Main> count 46656 4