Αγνωστο πληθος με Για

Ξεκίνησε από Sun, 22 Νοε 2007, 01:24:41 ΠΜ

« προηγούμενο - επόμενο »

Sun

Ν.γ.α που διαβαζει αγνωστο πληθος αριθμων και 8α υπολογιζει και 8α εκτυπωνει  το αθροισμα τους  και το μεσο ορο τους.Να τερματιζει οταν διαβαστει ο αριθμος -1 η οταν διαβαστουν 50 αριθμοι.

Λοιπον αδιαμφισβητητα ο καλυτερος τροπο λυσης ειναι με χρηση της "Οσο".Η8ελα ομως την λυσω και με "Για" ακομα και αν ειναι ανορθοδοξο.

ΠΡΟΓΡΑΜΜΑ             
ΜΕΤΑΒΛΗΤΕΣ
  ΠΡΑΓΜΑΤΙΚΕΣ: αριθμος,ι,αθροισμα,πληθος,ΜΟ
ΑΡΧΗ
  αθροισμα <- 0
  πληθος <- 0
  ΔΙΑΒΑΣΕ αριθμος
  ΑΝ αριθμος <> -1 ΤΟΤΕ
    ΓΙΑ ι ΑΠΟ 1 ΜΕΧΡΙ 10^10!θα μπορουσα να βαλω τον μεγαλυτερο..
      ΑΝ ι=50 ΤΟΤΕ
        ι <- 10^10
        αθροισμα <- αθροισμα+αριθμος
        πληθος <- πληθος+1
      ΑΛΛΙΩΣ_ΑΝ αριθμος=-1 ΤΟΤΕ
        ι <- 10^10
      ΑΛΛΙΩΣ
        αθροισμα <- αθροισμα+αριθμος
        πληθος <- πληθος+1
        ΔΙΑΒΑΣΕ αριθμος
      ΤΕΛΟΣ_ΑΝ
    ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
    ΜΟ <- αθροισμα/πληθος
    ΓΡΑΨΕ αθροισμα,ΜΟ
  ΤΕΛΟΣ_ΑΝ
ΤΕΛΟΣ_ΠΡΟΓΡΑΜΜΑΤΟΣ

Αν εξαιρεσουμε καποια "κενα" που βρηκα μονος μου και το γεγονος οτι πειραξα τον μετρητη που ενταξει δεν ειναι σωστο,γινεται καλυτερα?
Περισσοτερο ειναι για την πλακα μου,δεν θα παω ποτε να κανω τετοιες τρελες!  :D
Sincerely...

gpapargi

Καλημέρα

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

Κλασσικό λάθος που θα μπορούσε να γίνει είναι (γράφω μόνο τον επαναληπτικό βρόχο):

πλήθος<-0
S<-0
Διάβασε x
Όσο x <> -1 και πλήθος < 50 επανάλαβε
   S<-S+x
   Πλήθος<-πλήθος +1
   Διάβασε x
Τέλος_επανάληψης

Το πρόβλημα είναι ότι ο έλεγχος για τον αριθμό που διαβάζεται δεν γίνεται ταυτόχρονα με τον έλεγχο για το πλήθος. Αν διαβαστεί -1 τότε ο βρόχος διακόπτεται αυτομάτως χωρίς να διαβαστεί νέος αριθμός. Αν όμως διαβαστεί ο πεντηκοστός τότε ο βρόχος δεν σταματά αυτομάτως. Θα γίνει η επεξεργασία και του πεντηκοστού (πρόσθεση και μέτρηση) και μετά από αυτό θα τερματιστεί ο βρόχος χωρίς να διαβαστεί άλλος αριθμός. Αυτό ακριβώς είναι και το λάθος του παρακάνω αλγορίθμου. Αν διαβάσουμε 50 αριθμούς και κανείς δεν είναι -1 τότε θα διαβαστεί και ο 51 ο οποίος θα αγνοηθεί.

Υπάρχουν 2 τρόποι για σωστή λύση. Αυτός που θεωρώ ευκολότερος είναι η «δομή» (αν μπορώ να την πω έτσι):

τερματισμός<- Ψευδής
Αρχή_επανάληψης
….

Μέχρις_ότου τερματισμός= Αληθής

Όπου τερματισμός μια λογική μεταβλητή

Ουσιαστικά σκεφτόμαστε τι κάνουμε όταν διαβάσουμε κάποιον αριθμό. Να τι κάνουμε:
Αν είναι -1 τερματίζουμε αμέσως
Αν δεν είναι -1 τότε τον επεξεργαζόμαστε (πρόσθεση και μέτρηση)
Αμέσως μετά την επεξεργασία (και μόνο στην περίπτωση που δεν είχε εισαχθεί -1) ελέγχουμε αν το πλήθος είναι 50, οπότε τερματίζουμε αμέσως.

Να και η μεταφορά σε ψευδογλώσσα (παρατήρησε ότι μεταφέρω απλά την παραπάνω σκέψη):

τερματισμός<- Ψευδής
S<-0
Πλήθος<-0

Αρχή_επανάληψης
  Διάβασε x
  Αν x=-1 τότε
     Τερματισμός<-Αληθής
  αλλιώς
     S<S+x
     πλήθος<-πλήθος+1
     Αν πλήθος=50 τότε
          Τερμάτισμός<-Αληθής
     Τέλος_αν
  Τέλος_αν
Μέχρις_ότου τερματισμός= Αληθής

Αυτό θεωρώ εύκολο στη σύλληψη γιατί ταιριάζει πολύ στην ανθρώπινη σκέψη. Όταν σκεφτόμαστε εμείς οι άνθρωποι θέλουμε να ξεκινάμε με Διάβασε. Αυτό είναι το πρώτο που κάνουμε.

Άλλος τρόπος πιο συμπαγής είναι ο παρακάτω (παραλείπω τις αρχικοποιήσεις):

Αρχή_επανάληψης
  Διάβασε x
  Αν x<> -1 τότε
       S<S+x
       πλήθος<-πλήθος+1
   Τέλος_αν
Μέχρις_ότου x=-1 ή πλήθος = 50

Σε αυτή την προσέγγιση ουσιαστικά κρύβουμε σε μια συνθήκη «Αν» τις εντολές που δεν εκτελούνται αν ισχύει η μια συνθήκη διακοπής έτσι ώστε να κάνουμε ταυτόχρονα τον έλεγχο και για τις 2 συνθήκες.

Να και η προσέγγιση με Όσο:

Διάβασε x
Όσο x<>0 και πλήθος <50 επανάλαβε
   S<-S+x
   πλήθος<-πλήθος+1
   Αν πλήθος<50 τότε
       Διάβασε x
   Τέλος_αν
Τέλος_επανάληψης

Οι 2 τελευταίοι κώδικες είναι πιο συμπαγείς. Ο πρώτος όμως είναι πιο κοντά στο αληθινό πρόβλημα αφού διατηρεί τη σχετική χρονική σειρά μεταξύ των ελέγχων. Οι έλεγχοι δεν γίνονται ταυτόχρονα όπως υπονοούν οι 2 τελευταίες κωδικοποιήσεις.

Παρατήρησε ότι ο πρώτος τρόπος είναι πολύ κοντά και τη δική σου σκέψη. Αυτό που γράφω εγώ σαν «Τερματισμός <- αληθής» εσύ το γράφεις «ι<-10^10».
Η μόνη διαφορά στη σύλληψη σου από τη δική μου είναι ότι εσύ θεώρησες την περίπτωση που το πλήθος είναι 50 σαν ξεχωριστή περίπτωση. Ενώ εγώ τη θεώρησα σαν μια υποπερίπτωση της περίπτωσης που διαβάσαμε κάτι διαφορετικό από -1 γι αυτό και προχώρησα σε εμφώλευση. Έτσι γλίτωσα το να ξαναγράψω τις εντολές για πρόσθεση και μέτρηση. Κατά τα άλλα είναι πανομοιότυπες σκέψεις.

Ωστόσο πρόσεξε πως ακριβώς την ίδια σύλληψη μπορείς να γράψεις από κάτι τελείως ανορθόδοξο (σαν αυτό που έγραψες) εως κάτι απόλυτα νόμιμο.  Το να μετατρέπεις τη σκέψη σου σε ορθόδοξο και καλογραμμένο πρόγραμμα είναι μέρος της δουλειάς του προγραμματιστή. Οπότε θα πρέπει να δουλεύεις προς αυτή την κατεύθυνση.

Κάτι άλλο που ήθελα να πω είναι πάντα να προσέχεις όταν κάνεις διαιρέσεις. Μπορεί ο παρονομαστής να είναι 0. Οπότε βάζεις μια "Αν" για προστασία. Αυτό είναι πολύ συνηθισμένο στους μέσους όρους.

Τέλος, δες στο παρακάτω link το 3ο ερώτημα του μαθητή καθώς και την απάντηση που του έδωσα παρακάτω. Σχετίζεται με τη διακοπή της Για με τον τρόπο αλλαγήςτου μετρητή. Δες επίσης και τις απαντήσεις των άλλων συναδέλφων στο ίδιο θέμα.

https://alkisg.mysch.gr/steki/index.php?topic=286.0

spi

Δεν ηταν αναγκη να το γραψετε κυριε Γιώργο...το εχουμε καταλαβει ολοι μας πολυ καλα... :D 8)

Χάρης Τσιαΐρης

Το σημείο κλειδί είναι στην αρχική τιμή

πλήθος<-1
S<-0
Διάβασε x
Όσο x <> -1 και πλήθος < 50 επανάλαβε
   S<-S+x
   Πλήθος<-πλήθος +1
   Διάβασε x
Τέλος_επανάληψης

Αφού το "πλήθος" μετράει τους αριθμούς που έχουν διαβαστεί τότε η αρχική τιμή θα πρέπει να είναι 1.

Χάρης Τσιαΐρης



P.Tsiotakis

Χάρη, αν δοθεί το -1 στην αρχή, δεν πρέπει να καταμετρηθεί...

Αν δοθούν 50 αριθμοι (όχι -1), δεν πρέπει να διαβαστεί 51ος, η ανάλυση του Γιώργου είναι σωστή

Χάρης Τσιαΐρης

Έχεις δίκιο Παναγιώτη αλλά λόγο κεκτημένης ταχύτητας ... έφαγα το τέλος

Το ξαναδίνω:

πλήθος <- 1
  s <- 0
  ΔΙΑΒΑΣΕ x
  ΟΣΟ x <> -1 ΚΑΙ πλήθος < 50 ΕΠΑΝΑΛΑΒΕ
    s <- s+x
    πλήθος <- πλήθος +1
    ΔΙΑΒΑΣΕ x
  ΤΕΛΟΣ_ΕΠΑΝΑΛΗΨΗΣ
  ΑΝ x=-1 ΤΟΤΕ
    πλήθος <- πλήθος -1
  ΑΛΛΙΩΣ
    s <- s+x
  ΤΕΛΟΣ_ΑΝ
 
Η διαφορά είναι ότι ελέγχει το λόγο τερματισμού και ανάλογα είτε αυξάνεται το άθροισμα είτε το πλήθος. Θεωρώ αυτή τη μορφή απλούστερη καθώς:

  • Δεν έχει εμφώλευση
  • Εισάγει μία έννοια στους μαθητές (αναφέρομαι στον έλεγχο του εξαιτίας από ποιο λόγο τερματίστηκε η επανάληψη)

Με εκτίμηση,

Χάρης Τσιαΐρης