Λύσεις της Δραστηριότητας 1 (τρία προβλήματα: κάλπικα νομίσματα, χειραψία, ρέστα-βελτιστοποίηση), της Δραστηριότητας 2 (αυτοκίνητα — γενίκευση σε συνάρτηση), της Δραστηριότητας 3 (πύργοι του Ανόι) και των 4 Ερωτήσεων του κεφαλαίου 12.
Ερώτηση: Υπάρχουν δέκα σακιά που περιέχουν 100 νομίσματα το καθένα. Το κάθε νόμισμα ζυγίζει 10 γραμμάρια. Το ένα από τα δέκα σακιά έχει μέσα μόνο κάλπικα νομίσματα, τα οποία ζυγίζουν εννέα (9) γραμμάρια το καθένα. Πώς μπορούμε με μία μόνο ζύγιση σε μία ηλεκτρονική ζυγαριά ακριβείας, να βρούμε ποιο σακί περιέχει τα κάλπικα νομίσματα; (Να συμπληρωθεί: κατανόηση του προβλήματος — γνωστά δεδομένα, άγνωστα, ζητούμενο, συνθήκες, πλάνο εργασίας, σχεδίαση λύσης· υλοποίηση της λύσης· ανακεφαλαίωση και συζήτηση.)
Απάντηση:
elleimma = 550 - varos; print 'Κάλπικο το σακί', elleimma.Σύνοψη: Παίρνουμε 1 νόμισμα από το σακί 1, 2 από το 2, …, 10 από το 10 (55 νομίσματα, αναμενόμενο βάρος 550 g) και ζυγίζουμε μία φορά· το σακί με τα κάλπικα είναι το k = 550 − βάρος (π.χ. 547 g → σακί 3). Γενίκευση: N σακιά → 1…N νομίσματα.
Κριτήρια αξιολόγησης:
Ερώτηση: Ας υποθέσουμε ότι είκοσι άνθρωποι βρίσκονται μαζί με ένα μαθητή σε ένα δωμάτιο και πρέπει ο μαθητής να ανταλλάξει χειραψία με κάθε έναν από αυτούς. Με πόσους ανθρώπους τελικά θα ανταλλάξει χειραψία; Εάν υπάρχουν Ν (Ν>0) άνθρωποι μαζί με το μαθητή στο δωμάτιο, με πόσους τελικά θα έρθει αυτός σε επαφή;
Απάντηση:
N = input('Άνθρωποι στο δωμάτιο: '); print 'Ο μαθητής θα κάνει', N, 'χειραψίες'.Σύνοψη: Με 20 ανθρώπους → 20 χειραψίες· με Ν ανθρώπους → Ν (f(N) = N). Παραλλαγή «όλοι με όλους» (Ν+1 άτομα): (Ν+1)·Ν/2 — για 21 άτομα 210.
Κριτήρια αξιολόγησης:
Ερώτηση: Να μελετηθεί το πρόβλημα που θα υπολογίζει τα ρέστα που πρέπει να δώσει ένα αυτόματο μηχάνημα έκδοσης εισιτηρίων. Τα εισιτήρια κοστίζουν 0.95€. Ο αλγόριθμος θα δέχεται το ποσό που πληρώνει ο πελάτης και θα επιστρέφει τον αριθμό των κερμάτων με αξία 2€, 1€, 0.50€, 0.20€, 0.10€. Ο αλγόριθμος πρέπει να λειτουργεί με τέτοιο τρόπο, ώστε τα ρέστα να δίνονται με το μικρότερο δυνατό (βελτιστοποίηση) αριθμό νομισμάτων.
Απάντηση:
# Ρέστα με το ελάχιστο πλήθος κερμάτων (άπληστος αλγόριθμος) - υπολογισμοί σε λεπτά
timi = 95 # 0.95 ευρώ σε λεπτά
kermata = [200, 100, 50, 20, 10] # 2, 1, 0.50, 0.20, 0.10 ευρώ (φθίνουσα σειρά)
poso = input('Ποσό που πληρώνει ο πελάτης (ευρώ): ')
resta = int(round(poso * 100)) - timi # ρέστα σε λεπτά
if resta < 0:
print 'Το ποσό δεν επαρκεί'
else:
print 'Ρέστα:', resta / 100.0, 'ευρώ'
for kerma in kermata:
plithos = resta / kerma # ακέραια διαίρεση: πόσα τέτοια κέρματα χωρούν
resta = resta % kerma # ό,τι απομένει
if plithos > 0:
print plithos, 'x', kerma / 100.0, 'ευρώ'
if resta > 0:
print 'Υπόλοιπο', resta / 100.0, 'ευρώ δεν μπορεί να δοθεί με τα διαθέσιμα κέρματα'
Σύνοψη: Άπληστος αλγόριθμος: ρέστα = ποσό − 0,95 (σε λεπτά), για κάθε κέρμα από το μεγαλύτερο (200, 100, 50, 20, 10) πλήθος = ρέστα // κέρμα, ρέστα = ρέστα % κέρμα· επισήμανση μη αποδοτέου υπολοίπου < 0,10 (δεν υπάρχει 0,05)· π.χ. 5 € → 2 × 2 € + 0,05. Βέλτιστος για τα κέρματα του ευρώ.
Κριτήρια αξιολόγησης:
Ερώτηση: Ο σημερινός αριθμός αυτοκινήτων που κυκλοφορούν σε μια πόλη είναι 90000. Αν ο αριθμός αυτός αυξάνεται με ετήσιο ρυθμό 5%, να γραφεί σενάριο σε Python που υπολογίζει σε πόσα χρόνια ο αριθμός των αυτοκινήτων θα ξεπεράσει τις 160000. Να εμφανίζει πόσα θα είναι τότε τα αυτοκίνητα. Γενικεύστε το πρόγραμμα για Arith_Aytok αυτοκίνητα, που αυξάνονται με ετήσιο ρυθμό (Rythmos) και ξεπερνούν ένα δοσμένο όριο (Orio). Τέλος, να οπτικοποιηθεί ο κώδικας στο pythontutor.com.
Απάντηση:
Ανάλυση: κάθε χρόνο τα αυτοκίνητα γίνονται 1,05 φορές τα περσινά (αύξηση 5%). Δεν ξέρουμε εκ των προτέρων πόσες επαναλήψεις χρειάζονται → δομή while με συνθήκη «όσο τα αυτοκίνητα δεν ξεπερνούν το όριο»· σε κάθε επανάληψη αυξάνουμε τα αυτοκίνητα και μετράμε ένα έτος.
# Συγκεκριμένο πρόβλημα
aytokinita = 90000.0
xronia = 0
while aytokinita <= 160000:
aytokinita = aytokinita * 1.05 # αύξηση 5% ανά έτος
xronia = xronia + 1
print 'Τα αυτοκίνητα θα ξεπεράσουν τις 160000 σε', xronia, 'χρόνια'
print 'Τότε θα είναι', int(aytokinita), 'αυτοκίνητα'
Αποτέλεσμα (επαληθευμένο): σε 12 χρόνια, οπότε θα είναι 161627 αυτοκίνητα (90000 × 1,05¹² ≈ 161627,1· στα 11 χρόνια είναι 153930 < 160000).
Γενίκευση — τα τρία δεδομένα γίνονται παράμετροι (συνάρτηση ή είσοδος από τον χρήστη), ώστε το ίδιο πρόγραμμα να λύνει κάθε πρόβλημα «εκθετικής αύξησης μέχρι ένα όριο» (πληθυσμός, κεφάλαιο με τόκο, βακτήρια):
def xronia_gia_orio(Arith_Aytok, Rythmos, Orio):
# Επιστρέφει (χρόνια, τελικό πλήθος) μέχρι το Arith_Aytok να ξεπεράσει το Orio
# με ετήσιο ρυθμό αύξησης Rythmos (ποσοστό %)
xronia = 0
plithos = float(Arith_Aytok)
while plithos <= Orio:
plithos = plithos * (1 + Rythmos / 100.0)
xronia = xronia + 1
return xronia, plithos
Arith_Aytok = input('Σημερινός αριθμός αυτοκινήτων: ')
Rythmos = input('Ετήσιος ρυθμός αύξησης (%): ')
Orio = input('Όριο: ')
xronia, plithos = xronia_gia_orio(Arith_Aytok, Rythmos, Orio)
print 'Το όριο', Orio, 'ξεπερνιέται σε', xronia, 'χρόνια, με', int(plithos), 'αυτοκίνητα'
Έλεγχος: xronia_gia_orio(90000, 5, 160000) → (12, 161627.1) — ίδιο με το συγκεκριμένο πρόγραμμα. Προσοχή: αν ο ρυθμός είναι 0 ή αρνητικός και το όριο μεγαλύτερο του αρχικού πλήθους, ο βρόχος δεν τερματίζει — μια ολοκληρωμένη λύση ελέγχει Rythmos > 0. Η οπτικοποίηση στο pythontutor.com γίνεται επικολλώντας τον κώδικα (επιλογή Python 2.7) και πατώντας «Visualize Execution»: βήμα-βήμα φαίνονται οι τιμές των aytokinita/xronia σε κάθε επανάληψη — ενέργεια για την τάξη, δεν αποτυπώνεται εδώ.
Σύνοψη: while aytokinita <= 160000: aytokinita = 1.05; xronia += 1 → 12 χρόνια, 161627 αυτοκίνητα. Γενίκευση: συνάρτηση xronia_gia_orio(Arith_Aytok, Rythmos, Orio) με while plithos <= Orio: plithos = (1 + Rythmos/100.0)· είσοδος από τον χρήστη.
Κριτήρια αξιολόγησης:
Ερώτηση: Μελετήστε το πρόβλημα των πύργων του Ανόι βλέποντας την οπτικοποίησή του από το Φωτόδεντρο. Το πρόβλημα να επιλυθεί αρχικά για τρεις δίσκους, σε φυσική γλώσσα. Να αξιοποιηθεί η λύση αυτή για να λυθεί το πρόβλημα με τέσσερις δίσκους. Τέλος, να γενικευθεί η λύση για οποιοδήποτε πλήθος δίσκων.
Απάντηση:
Το πρόβλημα: τρεις στύλοι Α (αρχικός), Β (βοηθητικός), Γ (τελικός) και n δίσκοι διαφορετικού μεγέθους στοιβαγμένοι στον Α, ο μεγαλύτερος κάτω. Ζητείται να μεταφερθούν όλοι στον Γ με κανόνες: ένας δίσκος τη φορά (ο πάνω-πάνω κάποιου στύλου) και ποτέ μεγαλύτερος πάνω σε μικρότερο.
Τρεις δίσκοι (μικρός 1, μεσαίος 2, μεγάλος 3) — 7 κινήσεις σε φυσική γλώσσα: ① τον δίσκο 1 από Α στον Γ· ② τον 2 από Α στον Β· ③ τον 1 από Γ στον Β (τώρα ο Β έχει 1 πάνω στο 2)· ④ τον 3 από Α στον Γ (ο μεγάλος στη θέση του)· ⑤ τον 1 από Β στον Α· ⑥ τον 2 από Β στον Γ· ⑦ τον 1 από Α στον Γ. Παρατήρηση (αναγνώριση προτύπου): οι κινήσεις ①-③ μεταφέρουν τους δύο μικρότερους δίσκους στον βοηθητικό Β, η ④ μεταφέρει τον μεγαλύτερο, και οι ⑤-⑦ μεταφέρουν ξανά τους δύο μικρότερους από τον Β πάνω στον Γ — δηλαδή η λύση για 3 δίσκους χρησιμοποιεί δύο φορές τη λύση για 2 δίσκους (που είναι 3 κινήσεις).
Τέσσερις δίσκοι — αξιοποίηση της λύσης των 3: ① μεταφέρουμε τους τρεις μικρότερους από τον Α στον Β (με τη λύση των 3 δίσκων, 7 κινήσεις, χρησιμοποιώντας τον Γ ως βοηθητικό)· ② μεταφέρουμε τον δίσκο 4 από τον Α στον Γ (1 κίνηση)· ③ μεταφέρουμε τους τρεις μικρότερους από τον Β στον Γ (πάλι 7 κινήσεις, με τον Α βοηθητικό). Σύνολο 7 + 1 + 7 = 15 κινήσεις.
Γενίκευση για n δίσκους (διάσπαση σε υποπροβλήματα — αναδρομή): «Για να μεταφέρεις n δίσκους από τον Α στον Γ με βοηθητικό τον Β: αν n = 1, μετέφερε τον δίσκο απευθείας· αλλιώς μετέφερε τους n−1 πάνω δίσκους από Α στον Β (βοηθητικός ο Γ), μετά τον n-οστό από Α στον Γ, και τέλος τους n−1 από Β στον Γ (βοηθητικός ο Α)». Πλήθος κινήσεων: K(1) = 1, K(n) = 2·K(n−1) + 1 → 1, 3, 7, 15, 31, … = 2ⁿ − 1 (για 10 δίσκους 1023, για 64 δίσκους ≈ 1,8·10¹⁹ — ο θρύλος των μοναχών). Η ίδια διαδικασία εφαρμόζεται σε οποιοδήποτε πλήθος δίσκων — μεταφορά της λύσης (γενίκευση).
def hanoi(n, apo, pros, voithitikos):
# Μεταφέρει n δίσκους από τον στύλο apo στον pros με βοηθητικό τον voithitikos
if n == 1:
print 'Δίσκος 1 από', apo, 'στον', pros
else:
hanoi(n - 1, apo, voithitikos, pros) # οι n-1 μικρότεροι στον βοηθητικό
print 'Δίσκος', n, 'από', apo, 'στον', pros
hanoi(n - 1, voithitikos, pros, apo) # οι n-1 μικρότεροι πάνω στον μεγάλο
hanoi(3, 'A', 'Γ', 'B') # 7 κινήσεις - επαληθευμένο
Το πρόγραμμα για n = 3 τυπώνει ακριβώς τις 7 κινήσεις της φυσικής γλώσσας (1: Α→Γ, 2: Α→Β, 1: Γ→Β, 3: Α→Γ, 1: Β→Α, 2: Β→Γ, 1: Α→Γ) και για n = 4 τις 15 (επαληθεύτηκε με εκτέλεση). Η οπτικοποίηση του Φωτόδεντρου βοηθά να δούμε τη διάσπαση «n−1 + 1 + n−1» — ενέργεια στην τάξη.
Σύνοψη: 3 δίσκοι: 7 κινήσεις (1 Α→Γ, 2 Α→Β, 1 Γ→Β, 3 Α→Γ, 1 Β→Α, 2 Β→Γ, 1 Α→Γ) = λύση 2 δίσκων προς Β, ο μεγάλος στον Γ, λύση 2 δίσκων προς Γ. 4 δίσκοι: 3 δίσκοι στον Β (7), δίσκος 4 στον Γ (1), 3 δίσκοι στον Γ (7) = 15. Γενικά: n−1 στον βοηθητικό, ο n-οστός στον τελικό, n−1 στον τελικό — 2ⁿ − 1 κινήσεις (αναδρομική συνάρτηση hanoi).
Κριτήρια αξιολόγησης:
Ερώτηση: Να αναφερθούν πέντε βασικά χαρακτηριστικά της υπολογιστικής σκέψης.
Απάντηση:
Σύνοψη: (ενδεικτική) Π.χ. μορφοποίηση προβλήματος, εννοιολογική αφαίρεση, διάσπαση σε υποπροβλήματα, αλγοριθμική αυτοματοποίηση λύσεων, γενίκευση/μεταφορά — (επίσης οργάνωση δεδομένων, μοντέλα/προσομοιώσεις, αναγνώριση λύσεων, αξιολόγηση, ανθρώπινη συμπεριφορά).
Κριτήρια αξιολόγησης:
Ερώτηση: Να αναφερθούν τρία καθημερινά παραδείγματα υπολογιστικής σκέψης.
Απάντηση:
Σύνοψη: (ενδεικτική) Συντομότερη διαδρομή σπίτι-σχολείο (αφαίρεση, κόμβοι, δομή δεδομένων)· ουρά στο ταμείο (FIFO, μοντελοποίηση, αλγόριθμος)· αναζήτηση λήμματος σε εγκυκλοπαίδεια (σειριακή/δυαδική, γενίκευση) — επίσης ρομπότ σε λαβύρινθο, σχεδίαση σπιτιού, συνταγή, βαλίτσα.
Κριτήρια αξιολόγησης:
Ερώτηση: Να περιγραφεί σύντομα η λειτουργία της Αφαίρεσης για την κατανόηση σύνθετων προβλημάτων.
Απάντηση:
Σύνοψη: (ενδεικτική) Αφαίρεση = εντοπισμός των βασικών χαρακτηριστικών και απαλλαγή του προβλήματος από τις περιττές λεπτομέρειες, κρατώντας μόνο την απαραίτητη πληροφορία· επιτρέπει κριτική επεξεργασία, ανακάλυψη σχέσεων, διάσπαση σε υποπροβλήματα και σαφή διατύπωση της δομής (παραδείγματα: χρώμα vs ταχύτητα οχήματος, Φόρμουλα 1 και τζιπ = αυτοκίνητα, ο άγνωστος Χ).
Κριτήρια αξιολόγησης:
Ερώτηση: Να περιγραφεί σύντομα η λειτουργία της Γενίκευσης της διαδικασίας επίλυσης προβλήματος.
Απάντηση:
Σύνοψη: (ενδεικτική) Γενίκευση = μεταφορά της διαδικασίας επίλυσης ενός συγκεκριμένου προβλήματος σε ευρύτερη ποικιλία παρόμοιων προβλημάτων, αντικαθιστώντας τα συγκεκριμένα δεδομένα με παραμέτρους ώστε η λύση να γίνει γενική μέθοδος (λαβύρινθοι διαφορετικού σχήματος, αναζήτηση, αυτοκίνητα → συνάρτηση με παραμέτρους, Ανόι για n δίσκους, χειραψία για Ν).
Κριτήρια αξιολόγησης: