Çok uğraşmanız gerektiğini düşünmüyorum.
Basitçe adımlayalım.
Dört grubumuz var. Gruptaki öğrenci sayılarına göre gruplayalım. En uzun grup ana grubumuz olsun, daha sonra bir sonraki gruptan bir öğrenci çekelim. ve ilk en uzun gruptan çektiğimiz ile bireştirim bir listeye ekleyelim. Kısa grup bittiğinde bir sonraki kısa gruba geçerek devam edelim. Eğer en uzun grubumuzun sona geldi ise en uzun grubun tekrar başına dönerek, sıradaki kısa gruplardan eklemeye devam edelim şeklinde basit bir kod ile halledebilirsiniz. Sorun yaşarsanız ona da bakabiliriz.
EDIT 1:
Sizin için basit bir algoritma üzerinde konuşalım:
Elimizde bir listeler grubu olsun:
A = ["A-71", "A-26", "A-84", "A-67","A-68"]
B = ["B-84", "B-7", "B-63", "B-49"]
C = ["C-89", "C-105", "C-110", "C-120"]
D = ["D-63", "D-15", "D-39", "D-31", "D-84", "D-25", "D-91", "D-67", "D-2", "D-71"]
Farklı uzunlukta dört listemiz var.
lists = [A, B, C, D]
for group in lists:
random.shuffle(group)
Her grubu kendi içerisinde karıştıralım. Böylece her öğrenci sınıf listesindeki sıradan farklı bir konunmda liste içinde karıştırılmış olur. Ama hala aynı gruptan öğrenciler aynı grupta kalmaya devam etmektedir.
Sonra bu dört grubun öğrenci sayılarına göre büyükten küçüğe sıralnamasını sağlayalım.
sorted_lists = sorted(lists, key=lambda x: len(x), reverse=True)
Artık elimizde, kendi içinde rastgele karıştırılmış dört listenin büyükten küçüğe sıralanmış hali var.
Aşağıda bu büyükten küçüğe sıralanmış dört listenin hepsini bir birine birleştirelim:
merged_list = []
for group in sorted_lists:
merged_list.extend(group)
Yani şu an sadece aynı sınıf öğrencilerinin yan yana yazıldığı ve tüm grupların birleştirildiği bir listemiz var.
Şimdi algoritmanın kilit kısmına geldik. Bu şekli ile öğrenciler yan yana olduğundan istediğim sonuca henüz olaşamadık.
Şimdi bu birleşik listeyi, ortadan ikiye bölelim:
length = len(merged_list)
mid = length // 2
first_half = merged_list[:mid]
second_half = merged_list[mid:]
Artık birleştirilmiş dört gruptan oluşan iki listemiz iki parçaya bölündü.
Sıralı bir iskambil destesi düşünün, sonra bu desteyi ortadan ikiye böldük ve iki parçayı bir sağ deste yarısından bir sol deste yarısından ekleyerek karıştırırsak aynı gruptan yan yana öğrenci kalmayacaktır.
Peki deste tek sayı ise?
Bu durumda bölünmüş büyük destenin arasına küçük olan desteyi birer birer yerleştiriyoruz.
Bunu yapan kod parçasını da ekleyelim:
if len(first_half) >= len(second_half):
longer_list = first_half
shorter_list = second_half
else:
longer_list = second_half
shorter_list = first_half
merged_list = []
for i in range(len(longer_list)):
merged_list.append(longer_list[i])
if i < len(shorter_list):
merged_list.append(shorter_list[i])
Şimdi, artık listemiz tekrar birleşti ama bu sefer aynı gruptan öğrenciler yan yana olmayacaktır. Aynı zamanda sonda da yan yana artan öğrenci olmayacaktır.
Şimdi birleştirilmiş, karıştırılmış ve aynı grupta öğrencilerin yan yana gelmediğine emin olmak için ekrana çıktısını alalım.
print(merged_list)
Bu durumda kodun tümünü bir kez daha vereyim:
import random
A = ["A-71", "A-26", "A-84", "A-67","A-68"]
B = ["B-84", "B-7", "B-63", "B-49"]
C = ["C-89", "C-105", "C-110", "C-120"]
D = ["D-63", "D-15", "D-39", "D-31", "D-84", "D-25", "D-91", "D-67", "D-2", "D-71"]
###############################################
lists = [A, B, C, D]
for group in lists:
random.shuffle(group)
###############################################
sorted_lists = sorted(lists, key=lambda x: len(x), reverse=True)
###############################################
merged_list = []
for group in sorted_lists:
merged_list.extend(group)
###############################################
length = len(merged_list)
mid = length // 2
first_half = merged_list[:mid]
second_half = merged_list[mid:]
###############################################
if len(first_half) >= len(second_half):
longer_list = first_half
shorter_list = second_half
else:
longer_list = second_half
shorter_list = first_half
merged_list = []
for i in range(len(longer_list)):
merged_list.append(longer_list[i])
if i < len(shorter_list):
merged_list.append(shorter_list[i])
print(merged_list)
#################################################
Basit bir algoritma. Okunaklı kalsın diye her adımı ayırdım ve basitleştirdim. Hepsini birleştirip tek bir fonksiyın yada sınıf içine de alabilirsiniz.
Kolay gelsin.
EDIT 2:
Şimdi bu algoritmayı nasıl bir qt arayüzü ile kullanabilirize bakalım.
Koda ufak eklemeler yaptım:
Öncelikle random sınıf mevcutları oluşturmak için minimum 10 max 15 kişilik sınıflar oluşturulmasını sağladım.
count = random.randint(10, 15)
Satırı ile istediğimiz aralıkta sınıf mevcutlarımız oluştu.
Listeleri rastgele doldur butonuna bastığımızda dört grubun içerisine 10-15 aralığında rastgele sayıda öğrenciler yerleştiriliyor.
Daha sonra bir önceki EDIT’te anladığım karıştıran algoritmayı uygulamak ve alttaki listbox’a yazmdırmak için “Listeleri birleştir” butonuna basıyoruz.
Artık en alttaki liste kutumuzda, karıştırılmış ve bir biri ile aynı gruptan yan yana öğrencilerin gelmediği birleşik listemizi oluşturmuş oluyoruz.
Bu tek listeyi istediğimiz gibi tekrar alt gruplara bölebiliriz.
Dört liste kutumuzun dört sınıf mahali olduğunu ve bu birleşik listediki öğrenciler olabildiğince eşit sayıda bölüp sınıflara yerleştirdiğimizi düşünelim.
Bunun için de;
son olarak “Listeyi Gruplara Yeniden Yerleştir” e basıyoruz. Bu butona bastığımızda liste dört eşit parçaya bölünmeye çalışılır. Aslında numpy kütüphanesi ile daha basit bölünebilirdi ama ben biraz daha dengeli bir bölme için kendim bir parça kod yazım.
Sonuçta butona bastığımızda her sınıf mahaline eşit/eşite yakın sayıda öğrenci bölünerek dağıtılıyor. Tabi önce bu dört sınıf listbox’ını temizliyoruz sonra da böldüğümüz parçaları her bir listeye yerleştiriyoruz.
Dört liste kutusu içerisinde gezindiğinizde her sınıf grubunun içinde aynı sınıftan öğrencilerin yan yana gelmediğini. Aynı zamanda her sınıfta da aşağı yukarı aynı sayıda öğrenci olacak dört sınıfın içine yerleştirdiğini görebiliyoruz.
Umarım bu kod fikir verebilir:
import sys
import random
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QListWidget, QPushButton
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Dört Grup Sınıf Örneği")
self.setGeometry(100, 100, 300, 400)
layout = QVBoxLayout()
self.list_widgets = []
group_names = ["A", "B", "C", "D"]
for group_name in group_names:
list_widget = QListWidget()
list_widget.setObjectName(group_name)
layout.addWidget(list_widget)
self.list_widgets.append(list_widget)
populate_button = QPushButton("Listeleri Rastgele Doldur")
populate_button.clicked.connect(self.populate_lists)
layout.addWidget(populate_button)
merge_button = QPushButton("Listeleri Birleştir")
merge_button.clicked.connect(self.merge_lists)
layout.addWidget(merge_button)
replace_button = QPushButton("Listeyi Gruplara Yeniden Yerleştir")
replace_button.clicked.connect(self.distribute_lists)
layout.addWidget(replace_button)
self.merged_list_widget = QListWidget()
layout.addWidget(self.merged_list_widget)
self.setLayout(layout)
self.A = []
self.B = []
self.C = []
self.D = []
self.chunks = []
def populate_lists(self):
for list_widget in self.list_widgets:
list_widget.clear()
group_name = list_widget.objectName()
count = random.randint(10, 15)
for _ in range(count):
number = random.randint(1, 100)
list_widget.addItem(f"{group_name} - {number}")
if group_name == "A":
self.A.append(group_name+"-"+str(number))
elif group_name == "B":
self.B.append(f"{group_name}-{number}")
elif group_name == "C":
self.C.append(f"{group_name}-{number}")
elif group_name == "D":
self.D.append(f"{group_name}-{number}")
def merge_lists(self):
self.merged_list_widget.clear()
lists = [self.A, self.B, self.C, self.D]
for group in lists:
random.shuffle(group)
sorted_lists = sorted(lists, key=lambda x: len(x), reverse=True)
merged_list = []
for group in sorted_lists:
merged_list.extend(group)
length = len(merged_list)
mid = length // 2
first_half = merged_list[:mid]
second_half = merged_list[mid:]
if len(first_half) >= len(second_half):
longer_list = first_half
shorter_list = second_half
else:
longer_list = second_half
shorter_list = first_half
merged_list = []
for i in range(len(longer_list)):
merged_list.append(longer_list[i])
if i < len(shorter_list):
merged_list.append(shorter_list[i])
for item in merged_list:
self.merged_list_widget.addItem(str(item))
list_length = len(merged_list)
chunk_size = list_length // 4
remainder = list_length % 4
chunks = []
start = 0
for i in range(4):
if remainder > 0:
end = start + chunk_size + 1
remainder -= 1
else:
end = start + chunk_size
chunk = merged_list[start:end]
self.chunks.append(chunk)
start = end
def distribute_lists(self):
for list_widget in self.list_widgets:
list_widget.clear()
for count in range(4):
self.list_widgets[count].addItems(self.chunks[count])
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Kolay gelsin.