dalagiorgos

Eliminate Clubs

Oct 25th, 2025
830
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
R 7.06 KB | Source Code | 0 0
  1. # eliminateclubs_fixed.R
  2. # Εξάρτηση: install.packages(c("dplyr", "readr", "tidyr"))
  3.  
  4. library(dplyr)
  5. library(readr)
  6. library(tidyr)
  7.  
  8. # --- Ρυθμίσεις ---
  9. min_threshold <- 10L
  10. responses_file <- "responses.csv"
  11. clubs_file <- "clubs.csv"
  12. output_prefix <- "responses_round"
  13.  
  14. # --- Διαβάζουμε δεδομένα ---
  15. responses <- read_csv(responses_file, show_col_types = FALSE)
  16. clubs <- read_csv(clubs_file, show_col_types = FALSE)
  17.  
  18. # --- Καθαρισμός και εναρμόνιση (όπως πριν) ---
  19. colnames(clubs) <- tolower(trimws(colnames(clubs)))
  20. clubs$club_id <- trimws(tolower(clubs$club_id))
  21. if("club_name" %in% colnames(clubs)) {
  22.   clubs$club_name <- trimws(clubs$club_name)
  23. } else if("clubname" %in% colnames(clubs)) {
  24.   clubs$club_name <- trimws(clubs$clubname)
  25. } else {
  26.   clubs$club_name <- clubs$club_id
  27. }
  28.  
  29. student_col <- colnames(responses)[1]
  30. initial_club_cols <- trimws(tolower(colnames(responses)[-1]))
  31. colnames(responses) <- c(student_col, initial_club_cols)
  32.  
  33. # Μετατροπή σε 'long' μορφή για ευκολότερη διαχείριση προτιμήσεων
  34. responses_long_master <- responses |>
  35.   pivot_longer(cols = -all_of(student_col),
  36.                names_to = "ClubID", values_to = "Rank") |>
  37.   mutate(
  38.     ClubID = trimws(tolower(ClubID)),
  39.     # Εξασφάλιση ότι το Rank είναι ακέραιος
  40.     Rank = as.integer(Rank)
  41.   ) |>
  42.   # Φιλτράρουμε μόνο τις καταγεγραμμένες προτιμήσεις
  43.   filter(!is.na(Rank))
  44.  
  45.  
  46. round <- 1L
  47. elimination_log <- data.frame(Round=integer(), ClubID=character(), ClubName=character(), FirstPrefCount=integer(), stringsAsFactors = FALSE)
  48. active_clubs <- initial_club_cols
  49.  
  50. repeat {
  51.   # --- Βήμα 1: Υπολογισμός Πρώτων Προτιμήσεων (Τρέχουσα κατάσταση) ---
  52.   # Βρίσκουμε την τρέχουσα υψηλότερη προτίμηση (το χαμηλότερο Rank) για κάθε μαθητή
  53.   current_prefs <- responses_long_master |>
  54.     # Φιλτράρουμε μόνο τους ενεργούς Ομίλους
  55.     filter(ClubID %in% active_clubs) |>
  56.     # Βρίσκουμε το ελάχιστο Rank (την πρώτη προτίμηση)
  57.     group_by(across(all_of(student_col))) |>
  58.     filter(Rank == min(Rank, na.rm = TRUE)) |>
  59.     ungroup()
  60.  
  61.   # Μετράμε τις πρώτες προτιμήσεις
  62.   counts <- current_prefs |>
  63.     count(ClubID, name = "FirstPrefCount") |>
  64.     right_join(data.frame(ClubID = active_clubs), by = "ClubID") |>
  65.     replace_na(list(FirstPrefCount = 0)) |>
  66.     # Μετατροπή σε named vector για εύκολη χρήση
  67.     tibble::deframe()
  68.  
  69.   cat(sprintf("\n--- Γύρος %d ---\n", round))
  70.   cat("Όμιλοι και πρώτες προτιμήσεις:\n")
  71.   print(data.frame(ClubID=names(counts), FirstPref=as.integer(counts)), row.names = FALSE)
  72.  
  73.   # --- Βήμα 2: Έλεγχος Τερματισμού ---
  74.   if(length(active_clubs) == 0) {
  75.     cat("\nΤερματισμός: Δεν έμεινε κανένας Όμιλος.\n")
  76.     break
  77.   }
  78.   if(all(counts >= min_threshold)) {
  79.     cat("\nΤερματισμός: όλοι οι ενεργοί Όμιλοι έχουν τουλάχιστον ", min_threshold, " πρώτες προτιμήσεις.\n", sep = "")
  80.     # Αναδημιουργία του τελικού responses_wide για αποθήκευση
  81.     responses_final_wide <- responses_long_master |>
  82.       filter(ClubID %in% active_clubs) |>
  83.       pivot_wider(id_cols = all_of(student_col),
  84.                   names_from = ClubID, values_from = Rank)
  85.    
  86.     write_csv(responses_final_wide, "responses_final.csv")
  87.     break
  88.   }
  89.  
  90.   # --- Βήμα 3: Εξάλειψη ---
  91.   counts_df <- data.frame(ClubID=names(counts), FirstPrefCount=as.integer(counts)) |>
  92.     filter(FirstPrefCount < min_threshold)
  93.  
  94.   if(nrow(counts_df) == 0) {
  95.     # Αυτό δεν θα έπρεπε να συμβεί λόγω του προηγούμενου ελέγχου,
  96.     # αλλά εξασφαλίζει τη συνέχεια αν το all(counts >= min_threshold) δεν πιάσει την περίπτωση.
  97.     cat("\nΤερματισμός: Όλοι οι Όμιλοι άνω του ορίου.\n")
  98.     next
  99.   }
  100.  
  101.   min_count <- min(counts_df$FirstPrefCount)
  102.   elim_candidates <- counts_df |> filter(FirstPrefCount == min_count)
  103.  
  104.   # Λογική Ισοπαλίας: επιλέγουμε αλφαβητικά
  105.   club_to_elim <- sort(elim_candidates$ClubID)[1]
  106.  
  107.   match_idx <- match(club_to_elim, clubs$club_id)
  108.   club_name <- if(!is.na(match_idx)) clubs$club_name[match_idx] else club_to_elim
  109.   cat(sprintf("Εξαλείφεται ο Όμιλος: %s (%s) με %d πρώτες προτιμήσεις.\n",
  110.               club_to_elim, club_name, min_count))
  111.  
  112.   elimination_log <- rbind(elimination_log,
  113.                            data.frame(Round=round,
  114.                                       ClubID=club_to_elim,
  115.                                       ClubName=club_name,
  116.                                       FirstPrefCount=min_count,
  117.                                       stringsAsFactors = FALSE))
  118.  
  119.   # --- Βήμα 4: Μεταφορά Ψήφων (Αναβάθμιση Προτιμήσεων) ---
  120.  
  121.   # 1. Απενεργοποίηση του εξαλειφθέντος Ομίλου
  122.   active_clubs <- setdiff(active_clubs, club_to_elim)
  123.  
  124.   # 2. Ακύρωση του club_to_elim (θέτουμε το Rank του σε NA)
  125.   responses_long_master <- responses_long_master |>
  126.     mutate(Rank = ifelse(ClubID == club_to_elim, NA_integer_, Rank)) |>
  127.     # Αφαιρούμε πλέον τα NA rank, καθώς ο Όμιλος δεν μετράει
  128.     filter(!is.na(Rank))
  129.  
  130.   # 3. Αναβαθμίζουμε τα Ranks για κάθε μαθητή
  131.   responses_long_master <- responses_long_master |>
  132.     group_by(across(all_of(student_col))) |>
  133.     # Αναβαθμίζουμε τα Ranks (1, 3, 4, 5... γίνεται 1, 2, 3, 4...)
  134.     # Επανα-αριθμούμε τις προτιμήσεις με βάση την τρέχουσα σειρά τους
  135.     mutate(Rank = rank(Rank, ties.method = "min")) |>
  136.     ungroup()
  137.  
  138.   # --- Αποθήκευση Ενδιάμεσου Αρχείου (responses_wide) ---
  139.   round_file <- sprintf("%s%d.csv", output_prefix, round)
  140.  
  141.   responses_round_wide <- responses_long_master |>
  142.     pivot_wider(id_cols = all_of(student_col),
  143.                 names_from = ClubID, values_from = Rank) |>
  144.     # Συμπληρώνουμε με NA τους Όμιλους που έχουν ήδη εξαλειφθεί (αν υπάρχουν)
  145.     select(all_of(student_col), all_of(active_clubs))
  146.  
  147.   write_csv(responses_round_wide, round_file)
  148.   cat("Αποθηκεύτηκε ενδιάμεσο αρχείο: ", round_file, "\n")
  149.  
  150.   round <- round + 1L
  151. }
  152.  
  153. if(nrow(elimination_log)>0) write_csv(elimination_log, "elimination_log.csv")
  154. cat("\nΟλοκληρώθηκε η διαδικασία εξάλειψης. Δες το elimination_log.csv.\n")
Advertisement
Add Comment
Please, Sign In to add comment