Ανάλυση μιας συμβολοσειράς Smart Game Format.
Το SGF είναι μια τυποποιημένη μορφή για την αποθήκευση αρχείων επιτραπέζιων παιχνιδιών, ιδίως του γκο.
Το SGF είναι μια αρκετά απλή μορφή. Ένα αρχείο SGF περιέχει συνήθως ένα μόνο δέντρο κόμβων, όπου κάθε κόμβος είναι μια λίστα ιδιοτήτων. Η λίστα ιδιοτήτων περιέχει ζεύγη κλειδιού-τιμής· κάθε κλειδί μπορεί να εμφανιστεί μόνο μία φορά, αλλά μπορεί να έχει πολλαπλές τιμές.
Σε αυτή την άσκηση θα αναλύσεις μια συμβολοσειρά SGF και θα επιστρέψεις μια δομή δέντρου από ιδιότητες.
Ένα αρχείο SGF μπορεί να μοιάζει κάπως έτσι:
(;FF[4]C[root]SZ[19];B[aa];W[ab])
Πρόκειται για ένα δέντρο με τρεις κόμβους:
Όπως μπορείς να φανταστείς, ένα αρχείο SGF περιέχει πολλούς κόμβους με ένα μόνο παιδί, γι' αυτό υπάρχει μια συντομογραφία γι' αυτό.
Το SGF μπορεί να κωδικοποιήσει παραλλαγές του παιχνιδιού. Οι παίκτες του γκο γυρίζουν συχνά πίσω όταν αναλύουν τα παιχνίδια τους (ας δοκιμάσουμε αυτό, δεν δουλεύει, ας δοκιμάσουμε εκείνο) και το SGF υποστηρίζει παραλλαγές ακολουθιών παιχνιδιού. Για παράδειγμα:
(;FF[4](;B[aa];W[ab])(;B[dd];W[ee]))
Εδώ ο ριζικός κόμβος έχει δύο παραλλαγές. Η πρώτη (η οποία κατά σύμβαση δείχνει τι παίχτηκε πραγματικά) είναι εκείνη όπου ο μαύρος παίζει στο 1-1. Ο μαύρος έλαβε αυτό το αρχείο από τον δάσκαλό του, ο οποίος του επισήμανε ένα πιο λογικό παίξιμο στο δεύτερο παιδί του ριζικού κόμβου: B[dd] (σημείο 4-4, ένα πολύ συνηθισμένο άνοιγμα για να πάρεις τη γωνία).
Ένα κλειδί μπορεί να έχει πολλαπλές τιμές συνδεδεμένες με αυτό. Για παράδειγμα:
(;FF[4];AB[aa][ab][ba])
Εδώ το AB (προσθήκη μαύρων) χρησιμοποιείται για να προσθέσει τρεις μαύρες πέτρες στη σανίδα.
Όλες οι τιμές των ιδιοτήτων θα είναι του τύπου SGF Text. Δεν χρειάζεται να υλοποιήσεις κανέναν άλλο τύπο τιμής. Αν και μπορείς να διαβάσεις την πλήρη τεκμηρίωση του τύπου Text, παρακάτω υπάρχει μια σύνοψη των σημαντικών σημείων:
\, διαφορετικά παραμένουν ως αλλαγές γραμμής.\ είναι ο χαρακτήρας διαφυγής.
Κάθε μη-λευκός χαρακτήρας μετά το \ εισάγεται ως έχει.
Κάθε χαρακτήρας κενού μετά το \ ακολουθεί τους παραπάνω κανόνες.
Σημείωσε ότι το SGF δεν έχει ακολουθίες διαφυγής για χαρακτήρες κενού, όπως \t ή \n.Πρόσεξε να μην μπερδέψεις:
Οι ακολουθίες διαφυγής στα κυριολεκτικά συμβολοσειρών μπορεί να έχουν ήδη υποστεί επεξεργασία από τον αναλυτή της γλώσσας προγραμματισμού, πριν περάσουν στον αναλυτή SGF.
Υπάρχουν μερικές ακόμη πολυπλοκότητες στο SGF (και γενικά στην ανάλυση), τις οποίες μπορείς ως επί το πλείστον να αγνοήσεις. Να υποθέσεις ότι η είσοδος είναι κωδικοποιημένη σε UTF-8 και ότι τα τεστ δεν θα περιέχουν ιδιότητα charset, οπότε μην ανησυχείς γι' αυτό. Επιπλέον, μπορείς να υποθέσεις ότι όλες οι αλλαγές γραμμής είναι σε στυλ unix (\n, στα τεστ δεν θα υπάρχει \r ή \r\n) και ότι στα τεστ δεν θα υπάρχει προαιρετικός κενός χώρος ανάμεσα σε ιδιότητες, κόμβους κ.λπ.
Μερικές φορές είναι απαραίτητο να πετάξεις μια εξαίρεση. Όταν το κάνεις αυτό, θα πρέπει πάντα να συμπεριλαμβάνεις ένα μήνυμα σφάλματος με νόημα που να δείχνει ποια είναι η πηγή του σφάλματος. Αυτό κάνει τον κώδικά σου πιο ευανάγνωστο και βοηθά σημαντικά στο debugging. Σε περιπτώσεις που ξέρεις ότι η πηγή του σφάλματος θα είναι κάποιου συγκεκριμένου τύπου, μπορείς να επιλέξεις να πετάξεις έναν από τους ενσωματωμένους τύπους σφαλμάτων, αλλά θα πρέπει και πάλι να συμπεριλάβεις ένα μήνυμα με νόημα.
Αυτή η συγκεκριμένη άσκηση απαιτεί να χρησιμοποιήσεις την εντολή raise για να "πετάξεις" ένα ValueError αν η είσοδος δεν έχει σωστούς διαχωριστές, δεν είναι σε κεφαλαία, δεν σχηματίζει ένα δέντρο με κόμβους ή δεν σχηματίζει καθόλου δέντρο. Τα tests θα περάσουν μόνο αν κάνεις και raise την exception και συμπεριλάβεις ένα μήνυμα σε αυτήν.
Για να πετάξεις ένα ValueError με μήνυμα, γράψε το μήνυμα ως όρισμα στον τύπο exception:
# if the tree properties as given do not have proper delimiters.
raise ValueError("properties without delimiter")
# if the tree properties as given are not all in uppercase.
raise ValueError("property must be in uppercase")
# if the input does not form a tree, or is empty.
raise ValueError("tree missing")
# if the input is a tree without any nodes.
raise ValueError("tree with no nodes")
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Python με 17 έννοιες146 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.