Αποστολέας Θέμα: Άσκηση με Αντιμεταθέσεις  (Αναγνώστηκε 4300 φορές)

evry

  • Γενικός διαχειριστής
  • *****
  • Μηνύματα: 3286
  • to Iterate is human to Recurse divine
Άσκηση με Αντιμεταθέσεις
« στις: 13 Απρ 2012, 11:03:55 πμ »
Δίνεται ένας πίνακας με λογικές τιμές (Αληθής/Ψευδής) Ν θέσεων.

Να γράψετε αλγόριθμο ο οποίος να τοποθετεί όλες τις  Αληθείς πριν από τις Ψευδείς. Για παράδειγμα αν δοθεί ο παρακάτω πίνακας

  Ψευδής   Αληθής   Ψευδής   Ψευδής   Αληθής   Αληθής
     1             2             3             4             5            6

ο τελικός πίνακας θα είναι ο παρακάτω

  Αληθής   Αληθής   Αληθής   Ψευδής   Ψευδής   Ψευδής
     1             2             3            4             5            6

α) τρόπος (με διπλή επανάληψη)
β) τρόπος (με δύο σαρώσεις αλλά ουσιαστικά ξεφτιλίζει τη δυσκολία του προβλήματος)

γ) τρόπος που μας ενδιαφέρει με τους εξής περιορισμούς
     1. Θα σαρώσετε τα στοιχεία του πίνακα μόνο μια φορά. Υπόδειξη: Χρησιμοποιήστε την Αντιμετάθεσε
        (Δηλαδή εδώ ούτε δύο σαρώσεις μπορείτε να κάνετε, ούτε διπλή επανάληψη κάπου)

ΥΓ. Σε τέτοια προβλήματα η χρήση επιπλέον δομών δεδομένων πρέπει να είναι η τελευταία μας λύση. Φυσικά εδώ απαγορεύεται ;)
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

Πανάγος94

  • Βετεράνος
  • ****
  • Μηνύματα: 65
  • what doesn't kill you only makes you pissed off..
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #1 στις: 13 Απρ 2012, 11:02:31 μμ »
έστω Α[Ν] ο πίνακας, και αφού θεωρείται δεδομένος θα γράψω μόνο το κομμάτι που ζητείται

πλ <- 0 ! πλήθος αντιμεταθέσεων
Για ι από 2 μέχρι Ν
Αν Α[ι] = Αληθής τότε
πλ <- πλ + 1
Αντιμετάθεσε Α[ι],Α[πλ]
τέλος_αν
Τέλος_επανάληψης

δεν ξέρω αν είναι ο πιο αποτελεσματικός τρόπος αλλά δουλεύει...άμα βρείτε κανένα λάθος ειδοποιήστε!! :)

evry

  • Γενικός διαχειριστής
  • *****
  • Μηνύματα: 3286
  • to Iterate is human to Recurse divine
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #2 στις: 13 Απρ 2012, 11:07:02 μμ »
Βασικά δεν μπορώ να καταλάβω τι θέλεις να κάνεις. Το εξηγείς λίγο?

έστω Α[Ν] ο πίνακας, και αφού θεωρείται δεδομένος θα γράψω μόνο το κομμάτι που ζητείται

πλ <- 0 ! πλήθος αντιμεταθέσεων
Για ι από 2 μέχρι Ν
Αν Α[ι] = Αληθής τότε
πλ <- πλ + 1
Αντιμετάθεσε Α[ι],Α[πλ]
τέλος_αν
Τέλος_επανάληψης

δεν ξέρω αν είναι ο πιο αποτελεσματικός τρόπος αλλά δουλεύει...άμα βρείτε κανένα λάθος ειδοποιήστε!! :)

edit:
οκ, νομίζω ότι κατάλαβα τι πας να κάνεις, αλλά για τρέξτο για τον παρακάτω πίνακα

Α[1] ←  Αληθής
Α[2] ←  Αληθής
Α[3] ←  Αληθής
Α[4] ←  Ψευδής
Α[5] ←  Αληθής
Α[6] ←  Ψευδής

Ωστόσο η λύση σου μπορώ να πω ότι είναι πολύ έξυπνη.
Μια μικρή υπόδειξη όμως μια και το έφτασες ως εδώ. Για να κάνεις αντιμετάθεση σε 2 στοιχεία θα πρέπει να εξασφαλίσεις ότι και τα 2 είναι σε λάθος θέση.
Δηλαδή αν δεν κάνεις περιττές αντιμεταθέσεις τότε εξασφαλίζεις και την ορθότητα του αλγορίθμου σου.
Χωρίς αυτό να σημαίνει ότι δεν γίνεται αλλιώς.
« Τελευταία τροποποίηση: 13 Απρ 2012, 11:47:23 μμ από evry »
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

Stavros

  • Θαμώνας
  • ***
  • Μηνύματα: 40
    • http://csforces.gr/
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #3 στις: 14 Απρ 2012, 01:47:16 πμ »
Συγγνώμη για τον τρόπο που τα γράφω αλλα αφού είναι αλγόριθμος...
Ελπίζω να μην έκανα κάποιο λάθος στη μετατροπή από τη C στην ψευδογλώσσα.

Κώδικας: [Επιλογή]
l<-1
r<-N
while(l<r){
if(table[l]=false AND table[r]=true){
antimetathese(table[l],table[r])
}
else if(table[l]=true AND table[r]=true){
l=l+1
while(table[l]=true AND l<r)
l=l+1
                       if(l<r)
        antimetathese(table[l], table[r])
}else if(table[l]=false AND table[r]=false){
r=r-1
while(table[r]=false AND l<r)
r=r-1
if(l<r)
       antimetasthese(table[l],table[r])
}
l<-l+1
r<-r-1
}
Stavros
3ετής φοιτητής πληροφορικής


Το νέο φοιτητικό site
www.universitas.gr
www.csforces.gr/forums
All about computers!!!
Join us!!!!

evry

  • Γενικός διαχειριστής
  • *****
  • Μηνύματα: 3286
  • to Iterate is human to Recurse divine
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #4 στις: 14 Απρ 2012, 10:24:03 πμ »
Βασικά μια τέτοια λύση περίμενα για το γ) αλλά ο Πανάγος με κούφανε :D

Δηλαδή δύο δείκτες οι οποίοι κάθε φορά έχουν σαν στόχο να βρουν δύο στοιχεία που είναι σε λάθος θέση ώστε με μια αντιμετάθεση να βρεθούν και τα 2 εκεί που πρέπει.
Για δες λίγο μήπως μπορείς να απαλείψεις τις επαναλήψεις που έχεις μέσα στο if.
Δεν χρειάζονται. Σκέψου ότι κάθε φορά που ο δείκτης (ή ο πάνω ή ο κάτω) βρίσκει ένα στοιχείο στην σωστή θέση απλά προχωράει μια θέση πιο κάτω. Δεν νομίζω να χρειάζεται επανάληψη.
Φυσικά το ότι έχει διπλή επανάληψη δεν σημαίνει ότι η πολυπλοκότητα του αλγορίθμου (απόδοση) αλλάζει. Η ίδια είναι αφού οι ίδιες συγκρίσεις θα γίνουν πάνω κάτω.

Επίσης γιατί αντιμεταθέτεις και στην περίπτωση που είναι ίδια? (Αληθής,Αληθής και Ψευδής,Ψευδής)

Συγγνώμη για τον τρόπο που τα γράφω αλλα αφού είναι αλγόριθμος...
Ελπίζω να μην έκανα κάποιο λάθος στη μετατροπή από τη C στην ψευδογλώσσα.

Κώδικας: [Επιλογή]
l<-1
r<-N
while(l<r){
if(table[l]=false AND table[r]=true){
antimetathese(table[l],table[r])
}
else if(table[l]=true AND table[r]=true){
l=l+1
while(table[l]=true AND l<r)
l=l+1
                       if(l<r)
        antimetathese(table[l], table[r])
}else if(table[l]=false AND table[r]=false){
r=r-1
while(table[r]=false AND l<r)
r=r-1
if(l<r)
       antimetasthese(table[l],table[r])
}
l<-l+1
r<-r-1
}
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

Πανάγος94

  • Βετεράνος
  • ****
  • Μηνύματα: 65
  • what doesn't kill you only makes you pissed off..
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #5 στις: 14 Απρ 2012, 12:47:53 μμ »
έτσι το εννούσες??

θ ← 0
Για ι από 1 μέχρι Ν
  Αν α[ι] = Ψευδής τότε
    Αν θ = 0 τότε θ ← ι
  αλλιώς
    Αν θ > 0 τότε
      Αντιμετάθεσε α[ι], α[θ]
      θ ← ι
    Τέλος_αν
  Τέλος_αν
Τέλος_επανάληψης

Stavros

  • Θαμώνας
  • ***
  • Μηνύματα: 40
    • http://csforces.gr/
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #6 στις: 14 Απρ 2012, 01:30:36 μμ »
Παράθεση
Βασικά μια τέτοια λύση περίμενα για το γ) αλλά ο Πανάγος με κούφανε :D

Δηλαδή δύο δείκτες οι οποίοι κάθε φορά έχουν σαν στόχο να βρουν δύο στοιχεία που είναι σε λάθος θέση ώστε με μια αντιμετάθεση να βρεθούν και τα 2 εκεί που πρέπει.
Για δες λίγο μήπως μπορείς να απαλείψεις τις επαναλήψεις που έχεις μέσα στο if.
Δεν χρειάζονται. Σκέψου ότι κάθε φορά που ο δείκτης (ή ο πάνω ή ο κάτω) βρίσκει ένα στοιχείο στην σωστή θέση απλά προχωράει μια θέση πιο κάτω. Δεν νομίζω να χρειάζεται επανάληψη.
Φυσικά το ότι έχει διπλή επανάληψη δεν σημαίνει ότι η πολυπλοκότητα του αλγορίθμου (απόδοση) αλλάζει. Η ίδια είναι αφού οι ίδιες συγκρίσεις θα γίνουν πάνω κάτω.

Επίσης γιατί αντιμεταθέτεις και στην περίπτωση που είναι ίδια? (Αληθής,Αληθής και Ψευδής,Ψευδής)

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

Όταν 2 στοιχεια είναι ίδια δεν τα αντιμεταθέτω. Σε αυτό το while p.x.

else if(table[l]=true AND table[r]=true){
      l=l+1
     while(table[l]=true AND l<r)
     l=l+1

Όταν ελέγξω ότι δυο στοιχεια είναι ίδια ψάχνω να βρω αν υπάρχει το επόμενο στοιχειο που είναι ψευδές από τον δείκτη l, και τότε να τα αντιμεταθέσω.

Παράθεση
θ ← 0
Για ι από 1 μέχρι Ν
  Αν α[ι] = Ψευδής τότε
    Αν θ = 0 τότε θ ← ι
  αλλιώς
    Αν θ > 0 τότε
      Αντιμετάθεσε α[ι], α[θ]
      θ ← ι
    Τέλος_αν
  Τέλος_αν
Τέλος_επανάληψης

Ωραίος αλγόριθμος αλλα νομίζω πως χρειάζεται μερικές λίγες διορθώσεις για να γίνει καλύτερος... Λίγη προσπάθεια ακόμη και θα είναι έτοιμος.
Η μονη παρατήρηση εδώ (δεν ξέρω αν υπάρχουν κι άλλες) είναι πως, ok κανεις ένα πέρασμα αλλα επίσης κανεις και παρα πολλές αντιμεταθέσεις. p.x.
Αν έχεις πινακα 1000000000 (1 dis) με το πρώτο στοιχειο ψευδές και όλα τα αλλα αληθή τότε θα κανεις 1000000000-1 αντιμεταθέσεις ενώ θα μπορούσε να γίνει με 1 μόλις αντιμετάθεση.
« Τελευταία τροποποίηση: 14 Απρ 2012, 01:41:53 μμ από Stavros »
Stavros
3ετής φοιτητής πληροφορικής


Το νέο φοιτητικό site
www.universitas.gr
www.csforces.gr/forums
All about computers!!!
Join us!!!!

evry

  • Γενικός διαχειριστής
  • *****
  • Μηνύματα: 3286
  • to Iterate is human to Recurse divine
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #7 στις: 14 Απρ 2012, 02:45:04 μμ »
ναι οκ, το είδα βιαστικά.
και πάλι όμως δεν υπάρχει λόγος για τις εσωτερικές επαναλήψεις.
δηλαδή σε κάθε περίπτωση που βρίσκεις μια τιμή στη σωστή θέση απλά προχωράς τους μετρητές μια θέση πιο πέρα και τη δουλειά
που κάνουν οι εσωτερικές την κάνει η εξωτερική.
η βασική ιδέα μοιάζει λίγο με τον αλγόριθμο της συγχώνευσης
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr

Stavros

  • Θαμώνας
  • ***
  • Μηνύματα: 40
    • http://csforces.gr/
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #8 στις: 14 Απρ 2012, 03:04:19 μμ »
Ναι ok, είπα ότι κατά κάποιον τρόπο είναι περίρα τα 2a while, απλά δεν χάνουμε σε χρόνο (για να μην πω πως κερδίζουμε λίγο) απλά χάνουμε ας πούμε τη <<συνεχεια>> του αλγοριθμου. Εν πάση περίπτωση την ιδέα του αλγοριθμου εξετάζουμε, και πιστεύω πως λέμε ακριβώς το ίδιο. Απλά εδώ σε εμενα αυτό είναι πιο κατανοητό.
Stavros
3ετής φοιτητής πληροφορικής


Το νέο φοιτητικό site
www.universitas.gr
www.csforces.gr/forums
All about computers!!!
Join us!!!!

alkisg

  • Τεχνικός / καθαρίστρια
  • *****
  • Μηνύματα: 5303
    • Ο Διερμηνευτής της ΓΛΩΣΣΑΣ
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #9 στις: 14 Απρ 2012, 03:24:47 μμ »
και πάλι όμως δεν υπάρχει λόγος για τις εσωτερικές επαναλήψεις.

Αν μπει πολλαπλή Αν μέσα σε μία μόνο επανάληψη, τότε το πρώτο σκέλος της Αν πιθανώς να προσπελαύνει το ίδιο στοιχείο πολλές φορές, καταπατώντας τον περιορισμό της εκφώνησης για μία ανάγνωση κάθε στοιχείου του πίνακα (λογικός περιορισμός αν ο πίνακας αντιπροσωπεύει κάποια κάποια αργή μνήμη, π.χ. δίσκος). Οπότε για μία επανάληψη χρειάζεται caching, και έτσι γίνεται πιο πολύπλοκο από ότι πολλές εμφωλευμένες.

Αδοκίμαστα:
Κώδικας: Text
  1. ι=1
  2. κ=Ν
  3. Όσο ι < κ επανάλαβε
  4.     Αν Α[ι] = Ψευδής τότε
  5.         ι <- ι + 1
  6.     αλλιώς_αν Α[κ] = Αληθής τότε
  7.         κ <- κ - 1
  8.     αλλιώς
  9.         Αντιμετάθεσε Α[ι], Α[κ]
  10.         ι <- ι + 1
  11.         κ <- κ - 1
  12.     τέλος_αν
  13. τέλος_επανάληψης
  14.  

Κώδικας: Text
  1. ι=1
  2. κ=Ν
  3. Όσο ι < κ επανάλαβε
  4.     Όσο Α[ι] = Ψευδής επανάλαβε
  5.         ι <- ι + 1
  6.     τέλος_επανάληψης
  7.     Όσο (προαιρετικά: ι < κ και) Α[κ] = Αληθής επανάλαβε
  8.         κ <- κ - 1
  9.     τέλος_επανάληψης
  10.     Αν ι < κ τότε
  11.         Αντιμετάθεσε Α[ι], Α[κ]
  12.     τέλος_επανάληψης
  13. τέλος_επανάληψης
  14.  

...προτιμώ τη δεύτερη εκδοχή, που ελαχιστοποιεί τις φορές που το ίδιο στοιχείο του πίνακα διαβάζεται παραπάνω από μία φορά, χωρίς να βάζει την πολυπλοκότητα του caching.

evry

  • Γενικός διαχειριστής
  • *****
  • Μηνύματα: 3286
  • to Iterate is human to Recurse divine
Απ: Άσκηση με Αντιμεταθέσεις
« Απάντηση #10 στις: 14 Απρ 2012, 04:02:49 μμ »
Όταν έθεσα την άσκηση είχα στο μυαλό μου την 1η λύση που είναι αρκετά απλή και θυμίζει και λίγο συγχώνευση.
Ουσιαστικά η 2η που δίνεις είναι μια βελτιστοποιημένη εκδοχή της 1ης όπως λες.
Όταν έβαζα τον περιορισμό της μιας σάρωσης ο σκοπός μου ήταν να αποτρέψω την διπλή επανάληψη, δηλαδή το O(n^2).
Για να μην πω εξαρχής O(n^2) που οι μαθητές δεν ξέρουν τι είναι, προτίμησα αυτή τη διατύπωση.
What I cannot create I do not understand -- Richard Feynman
http://evripides.mysch.gr