Μετάβαση στο περιεχόμενο

Μετάθεση (μαθηματικά)

Από τη Βικιπαίδεια, την ελεύθερη εγκυκλοπαίδεια

Στα μαθηματικά, μια μετάθεση ενός συνόλου είναι μια τοποθέτηση των στοιχείων αυτού με μια συγκεκριμένη σειρά.

Για παράδειγμα, για τα στοιχεία του συνόλου υπάρχουν οι εξής έξι μεταθέσεις:

Στην γενική περίπτωση, το πλήθος των μεταθέσεων συνόλου με στοιχεία είναι (νι παραγοντικό, δηλαδή

.

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

Σε μία τάξη με μαθητές και θρανία υπάρχουν τόσοι δυνατοί τρόποι να καθίσουν οι μαθητές στα θρανία όσες και οι μεταθέσεις, δηλαδή .

Μία ομάδα παιδιών θέλει να πει τα κάλαντα σε πέντε σπίτια. Υπάρχουν δυνατές σειρές με τις οποίες μπορούν να χτυπήσουν τα κουδούνια.

Πλήθος μεταθέσεων

[Επεξεργασία | επεξεργασία κώδικα]
ν ν!
01
11
22
36
424
5120
6720
75040
840320
9362880
103628800
1139916800
12479001600

Το πλήθος των μεταθέσεων ενός συνόλου με στοιχεία είναι που είναι ίσο με

.

Κατασκευή μεταθέσεων

[Επεξεργασία | επεξεργασία κώδικα]

Αναδρομική κατασκευή

[Επεξεργασία | επεξεργασία κώδικα]

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

Γενική αναδρομική κατασκευή μεταθέσεων με 
  
    
      
        ν
      
    
    {\displaystyle \nu }
  
 στοιχεία, έχοντας τις μεταθέσεις για τα 
  
    
      
        ν
        −
        1
      
    
    {\displaystyle \nu -1}
  
 στοιχεία.
Γενική αναδρομική κατασκευή μεταθέσεων με στοιχεία, έχοντας τις μεταθέσεις για τα στοιχεία.
# Βοηθητική συνάρτησηη που προσθέτει ένα στοιχείο σε κάθε μία από τις δοσμένες λίστες.
def append_to_all(v, arrs):
  ans = []
  for arr in arrs:
    ans.append([v] + arr)
  return ans

def generate_all_permutations(arr):
  # Βασική περίπτωση: Ο πίνακας δεν έχει άλλα στοιχεία.
  if len(arr) == 0:
    return [[]]
  ans = []
  # Για κάθε στοιχείο το βάζουμε πρώτο και βρίσκουμε αναδρομικά
  #  όλες τις μεταθέσεις για τα υπόλοιπα.
  for i in range(len(arr)):
    rem = generate_all_permutations(arr[:i] + arr[i+1:])
    ans += append_to_all(arr[i], rem)
  return ans

print(generate_all_permutations([1,2,3]))

Λεξικογραφική κατασκευή

[Επεξεργασία | επεξεργασία κώδικα]

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

Δουλεύει με τον εξής τρόπο:

  1. Βρίσκουμε το μεγαλύτερο suffix της μετάθεσης που είναι φθίνον.
  1. Το αντιστρέφουμε
  1. Αλλάζουμε θέση στο στοιχείο αριστερά από το suffix και στο αμέσως μεγαλύτερό του στα δεξιά

Η παραπάνω διαδικασία εγγυάται ότι θα διαπεράσουμε τις μεταθέσεις από την λεξικογραφικά μικρότερη προς την λεξικογραφικά μεγαλύτερη.

def next_permutation(arr):
  i = len(arr) - 1
  prev = -1
  while i >= 0 and arr[i] > prev:
    prev = arr[i]
    i -= 1
  if i == -1:
    arr[:] = reversed(arr[:])
    return
  tmp = arr[i]
  j = i + 1
  arr[j:] = reversed(arr[j:])
  while arr[j] < tmp:
    j += 1
  arr[i] = arr[j]
  arr[j] = tmp

arr = [1,2,3,4]
for i in range(25):
  print(arr)
  next_permutation(arr)

Κατασκευή τυχαίας μετάθεσης

[Επεξεργασία | επεξεργασία κώδικα]

Μία τυχαία μετάθεση μπορεί να δημιουργηθεί με τον εξής αλγόριθμο:

  1. Διαλέγουμε τυχαία από τα στοιχεία ποιο θα βάλουμε στην πρώτη θέση.
  2. Έπειτα διαλέγουμε μία μετάθεση για τα υπόλοιπα στοιχεία.
import random

def shuffle(arr):
  N = len(arr) - 1
  for i in range(N):
    j = random.randint(i, N)
    tmp = arr[i]
    arr[i] = arr[j]
    arr[j] = tmp

arr = [1,2,3,4,5,6]
shuffle(arr)
print(arr)
  • Γ. Κοκολάκης, Εισαγωγή στη Θεωρία Πιθανοτήτων και Στατιστική, 1991
  • Άλγεβρα Β΄Λυκείου, Ο.Ε.Δ.Β., 1992