Διαδρομές
/
Factor
Factor
/
Ασκήσεις
/
Ημερολόγιο Φάρου
Ημερολόγιο Φάρου

Ημερολόγιο Φάρου

Άσκηση εκμάθησης

Εισαγωγή

Τα hash-sets είναι μεταβλητές, μη διατεταγμένες συλλογές που αποθηκεύουν κάθε τιμή το πολύ μία φορά. Η αναζήτηση, η εισαγωγή και η διαγραφή είναι όλες κατά μέσο όρο O(1). Βρίσκονται στο hash-sets και υλοποιούν το πρωτόκολλο sets.

Τα literals των hash-set

HS{ "NS-1024" "WB-203" } .
! => HS{ "NS-1024" "WB-203" }

Το HS{ } είναι το κενό literal. Όπως και τα άλλα literals της Factor, είναι ένα κοινόχρηστο αντικείμενο: κάθε αναφορά στο HS{ } μέσα στον κώδικα δείχνει στο ίδιο σύνολο. Το HS{ } clone σου δίνει ένα καινούργιο ανεξάρτητο αντίγραφο σε κάθε κλήση.

Από μια ακολουθία

>hash-set ( seq -- set )    ! build a fresh set from a sequence

Όταν έχεις ήδη τις τιμές σε μια ακολουθία, το >hash-set τις μετατρέπει σε ένα βήμα, αφαιρώντας τυχόν διπλότυπα.

USING: hash-sets prettyprint ;

{ "NS-1024" "WB-203" "NS-1024" } >hash-set .
! => HS{ "NS-1024" "WB-203" }

Προσθήκη και αφαίρεση

adjoin     ( elt set -- )    ! insert in place; no-op if already present
adjoin-all ( seq set -- )    ! insert every element of seq in place
delete     ( elt set -- )    ! remove in place; no-op if absent

Και τα τρία μεταβάλλουν το σύνολο· κανένα δεν επιστρέφει κάτι στη στοίβα.

USING: hash-sets kernel sets ;

HS{ } clone
"NS-1024" over adjoin
"WB-203"  over adjoin
"NS-1024" over adjoin    ! duplicate — no effect
.                        ! => HS{ "NS-1024" "WB-203" }

Το adjoin-all είναι η μαζική μορφή: προσθέτει κάθε στοιχείο μιας ακολουθίας, παραλείποντας τα διπλότυπα, ακριβώς όπως κάνει το adjoin ένα κάθε φορά.

USING: hash-sets kernel sets ;

HS{ "NS-1024" } clone
{ "WB-203" "NS-1024" "QR-7" } over adjoin-all
.                        ! => HS{ "QR-7" "NS-1024" "WB-203" }  (order not guaranteed)

Ρωτώντας το σύνολο

in?         ( elt set -- ? )   ! is elt in the set?
null?       ( set -- ? )       ! is the set empty?
cardinality ( set -- n )       ! number of elements
members     ( set -- seq )     ! enumerate as a sequence

Το in? είναι ο έλεγχος συμμετοχής του πρωτοκόλλου συνόλων. Διαφέρει από το member? (από το sequences), που κάνει γραμμική σάρωση πάνω σε μια ακολουθία. Για ένα hash-set, το in? είναι αναζήτηση σε πίνακα κατακερματισμού, κατά μέσο όρο O(1), που είναι και το όλο νόημα της χρήσης ενός hash-set.

Το null? αναφέρει αν το σύνολο δεν έχει στοιχεία, ο άμεσος τρόπος να ρωτήσεις "είναι αυτό κενό;" αντί να συγκρίνεις το cardinality με το μηδέν.

: my-log ( -- set ) HS{ "NS-1024" "WB-203" } ;

"NS-1024" my-log in? .   ! => t
"X-99"    my-log in? .   ! => f
my-log null? .           ! => f
HS{ } clone null? .      ! => t
my-log cardinality .     ! => 2

Συνδυασμός συνόλων

union     ( set1 set2 -- set )
intersect ( set1 set2 -- set )
diff      ( set1 set2 -- set )
set-like  ( set exemplar -- set' )

Το union είναι "όλα τα στοιχεία από οποιοδήποτε από τα δύο"· το intersect είναι "τα στοιχεία που υπάρχουν και στα δύο"· το diff είναι "όσα είναι στο set1 αλλά όχι στο set2". Κάθε ένα επιστρέφει ένα νέο σύνολο χωρίς να μεταβάλλει τα ορίσματά του.

Το set-like μετατρέπει το set στον τύπο του exemplar. Οι προεπιλεγμένες υλοποιήσεις των union/intersect/diff το χρησιμοποιούν για να ταιριάξει το αποτέλεσμα με τον τύπο του δέκτη: το <my-set> <hash-set> union επιστρέφει ένα my-set, όχι ένα hash-set.

Γιατί έχει σημασία

Τα hash-sets ταιριάζουν φυσικά με τα hashtables για διάσχιση γράφου: ένα hashtable αντιστοιχίζει κάθε κόμβο με τους γείτονές του, και ένα hash-set καταγράφει ποιοι κόμβοι έχουν ήδη επισκεφθεί, ώστε η αναζήτηση να μην κάνει κύκλους ή να μην επαναλαμβάνει δουλειά. Η διάσχιση είναι τότε μια ουρά συν τις δύο δομές, που μεταβάλλονται επί τόπου καθώς απλώνεσαι προς τα έξω.

Οδηγίες

Είσαι ο φαροφύλακας στον φάρο του Cape Crozier. Από τον θάλαμο του φαναριού καταγράφεις κάθε σκάφος που περνάει, καθένα αναγνωρίζεται από ένα μοναδικό διακριτικό κλήσης, και συντονίζεις επίσης τις αναμεταδόσεις σημάτων με τους άλλους φάρους κατά μήκος της ακτής.

1. Ένα καινούργιο ημερολόγιο

Όρισε το empty-log ώστε να επιστρέφει ένα καινούργιο κενό σύνολο κατακερματισμού, έτοιμο να συγκεντρώσει διακριτικά κλήσης.

empty-log .
! => HS{ }

2. Κατέγραψε μια θέαση

Όρισε το sight ώστε να παίρνει ένα ημερολόγιο και ένα διακριτικό κλήσης και να καταγράφει τη θέαση επιτόπου. Δεν επιστρέφει τίποτα.

empty-log dup "NS-1024" sight .
! => HS{ "NS-1024" }

3. Το έχουμε ξαναδεί αυτό;

Όρισε το seen? ώστε να παίρνει ένα ημερολόγιο και ένα διακριτικό κλήσης, επιστρέφοντας t αν το διακριτικό κλήσης έχει καταγραφεί και f διαφορετικά.

HS{ "NS-1024" "WB-203" } "NS-1024" seen? .   ! => t
HS{ "NS-1024" "WB-203" } "X-99"    seen? .   ! => f

4. Ξέχνα μια θέαση

Όρισε το forget-sighting ώστε να παίρνει ένα ημερολόγιο και ένα διακριτικό κλήσης και να αφαιρεί το διακριτικό κλήσης από το ημερολόγιο επιτόπου. Δεν επιστρέφει τίποτα. Αν το διακριτικό κλήσης δεν υπάρχει, μην κάνεις τίποτα.

HS{ "NS-1024" "WB-203" } clone dup "WB-203" forget-sighting .
! => HS{ "NS-1024" }

5. Πόσα διαφορετικά σκάφη;

Όρισε το unique-count ώστε να επιστρέφει τον αριθμό των διαφορετικών διακριτικών κλήσης στο ημερολόγιο.

HS{ "NS-1024" "WB-203" "AC-77" } unique-count .   ! => 3
empty-log unique-count .                          ! => 0

6. Προσβάσιμοι φάροι

Η ακτοφυλακή διατηρεί έναν relay-map: έναν πίνακα κατακερματισμού όπου τα κλειδιά είναι ονόματα φάρων, και κάθε τιμή είναι ένας πίνακας με τους φάρους προς τους οποίους ο αντίστοιχος φάρος μπορεί να κάνει απευθείας αναμετάδοση.

Όρισε το reachable ώστε να παίρνει έναν φάρο start και έναν relay-map, και να επιστρέφει ένα σύνολο κατακερματισμού με κάθε φάρο που είναι προσβάσιμος από το start (συμπεριλαμβανομένου του ίδιου του start) μέσω επαναλαμβανόμενων αναμεταδόσεων.

H{
    { "Crozier"  { "Beacon"  "Hadley"  } }
    { "Beacon"   { "Crozier" "Spiral"  } }
    { "Hadley"   { "Crozier"           } }
    { "Spiral"   { "Beacon"  "Outpost" } }
    { "Outpost"  { "Spiral"            } }
    { "Far-Isle" { "Lonely"            } }
    { "Lonely"   { "Far-Isle"          } }
}
"Crozier" swap reachable .
! => HS{ "Crozier" "Beacon" "Hadley" "Spiral" "Outpost" }

Το ζεύγος Far-Isle/Lonely αποτελεί δική του συνδεδεμένη συνιστώσα, οπότε κανένα από τα δύο δεν εμφανίζεται στο αποτέλεσμα.

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Factor Exercism

Έτοιμος να ξεκινήσεις την άσκηση Ημερολόγιο Φάρου;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις Factor με 47 έννοιες163 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.