基于 python 实现的中小学随机化分班算法(思路、实现、代码以及打包好的可执行文件)

本文主要是介绍基于 python 实现的中小学随机化分班算法(思路、实现、代码以及打包好的可执行文件),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 0. 请勿转作商用!有问题可以添加QQ470585226
    • 1. 代码运行情况
    • 2. 需要提供的excel格式
    • 3. 最终结果
    • 4. 算法实现
    • 5. 代码
    • 6. 下载地址

0. 请勿转作商用!有问题可以添加QQ470585226

1. 代码运行情况

    *****************************************************代码会自动分配所有学生到每个班,并自动生成每个班级的表格1. 每个班级男女生数量尽可能平均2. 每个班级每个分段人数尽可能相等3. 每个班级之间的所有科目平均分尽可能相近4. 允许对每个人预设班级* 分班采用随机算法,每次运行会尝试 20 次计算挑选最小值,多次运算代码可能会得到不同的结果*****************************************************需要提供的excel表格内的列大致分为三段:(姓名 性别)         (语文 数学 英语 科学 总分)    (预设班级)1. 姓名、性别等信息 ;      2. 成绩 ;          3. 预设班级*****************************************************1. 姓名、性别等信息: 可以添加 '姓名' '学号' 等信息,这些信息不会影响结果信息的顺序没有影响,但是此段内容最后一列必须是性别'性别' 的值只能是 '男' 或者 '女'2. 成绩:顺序无关,但是必须以总分结尾3. 预设班级: 可选是否存在,需要预设分分班的人后面用数字标明需要分班到哪个班级即可注意此列需要使用阿拉伯数字即 1,2,3,4...且预设班级的数值应该是 [1,分班数量] 区间内的数字不可以超过分班数量 *****************************************************举例1:姓名 性别 语文 数学 英语 科学 总分 预设班级举例2:学号 姓名 性别 数学 语文 英语 科学 总分 预设班级举例3:姓名 学号 性别 语文 数学 科学 英语 总分*****************************************************此项目开源仅仅是为了交流学习,请自觉遵守法律以及道德规范,请勿将其用于商业用途!有任何问题可以联系QQ470585226---by jnxxhzz杭州二中白马湖学校

2. 需要提供的excel格式

在这里插入图片描述
这里 列 A , B A,B A,B 为第一部分内容,列 C D E F G CDEFG CDEFG 为第二部分内容,列 H H H 为可选内容

  1. 其中第一部分内容必须以 "性别"列 结尾,前面的内容可以随意增加,顺序无关
  2. 其中第二部分内容必须跟在 “性别” 列之后,全部为每门课的成绩分数,以 "总分"列结尾,其中课程数量可以随意增加,顺序无关
  3. 其中第三部分内容为可选内容,若需要预设班级则添加此列,在需要预设班级的人后面标上班级即可,注意若需要分为 6 6 6 个班,预设班级的数字范围应该是 1 ∼ 6 1\sim6 16

3. 最终结果

最终会在代码目录下生成 F i n a l l _ p l a n . x l s Finall\_plan.xls Finall_plan.xls 文件,文件内即为最终方案,每个班级的名单以及全校的总情况
在这里插入图片描述
在这里插入图片描述

4. 算法实现

代码整体采用的是随机化算法
主要步骤分 5 5 5

  1. 将所有人按分数排序

  2. S S S 型分班将所有人分成对应需求的 n e e d _ c l a s s need\_class need_class 个班级(即按照 1 , 2 , 3 , 4 , 5 , 6 , 6 , 5 , 4 , 3 , 2 , 1..... 1,2,3,4,5,6,6,5,4,3,2,1..... 1,2,3,4,5,6,6,5,4,3,2,1..... 的顺序分班)。同时将所有人打上分段标记(即 l e v e l level level 也就是排名前多少人分为一段,此处默认选择 n e e d _ c l a s s need\_class need_class 超过 30 30 30 的最小倍数)

  3. 调整预设班级,若有人存在预设班级而本人不在对应班级,则跟对应班级同 l e v e l level level 的人交换,后序所有交换中不允许交换有预设班级的人

  4. 调整每个班级的男女数量(四种情况分别配平,交换男女时保证只能交换同分数段的人)

    1. 男女都超过高平均值的两个班级互换
    2. 女生超过高平均值的班级和男生超过低平均值的班级互换 (男生班级人数会变成高平均值)
    3. 男生超过高平均值的班级和女超过低平均值的班级互换 (女班级人数会变成高平均值)
    4. 女生低于低平均值的班级和女生等于高平均值班级互换 (男生班级人数会变成低平均值)
  5. 随机调整,每次随机挑选两个班,分别枚举两个班的人,若两人 p 1 , p 2 p1,p2 p1,p2 满足条件:

    1. 性别相同
    2. l e v e l level level 相同
    3. 没有预设班级
    4. 随机在 c h e c k 1 check1 check1 c h e c k 2 check2 check2 中挑选一种,若能满足则交换
      c h e c k 1 : check1: check1: 按两个班级的每门课平均分差值是否变小决定是否交换
      c h e c k 2 : check2: check2: 按总极差(即所有班级中同一门课的最高平均分减最低平均分之和)是否变小决定是否交换

    以上交换共执行 1000 1000 1000 次,多次测试发现一般最多只能交换几十次,所以一千次一定能使得误差无法再变小,但是因为算法完全随机,所以在任何一次步骤不同都会导致不同的结果,所以考虑随机调整 20 20 20 次最终选择误差最小的那一次作为答案,当然 20 20 20 次可以根据计算机运行速度以及所需求效率来进行调整,一般一两秒就可以产生结果

5. 代码

  1. 将所有人按分数排序
	r = Read_Ex()all_students = r.read_excel()all_students = sorted(all_students, key=itemgetter('总分'), reverse = True)need_class = int(input("请输入分班数:"))
  1. S S S 型分班将所有人分成对应需求的 n e e d _ c l a s s need\_class need_class 个班级(即按照 1 , 2 , 3 , 4 , 5 , 6 , 6 , 5 , 4 , 3 , 2 , 1..... 1,2,3,4,5,6,6,5,4,3,2,1..... 1,2,3,4,5,6,6,5,4,3,2,1..... 的顺序分班)。同时将所有人打上分段标记(即 l e v e l level level 也就是排名前多少人分为一段,此处默认选择 n e e d _ c l a s s need\_class need_class 超过 30 30 30 的最小倍数)
# 初始化每个班级finall_class = []every_class = []for i in range(need_class):temp_map = {'男':0,'女':0}temp_list = []finall_class.append(temp_list)every_class.append(temp_map)# 计算分段人数every_level = (int)(20 / need_class) * need_classif every_level < 20:every_level = every_level + need_class# 蛇形分班 & 标记分段now_class_number = 0flag = 1level_numebr = 1now_level_number = 0now_every_level = every_levelboys_number = 0   # 记录男生数量girls_number = 0  # 记录女生数量every_level_two = 0for i in range(len(all_students)):# 记录男女生数量if all_students[i]['性别'] == '男':boys_number = boys_number + 1every_class[now_class_number]['男'] = every_class[now_class_number]['男'] + 1else:girls_number = girls_number + 1every_class[now_class_number]['女'] = every_class[now_class_number]['女'] + 1# 标记分段all_students[i]['分段'] = level_numebrnow_level_number = now_level_number + 1if now_level_number >= now_every_level:if i + 1< len(all_students) and all_students[i + 1]['总分'] == all_students[i]['总分']:now_every_level += need_classelse:now_level_number = 0level_numebr = level_numebr + 1every_level_two = every_level_two + 1if every_level_two >= 2:now_every_level = now_every_level + every_levelevery_level_two = 0# 分班finall_class[now_class_number].append(all_students[i]);now_class_number = now_class_number + flagif now_class_number >= need_class or now_class_number < 0:now_class_number = now_class_number - flagflag = -flag
  1. 调整预设班级,若有人存在预设班级而本人不在对应班级,则跟对应班级同 l e v e l level level 的人交换,后序所有交换中不允许交换有预设班级的人
     # 调整预设班级if book_key.count('预设班级') != 0:for i in range(need_class):for p1 in range(len(finall_class[i])):go_class = finall_class[i][p1]['预设班级']if go_class != '' and i != int(go_class) - 1:go_class = int(go_class) - 1for p2 in range(len(finall_class[go_class])):if finall_class[i][p1]['性别'] == finall_class[go_class][p2]['性别']:finall_class[i][p1], finall_class[go_class][p2] = finall_class[go_class][p2], finall_class[i][p1]break
  1. 调整每个班级的男女数量(四种情况分别配平,交换男女时保证只能交换同分数段的人)
def change_sex():# print(every_boys_number1," ", every_girls_number1)# print(every_boys_number2," ", every_girls_number2)# 对男女超过平均值的班级配平男女# 1. 男女都超过高平均值的两个班级互换for boys_id in range(need_class):while every_class[boys_id]['男'] > every_boys_number2:once_flag = 0for girls_id in range(need_class):if boys_id != girls_id and every_class[girls_id]['女'] > every_girls_number2:# 在 boys_id 班和 girls_id 班中寻找 分段 相同的男女生交换for boy in range(len(finall_class[boys_id])):if finall_class[boys_id][boy]['性别'] == '男' \and ((book_key.count('预设班级') != 0 and finall_class[boys_id][boy]['预设班级'] == '') or book_key.count('预设班级') == 0):for girl in range(len(finall_class[girls_id])):if finall_class[girls_id][girl]['性别'] == '女' \and ((book_key.count('预设班级') != 0 and finall_class[girls_id][girl]['预设班级'] == '') or book_key.count('预设班级') == 0) \and finall_class[boys_id][boy]['分段'] ==  finall_class[girls_id][girl]['分段']:finall_class[boys_id][boy], finall_class[girls_id][girl] = finall_class[girls_id][girl],finall_class[boys_id][boy]every_class[boys_id]['男'] = every_class[boys_id]['男'] - 1every_class[boys_id]['女'] = every_class[boys_id]['女'] + 1every_class[girls_id]['男'] = every_class[girls_id]['男'] + 1every_class[girls_id]['女'] = every_class[girls_id]['女'] - 1once_flag = 1;breakif once_flag == 1:breakif once_flag == 1:breakif once_flag == 0:break# 2. 女生超过高平均值的班级和男生超过低平均值的班级互换 (男生班级人数会变成高平均值)for girls_id in range(need_class):while every_class[girls_id]['女'] > every_girls_number2:once_flag = 0for boys_id in range(need_class):if boys_id != girls_id and every_class[boys_id]['男'] > every_boys_number1:# 在 boys_id 班和 girls_id 班中寻找 分段 相同的男女生交换for boy in range(len(finall_class[boys_id])):if finall_class[boys_id][boy]['性别'] == '男'\and ((book_key.count('预设班级') != 0 and finall_class[boys_id][boy]['预设班级'] == '') or book_key.count('预设班级') == 0):for girl in range(len(finall_class[girls_id])):if finall_class[girls_id][girl]['性别'] == '女' \and ((book_key.count('预设班级') != 0 and finall_class[girls_id][girl]['预设班级'] == '') or book_key.count('预设班级') == 0) \and finall_class[boys_id][boy]['分段'] ==  finall_class[girls_id][girl]['分段']:finall_class[boys_id][boy], finall_class[girls_id][girl] = finall_class[girls_id][girl],finall_class[boys_id][boy]every_class[boys_id]['男'] = every_class[boys_id]['男'] - 1every_class[boys_id]['女'] = every_class[boys_id]['女'] + 1every_class[girls_id]['男'] = every_class[girls_id]['男'] + 1every_class[girls_id]['女'] = every_class[girls_id]['女'] - 1once_flag = 1;breakif once_flag == 1:breakif once_flag == 1:breakif once_flag == 0:break# 3. 男生超过高平均值的班级和女超过低平均值的班级互换 (女班级人数会变成高平均值)for boys_id in range(need_class):while every_class[boys_id]['男'] > every_boys_number2:once_flag = 0for girls_id in range(need_class):if boys_id != girls_id and every_class[girls_id]['女'] > every_girls_number1:# 在 boys_id 班和 girls_id 班中寻找 分段 相同的男女生交换for boy in range(len(finall_class[boys_id])):if finall_class[boys_id][boy]['性别'] == '男'\and ((book_key.count('预设班级') != 0 and finall_class[boys_id][boy]['预设班级'] == '') or book_key.count('预设班级') == 0):for girl in range(len(finall_class[girls_id])):if finall_class[girls_id][girl]['性别'] == '女' \and ((book_key.count('预设班级') != 0 and finall_class[girls_id][girl]['预设班级'] == '') or book_key.count('预设班级') == 0) \and finall_class[boys_id][boy]['分段'] ==  finall_class[girls_id][girl]['分段']:finall_class[boys_id][boy], finall_class[girls_id][girl] = finall_class[girls_id][girl],finall_class[boys_id][boy]every_class[boys_id]['男'] = every_class[boys_id]['男'] - 1every_class[boys_id]['女'] = every_class[boys_id]['女'] + 1every_class[girls_id]['男'] = every_class[girls_id]['男'] + 1every_class[girls_id]['女'] = every_class[girls_id]['女'] - 1once_flag = 1;breakif once_flag == 1:breakif once_flag == 1:breakif once_flag == 0:break      # 4. 女生低于低平均值的班级和女生等于高平均值班级互换 (男生班级人数会变成低平均值)for girls_id in range(need_class):while every_class[girls_id]['女'] < every_girls_number1 and every_class[girls_id]['男'] > every_boys_number1:once_flag = 0for boys_id in range(need_class):if boys_id != girls_id and every_class[boys_id]['男'] < every_boys_number2 and every_class[boys_id]['女'] > every_girls_number1:# 在 boys_id 班和 girls_id 班中寻找 分段 相同的男女生交换for boy in range(len(finall_class[girls_id])):if finall_class[girls_id][boy]['性别'] == '男'\and ((book_key.count('预设班级') != 0 and finall_class[girls_id][boy]['预设班级'] == '') or book_key.count('预设班级') == 0):for girl in range(len(finall_class[boys_id])):if finall_class[boys_id][girl]['性别'] == '女' \and ((book_key.count('预设班级') != 0 and finall_class[boys_id][girl]['预设班级'] == '') or book_key.count('预设班级') == 0) \and finall_class[boys_id][girl]['分段'] ==  finall_class[girls_id][boy]['分段']:finall_class[boys_id][girl], finall_class[girls_id][boy] = finall_class[girls_id][boy],finall_class[boys_id][girl]every_class[boys_id]['男'] = every_class[boys_id]['男'] + 1every_class[boys_id]['女'] = every_class[boys_id]['女'] - 1every_class[girls_id]['男'] = every_class[girls_id]['男'] - 1every_class[girls_id]['女'] = every_class[girls_id]['女'] + 1once_flag = 1;breakif once_flag == 1:breakif once_flag == 1:breakif once_flag == 0:break
  1. 随机调整 , c h e c k 1 check1 check1 c h e c k 2 check2 check2 的实现
# 按两个班级的每门课平均分差值是否变小决定是否交换
def check1(max_class_id, p1, min_class_id, p2):all_range1 = 0for subject in score_key:all_range1 = all_range1 + abs(every_class[max_class_id][subject] - every_class[min_class_id][subject])all_range2 = 0for subject in score_key:all_subject = '总分' + subjecttemp1_ave = every_class[max_class_id][all_subject] - finall_class[max_class_id][p1][subject] + finall_class[min_class_id][p2][subject]temp1_ave = temp1_ave / len(finall_class[max_class_id])temp2_ave = every_class[min_class_id][all_subject] - finall_class[min_class_id][p2][subject] + finall_class[max_class_id][p1][subject]temp2_ave = temp2_ave / len(finall_class[min_class_id])all_range2 = all_range2 + abs(temp2_ave - temp1_ave)# print(all_range1, all_range2)if all_range2 < all_range1:return Trueelse:return False# 按总极差变小决定是否交换
def check2(max_class_id, p1, min_class_id, p2):all_range = 0all_range1 = 0for subject in score_key:all_range1 = all_range1 + abs(every_class[max_class_id][subject] - every_class[min_class_id][subject])all_range2 = 0for subject in score_key:all_subject = '总分' + subjecttemp1_ave = every_class[max_class_id][all_subject] - finall_class[max_class_id][p1][subject] + finall_class[min_class_id][p2][subject]temp1_ave = temp1_ave / len(finall_class[max_class_id])temp2_ave = every_class[min_class_id][all_subject] - finall_class[min_class_id][p2][subject] + finall_class[max_class_id][p1][subject]temp2_ave = temp2_ave / len(finall_class[min_class_id])if temp1_ave > temp2_ave:temp1_ave, temp2_ave = temp2_ave, temp1_avemax_score = temp2_avemin_score = temp1_avefor i in range(need_class):if i != max_class_id and i != min_class_id:if max_score < every_class[i][subject]:max_score = every_class[i][subject]if min_score > every_class[i][subject]:min_score = every_class[i][subject]all_range = all_range + max_score - min_score# print(all_range1, all_range2)return all_rangedef change_people(max_class_id, min_class_id, subject):global finall_all_rangefor p1 in range(len(finall_class[max_class_id])):# 在高分班级中选出高于该科目平均分的人 finall_class[max_class_id][p1]if finall_class[max_class_id][p1][subject] > every_class[max_class_id][subject]:for p2 in range(len(finall_class[min_class_id])):# 预设班级的人不允许交换if (book_key.count('预设班级') != 0 and finall_class[max_class_id][p1]['预设班级'] == '' and finall_class[min_class_id][p2]['预设班级'] == '') \or book_key.count('预设班级') == 0:# 在低分班级中选出低于该科目平均分的人 finall_class[min_class_id][p2]if finall_class[max_class_id][p1]['性别'] == finall_class[min_class_id][p2]['性别'] \and finall_class[max_class_id][p1]['分段'] == finall_class[min_class_id][p2]['分段'] \and finall_class[min_class_id][p2][subject] < every_class[min_class_id][subject]:# 计算交换后总极差choice_check = int(random.random() * 2)checkok = Falseif choice_check == 1:checkok = check1(max_class_id, p1, min_class_id, p2)else:temp_all_range = check2(max_class_id, p1, min_class_id, p2)if temp_all_range < finall_all_range:checkok = True# print(temp_range, finall_all_range)# 若交换后极差变变小则交换if checkok == True:finall_class[max_class_id][p1], finall_class[min_class_id][p2] = finall_class[min_class_id][p2], finall_class[max_class_id][p1]finall_all_range = cal_ave()

6. 下载地址

当然也可以加本人好友 QQ470585226

https://download.csdn.net/download/jnxxhzz/12853196

这篇关于基于 python 实现的中小学随机化分班算法(思路、实现、代码以及打包好的可执行文件)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/803945

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

springboot3打包成war包,用tomcat8启动

1、在pom中,将打包类型改为war <packaging>war</packaging> 2、pom中排除SpringBoot内置的Tomcat容器并添加Tomcat依赖,用于编译和测试,         *依赖时一定设置 scope 为 provided (相当于 tomcat 依赖只在本地运行和测试的时候有效,         打包的时候会排除这个依赖)<scope>provided