Λύσεις των 8 Δραστηριοτήτων (κώδικας Python: συμβολοσειρές, στοίβα, λεξικό, λίστες) και των 10 Ερωτήσεων του κεφαλαίου 8, ελεγμένες με το επίσημο βιβλίο λύσεων.
Ερώτηση: Να γράψετε ένα πρόγραμμα το οποίο θα διαβάζει μία λέξη και θα εμφανίζει τα γράμματά της, ένα σε κάθε γραμμή.
Απάντηση:
for … in … (σελ. 128-129) και τυπώνουμε κάθε γράμμα με ξεχωριστή print (η print αλλάζει γραμμή):# Εμφανίζει κάθε γράμμα της λέξης σε ξεχωριστή γραμμή
word = raw_input('Δώσε μια λέξη: ')
for letter in word:
print letter
for i in range(len(word)): print word[i]. (Python 3: input() και print(letter).)Σύνοψη: word = raw_input(...)· for letter in word: print letter.
Κριτήρια αξιολόγησης:
Ερώτηση: Να γράψετε ένα πρόγραμμα το οποίο θα διαβάζει μία λέξη και θα εμφανίζει πόσα κεφαλαία αγγλικά γράμματα περιέχει η λέξη.
Απάντηση:
# Μετράει τα κεφαλαία αγγλικά γράμματα μιας λέξης
enCapSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
word = raw_input('Δώσε μια λέξη: ')
countCapitals = 0
for letter in word:
if letter in enCapSet:
countCapitals += 1
print 'Κεφαλαία αγγλικά γράμματα:', countCapitals
'A' <= letter <= 'Z' (λεξικογραφική σύγκριση).Σύνοψη: Συμβολοσειρά με τα 26 κεφαλαία· for letter in word: if letter in enCapSet: μετρητής += 1· εμφάνιση του μετρητή.
Κριτήρια αξιολόγησης:
Ερώτηση: Να γράψετε ένα πρόγραμμα το οποίο θα διαβάζει μία λέξη και θα την εμφανίζει αντεστραμμένη, με τη χρήση μιας στοίβας.
Απάντηση:
Ιδέα: ωθούμε τα γράμματα της λέξης στη στοίβα με τη σειρά που διαβάζονται· το τελευταίο γράμμα είναι το τελευταίο που μπαίνει, άρα βρίσκεται στην κορυφή. Απωθώντας, βγαίνει πρώτα το τελευταίο, μετά το προτελευταίο κ.ο.κ. (LIFO) — τα γράμματα εμφανίζονται σε αντίστροφη σειρά. Χρησιμοποιούμε την υλοποίηση στοίβας του βιβλίου (σελ. 143):
# Υλοποίηση στοίβας (σελ. 143) — χρησιμοποιείται και στις επόμενες δραστηριότητες
def push(stack, item):
stack.append(item)
def pop(stack):
return stack.pop()
def isEmpty(stack):
return len(stack) == 0
def createStack():
return []
# Αντιστρέφει μια λέξη με τη χρήση στοίβας
word = raw_input('Δώσε μια λέξη: ')
stack = createStack()
for letter in word:
push(stack, letter) # ώθηση κάθε γράμματος
reverse = ''
while not isEmpty(stack):
reverse = reverse + pop(stack) # απώθηση: πρώτα το τελευταίο γράμμα
print reverse
Παράδειγμα: 'PYTHON' → στοίβα [P, Y, T, H, O, N] (κορυφή N) → απωθήσεις N, O, H, T, Y, P → 'NOHTYP'. Ο έλεγχος isEmpty πριν από κάθε απώθηση είναι απαραίτητος (σελ. 142). Ίδια λογική με την εφαρμογή «αντιστροφή αριθμών» της σελ. 143.
Σύνοψη: Ώθηση κάθε γράμματος στη στοίβα· όσο δεν είναι κενή, απώθηση και συνένωση σε νέα συμβολοσειρά· εμφάνιση — LIFO δίνει την αντίστροφη σειρά.
Κριτήρια αξιολόγησης:
Ερώτηση: Να γράψετε μια συνάρτηση isSubstring(string, substring) η οποία θα ελέγχει, αν η συμβολοσειρά substring περιέχεται στη συμβολοσειρά string και αν ναι, θα επιστρέφει True. Στη συνέχεια να υλοποιήσετε μια δεύτερη συνάρτηση, η οποία θα επιστρέφει πόσες φορές εμφανίζεται μια συμβολοσειρά μέσα σε μια άλλη.
Απάντηση:
Μέρος Α: ο υπαρξιακός τελεστής in λειτουργεί και για ολόκληρες υποσυμβολοσειρές ('Py' in 'Python' → True, σελ. 128), οπότε η συνάρτηση γράφεται σε μία γραμμή:
def isSubstring(string, substring):
return substring in string
Μέρος Β — πλήθος εμφανίσεων: για κάθε θέση pos του string ελέγχουμε αν το substring «ξεκινά» εκεί, συγκρίνοντας χαρακτήρα-χαρακτήρα (βοηθητική isPrefix), και μετράμε τις επιτυχίες:
# Ελέγχει αν το substring εμφανίζεται στο string ξεκινώντας από τη θέση start
def isPrefix(string, substring, start):
i = start
j = 0
count = 0
while j < len(substring) and i < len(string):
if string[i] == substring[j]:
count = count + 1
i = i + 1
j = j + 1
return count == len(substring)
# Μετρά πόσες φορές εμφανίζεται το substring μέσα στο string
def findSubstring(string, substring):
pos = 0
count = 0
while pos < len(string):
if isPrefix(string, substring, pos):
count = count + 1
pos = pos + 1
return count
print isSubstring('Python', 'tho') # True
print findSubstring('banana', 'ana') # 2 (θέσεις 1 και 3 — επικαλυπτόμενες)
print findSubstring('abcabcab', 'ab') # 3
Εναλλακτικά με τον τελεστή διαμέρισης: if string[pos:pos+len(substring)] == substring — ίδιο αποτέλεσμα, λιγότερος κώδικας. Σημείωση: η μέθοδος string.count(substring) της Python μετρά μη επικαλυπτόμενες εμφανίσεις ('banana'.count('ana') = 1), ενώ η δική μας και τις επικαλυπτόμενες.
Σύνοψη: isSubstring: return substring in string. Πλήθος: για κάθε θέση pos ελέγχουμε (χαρακτήρα-χαρακτήρα ή με string[pos:pos+len(sub)] == sub) αν το substring ξεκινά εκεί και μετράμε.
Κριτήρια αξιολόγησης:
Ερώτηση: Να γράψετε ένα πρόγραμμα το οποίο θα διαβάζει αριθμούς από το πληκτρολόγιο, μέχρι να δοθεί ο αριθμός 0. Κάθε φορά που θα διαβάζει έναν θετικό αριθμό, θα τον προσθέτει σε μια στοίβα. Όταν διαβάζει έναν αρνητικό αριθμό θα αφαιρεί τόσους αριθμούς από τη στοίβα, αν αυτό είναι δυνατόν και θα τους εμφανίζει στην οθόνη.
Απάντηση:
Σχέδιο: βρόχος while number != 0· αν ο αριθμός είναι θετικός → push· αν είναι αρνητικός → απωθούμε |number| στοιχεία (π.χ. −3 → τρεις απωθήσεις), αλλά μόνο όσο η στοίβα δεν είναι κενή («αν αυτό είναι δυνατόν» → έλεγχος isEmpty), και τυπώνουμε καθένα:
# Υλοποίηση στοίβας (σελ. 143) — χρησιμοποιείται και στις επόμενες δραστηριότητες
def push(stack, item):
stack.append(item)
def pop(stack):
return stack.pop()
def isEmpty(stack):
return len(stack) == 0
def createStack():
return []
stack = createStack()
number = input('Δώσε έναν αριθμό: ')
while number != 0:
if number > 0:
push(stack, number)
else:
i = 0
while i < -number and not isEmpty(stack): # -number = απόλυτη τιμή
print pop(stack),
i = i + 1
print
number = input('Δώσε έναν αριθμό: ')
Παράδειγμα εκτέλεσης: είσοδος 5, 8, 12, −2, 7, −5, 0 → στο −2 τυπώνει «12 8» (μένει [5])· στο −5 τυπώνει «7 5» και σταματά γιατί η στοίβα άδειασε (μόνο 2 στοιχεία ήταν διαθέσιμα). Οι απωθήσεις βγάζουν πάντα τον πιο πρόσφατο αριθμό πρώτα (LIFO).
Σημείωση: το επίσημο βιβλίο λύσεων γράφει while i <= number (με το number αρνητικό) — τυπογραφικό· η σωστή συνθήκη είναι i < -number (ή i < abs(number)).
Σύνοψη: Ανάγνωση μέχρι 0· θετικός → push· αρνητικός → έως |number| φορές: αν όχι κενή, print pop(stack)· LIFO.
Κριτήρια αξιολόγησης:
Ερώτηση: Να γράψετε πρόγραμμα στη γλώσσα Python το οποίο θα δέχεται ως είσοδο ένα κείμενο και θα εμφανίζει πόσες φορές εμφανίζεται κάθε γράμμα του αγγλικού αλφαβήτου σε αυτό. Να χρησιμοποιήσετε ένα λεξικό.
Απάντηση:
# Συχνότητα γραμμάτων του αγγλικού αλφαβήτου σε ένα κείμενο (με λεξικό)
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
text = raw_input('Δώσε ένα κείμενο: ')
frequency = dict() # κενό λεξικό
for letter in text:
if letter in letters: # μόνο αγγλικά γράμματα (όχι κενά, σημεία στίξης)
if letter in frequency: # το κλειδί υπάρχει -> ενημέρωση
frequency[letter] += 1
else: # νέο κλειδί -> δημιουργία με τιμή 1
frequency[letter] = 1
print ' Letter Frequency'
for letter in frequency:
print ' ', letter, ' ', frequency[letter]
text = text.upper(). Το επίσημο βιβλίο λύσεων δίνει και έναν τρόπο χωρίς λεξικό, με λίστα 26 μετρητών και συνάρτηση που επιστρέφει τη θέση κάθε γράμματος στο αλφάβητο.Σύνοψη: Λεξικό frequency· for letter in text: αν είναι αγγλικό γράμμα, frequency[letter] += 1 αν υπάρχει αλλιώς = 1· εμφάνιση ζευγών κλειδί-τιμή.
Κριτήρια αξιολόγησης:
Ερώτηση: Να γράψετε μια συνάρτηση σε Python η οποία θα δέχεται μια λίστα από λέξεις και θα επιστρέφει τη λέξη με το μεγαλύτερο μήκος.
Απάντηση:
Κλασικός αλγόριθμος εύρεσης μεγίστου (σελ. 134, Παράδειγμα 3), με κριτήριο το μήκος len(word): κρατάμε το μέγιστο μήκος και τη λέξη που το έδωσε, διασχίζοντας τη λίστα:
def maxLength(wordList):
maxLen = 0
maxWord = ''
for word in wordList:
if len(word) > maxLen:
maxLen = len(word)
maxWord = word
return maxWord
print maxLength(['Python', 'is', 'a', 'programming', 'language']) # programming
Σε ισοπαλία επιστρέφεται η πρώτη λέξη με το μέγιστο μήκος (η σύγκριση είναι με αυστηρό >)· για κενή λίστα επιστρέφει ''. Εναλλακτικά με αρχικοποίηση maxWord = wordList[0] (απαιτεί μη κενή λίστα).
Σύνοψη: Διάσχιση της λίστας με μεταβλητές maxLen/maxWord· αν len(word) > maxLen ενημέρωση· return maxWord.
Κριτήρια αξιολόγησης:
Ερώτηση: Να γράψετε μια συνάρτηση σε Python η οποία θα δέχεται μια λέξη και θα επιστρέφει το πλήθος των φωνηέντων που έχει. Στη συνέχεια, να γράψετε μια δεύτερη συνάρτηση, η οποία θα δέχεται μια λίστα από λέξεις και θα επιστρέφει τη λέξη με τα περισσότερα φωνήεντα.
Απάντηση:
Πρώτη συνάρτηση: όπως η count_vowels του βιβλίου (σελ. 129) — συμβολοσειρά με τα φωνήεντα (κεφαλαία και πεζά) και έλεγχος letter in vowels. Δεύτερη: εύρεση μεγίστου με κριτήριο την τιμή της πρώτης συνάρτησης (όπως στη δραστηριότητα 7):
def num_of_Vowels(word):
vowels = 'AEIOUaeiou'
count = 0
for letter in word:
if letter in vowels:
count += 1
return count
def maxVowels(wordList):
maxV = -1
maxWord = ''
for word in wordList:
v = num_of_Vowels(word) # μία κλήση ανά λέξη
if v > maxV:
maxV = v
maxWord = word
return maxWord
print num_of_Vowels('education') # 5
print maxVowels(['sky', 'queue', 'python', 'education']) # education
Σημείωση: το επίσημο βιβλίο λύσεων περιλαμβάνει και το y/Y στα φωνήεντα ('AEIOUYaeiouy')· το βιβλίο μαθητή (σελ. 129) χρησιμοποιεί 'AEIOUaeiou' — και οι δύο επιλογές γίνονται δεκτές αν δηλωθούν. Με maxV = -1 επιστρέφεται λέξη ακόμη κι αν καμία δεν έχει φωνήεντα (η πρώτη).
Σύνοψη: num_of_Vowels: μετρητής με letter in 'AEIOUaeiou'· maxVowels: εύρεση μεγίστου με κριτήριο num_of_Vowels(word).
Κριτήρια αξιολόγησης:
Ερώτηση: Να περιγράψετε τη δομή δεδομένων συμβολοσειρά (str) στην Python και να αναφέρετε τους τελεστές επεξεργασίας της.
Απάντηση:
Σύνοψη: (ενδεικτική) Ακολουθία χαρακτήρων, σταθερού μεγέθους, immutable, δείκτες από 0, τύπος str· τελεστές: [i], len, +, *, in/not in, συγκριτικοί (λεξικογραφικά), διαμέριση a:b, str/int, for char in.
Κριτήρια αξιολόγησης:
Ερώτηση: Να περιγράψετε τη δομή δεδομένων Λίστα στην Python και να αναφέρετε τους τελεστές επεξεργασίας της.
Απάντηση:
L[i]. Ορίζεται με αγκύλες: L = [3, 5, 8, 13, 21, 34], mix = [6, 3.14159, True, 'Guido'].L[0] = ...)· + συνένωση λιστών (Λίστα + [στοιχείο] — δημιουργεί νέα λίστα) και += για προσθήκη στο τέλος· in / not in ύπαρξη στοιχείου· len(L) πλήθος· list(string) μετατροπή σε λίστα· τελεστής διαμέρισης : (L[a:b], L[:] = αντίγραφο)· range(A, M, B) παράγει λίστες αριθμών. Μέθοδοι: L.append(x) (στο τέλος), L.insert(i, x) (στη θέση i), L.pop([i]) (αφαίρεση και επιστροφή). Διάσχιση με for item in L (ή for index in range(len(L))).Σύνοψη: (ενδεικτική) Διατεταγμένη, δυναμική, mutable ακολουθία αντικειμένων (και διαφορετικών τύπων), δείκτες από 0· τελεστές: [i], +, +=, in/not in, len, list(), διαμέριση, range· μέθοδοι append/insert/pop· for item in L.
Κριτήρια αξιολόγησης:
Ερώτηση: Να αναφέρετε τις δομές δεδομένων οι οποίες επιτρέπουν τροποποίηση των δεδομένων τους (mutables).
Απάντηση:
L[i] = … (σελ. 130). Λεξικό: προσθήκη/ενημέρωση ζευγών με Λεξικό[κλειδί] = τιμή και διαγραφή με del (σελ. 147-148). Με βάση τις λίστες υλοποιούνται και η στοίβα και η ουρά, που είναι επίσης μεταβαλλόμενες δομές.Σύνοψη: Λίστα και λεξικό (και οι δομές που υλοποιούνται με λίστα: στοίβα, ουρά).
Κριτήρια αξιολόγησης:
Ερώτηση: Να αναφέρετε τις δομές δεδομένων οι οποίες δεν επιτρέπουν τροποποίηση των δεδομένων τους (immutables).
Απάντηση:
rec = ('Edsger', 'Dijkstra', 1940, 2006).Σύνοψη: Συμβολοσειρές (str) και πλειάδες (tuples).
Κριτήρια αξιολόγησης:
Ερώτηση: Πότε χρησιμοποιούμε τη δομή δεδομένων του Λεξικού;
Απάντηση:
version['python'] = 3.4, dictionary['Giga'] → 9.Σύνοψη: (ενδεικτική) Όταν θέλουμε ζεύγη κλειδί–τιμή με μοναδικά κλειδιά και γρήγορη εύρεση της τιμής από το κλειδί (τηλεφωνικός κατάλογος, μετρητές συχνότητας, αντιστοιχίσεις), αντί για προσπέλαση με θέση.
Κριτήρια αξιολόγησης:
Ερώτηση: Να αναφέρετε μια εφαρμογή των Πλειάδων.
Απάντηση:
a, b = b, a (a = 496, b = 28 → a = 28, b = 496). Στο δεξί μέλος σχηματίζεται η πλειάδα (b, a) και οι τιμές της εκχωρούνται στα a, b. Η ίδια εντολή χρησιμοποιείται στους αλγορίθμους ταξινόμησης (κεφ. 5).rec = ('Edsger', 'Dijkstra', 1940, 2006)· επίσης η divmod(10, 3) επιστρέφει πλειάδα (3, 1) (σελ. 39).Σύνοψη: (ενδεικτική) Η αντιμετάθεση τιμών δύο μεταβλητών χωρίς βοηθητική μεταβλητή: a, b = b, a· επίσης η αναπαράσταση οντοτήτων/εγγραφών με σταθερές ιδιότητες.
Κριτήρια αξιολόγησης:
Ερώτηση: Ποιες είναι οι βασικές λειτουργίες σε μια Στοίβα και ποιες σε μια Ουρά;
Απάντηση:
Σύνοψη: (ενδεικτική) Στοίβα: δημιουργία, έλεγχος κενής, ώθηση (push), απώθηση (pop) — LIFO από το ίδιο άκρο. Ουρά: εισαγωγή (enqueue) πίσω, εξαγωγή (dequeue) εμπρός (+ δημιουργία, έλεγχος κενής) — FIFO.
Κριτήρια αξιολόγησης:
Ερώτηση: Να αναφέρετε εφαρμογές της Στοίβας.
Απάντηση:
Σύνοψη: (ενδεικτική) Ιστορικό/Back του φυλλομετρητή, σωρός πιάτων, αντιστροφή αριθμών ή λέξης, αλγόριθμοι, μεταγλωττιστές, τεχνητή νοημοσύνη (επίσης Undo, παρενθέσεις, κλήσεις συναρτήσεων).
Κριτήρια αξιολόγησης:
Ερώτηση: Να αναφέρετε εφαρμογές της Ουράς.
Απάντηση:
Σύνοψη: (ενδεικτική) Ουρές τραπεζών/σούπερ-μάρκετ, προγράμματα προς τον επεξεργαστή, αιτήσεις σε web server (προσομοίωση εξυπηρέτησης, Θεωρία Ουρών)· επίσης ουρά εκτύπωσης κ.ά.
Κριτήρια αξιολόγησης:
Ερώτηση: Σε τι διαφέρει ένα Δέντρο από ένα Γράφο;
Απάντηση:
Σύνοψη: (ενδεικτική) Το δέντρο είναι γράφος στον οποίο υπάρχει μονοπάτι μεταξύ οποιωνδήποτε δύο κορυφών και δεν υπάρχουν κύκλοι — ιεραρχικός, με ρίζα, πρόγονο/απογόνους, φύλλα, επίπεδα, ύψος· ο γράφος γενικά μπορεί να έχει κύκλους και ασύνδετες κορυφές.
Κριτήρια αξιολόγησης: