返回列表 发帖

【练习-059】批处理解实现自动新生分班

出题目的:
    让大家熟练掌握随机数概念和用法
解题要求:
    1、代码简洁、高效、通用并不生成临时文件
    2、请版主级会员暂缓解题,但可跟贴为新人做指导
加分规则:
    本题满分15分,视情况加分
题目如下:
    某学校要新招收400名学生,其中有100名优等生、100名高等生、100名中等生、100名差等生,现在学校校长要求将这400名
学生随机安排到新开的10个班,同时要求每个班有10名优等生、10名高等生、10名中等生、10名差等生,并且要在学生报到的时候
就分好班次,并且他要为两个学生开后门,一个是将教育局局长的儿子分到第3班,一个是将文化局局长的女儿分到第8班。这下可
难坏了招生办的老师,一时都不知道怎么办,正好这时教务处长来了,他马上想到一个好办法,终于招生办解决了校长交给的难题,
受到校长的表扬。现在假设你是教务处长,你能想到什么好办法吗?请注意,我不是要你们写文字,要看你们的代码,请最后将每个
班的学生显示出来(最好是分屏显示)
随题提示:
    1、优等生用A-1至A-100表示,高等生用B-1至B-100表示,中等生用C-1至C-100表示,差等生用D-1至D-100表示
    2、教育局局长的儿子用B-60表示,文化局局长的女儿用C-49表示
    3、班级用X-1至X-10表示
    4、假设学生报到的顺序不是随机的,是按A-D、1-100的顺序来进行,即先按1-00的顺序招收优等生,再按1-100的顺序招收高等
生,依此类推直到招收D-100,所以才要求在报到时就随机分好班

要睡觉了,看来本题确实有难度,先给出本人的参考答案吧,不过大家还是争取不要看答案哦:


@echo off&setlocal enabledelayedexpansion
for %%a in (A B C D) do (
    for /l %%b in (1,1,100) do set ".!random!_%%a-%%b=%%a-%%b"
    for /f "tokens=2 delims==" %%b in ('set .') do (
        if not defined code set "code=123456789a"&set /a n=10
        set /a a=!random!%%n
        for %%c in (!a!) do (
            set "a=!code:~%%c,1!"
            for %%c in (!a!) do (
                set "code=!code:%%c=!"&set "X-%%c=!X-%%c! %%b"&set /a n-=1
                for %%d in (B-3 C-8) do (
                    for /f "tokens=1,2 delims=-" %%e in ("%%d") do (
                        if %%e equ %%a if %%f equ %%c if not defined _%%e%%f set "_%%e%%f=%%b"
                    )
                )
                for %%d in (B-60 C-49) do if "%%d" equ "%%b" set ".%%d=X-%%c"
            )  
        )
    )
    for /f "delims==" %%b in ('set .') do set "%%b="
)
set "X-10=%X-a%"
if "%X-3:B-60=%" equ "%X-3%" set "X-3=!X-3:%_B3%=B-60!"&call,set "!.B-60!=%%!.B-60:B-60=%_B3%!%%"
if "%X-8:C-49=%" equ "%X-8%" set "X-8=!X-8:%_C8%=C-49!"&call,set "!.C-49!=%%!.C-49:C-40=%_C8%!%%"
for /l %%a in (1,1,10) do cls&echo X-%%a班:&echo.&echo !X-%%a:~1!&pause>nulCOPY

-------------------------------------------------------------------------------------------------------------------------------------------
此代码重复随机,不可取,请大家看后面的代码。

[ 本帖最后由 batman 于 2010-6-29 09:22 编辑 ]
***共同提高***

每个班规定40人吗
那两个开后门的是差等生,还是?
那个所谓的办法,能用文字表达一下吗?
技术问题请到论坛发帖求助!

TOP

回复 2楼 的帖子

1、是的,因为题目里面说“同时要求每个班有10名优等生、10名高等生、10名中等生、10名差等生”。
2、B代表高等、C代表中等。
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复 2楼 的帖子

所谓的办法在每个人的心中,呵呵。。。

如觉得有难度,先可不开后门(本来就反对开后门

[ 本帖最后由 batman 于 2010-6-27 20:44 编辑 ]
***共同提高***

TOP

应该不难,但要求简洁。。。只怕有难度。
技术问题请到论坛发帖求助!

TOP

@echo off & setlocal enableDelayedExpansion
for %%c in (A B C D) do (
  set "Max=10"
  for /l %%i in (0 1 9) do (set "ptClass%%i=%%i"& set Cnt%%i=0)
  for /l %%s in (1 1 100) do (
    set /a to_pt=!random! %% !Max!
    set /a "to=ptClass!to_pt!"
    for %%t in (!to!) do (
      set "X-%%t=!X-%%t! %%c-%%s"
      set /a Cnt%%t+=1
      if !Cnt%%t! geq 10 (
        set /a last=Max-1
        set /a tt=ptClass!to_pt!
        set /a ptClass!to_pt!=ptClass!last!
        set /a ptClass!last!=tt
        set /a Max-=1
      )
    )
  )
)
set "X-10=!X-0!"& set "X-0="
for /l %%i in (1 1 10) do set "X-%%i=!X-%%i! "& rem 加入尾部空格防止单数错误替换
echo 开后门之前...
set X-
pause
echo 开后门...
call :backDoor B-60 X-3 11
call :backDoor C-49 X-8 21
echo 开后门之后...
set X-
pause
exit /b
:backDoor 学生编号 班编号 班内目标号 C-49 安排到 X-8, C 起始于 #21
for /l %%i in (1 1 10) do (
  if /i "X-%%i" neq "%2" (
    (echo !X-%%i!|find /i "%1">nul)&&(
      for /f "tokens=%3 delims= " %%t in ("!%2!") do (
        (echo 调换: X-%%i 班的 %1 ^<==^> %2 班的 %%t )
        set "X-%%i=!X-%%i:%1 =%%t !" & rem 带尾部空格防止双数被当成单数替换,
        set "%2=!%2:%%t =%1 !"       & rem 例: B-12 会当作 B-12
      )  
      exit /b
    )
  )
)
exit /bCOPY

[ 本帖最后由 neorobin 于 2010-6-27 21:38 编辑 ]
1

评分人数

    • batman: 思路再打开点,代码确实难以很简洁PB + 10

TOP

开后门还真是有难度,思考中。。。。。
技术问题请到论坛发帖求助!

TOP

回复 7楼 的帖子

我的方法是先全部 平等 对待 安排, 之后再找出相应的 班和学生 调换一下(如果已经安排到了所要的班就免调换了)即可,  前部的代码排除了 特殊性, 可以写得简洁

TOP

开后门也不难,思路打开点,试试交换法,嘿嘿。。。
***共同提高***

TOP

回复 9楼 的帖子

对, 不需要调换学生, 找到所在的班, 直接和想要的班换一下就可以了, 实质上也就是把后门学生所要的班号 换成 所要求的就行了, 比如 B-60 被安排到了 8 班, 那么直接把 8 班看成 3  班, 3 班看成 8 班就行了!

TOP

开窍了,哈哈,是的,任何问题从多个角度上来想,总能找到解决的好办法的。
***共同提高***

TOP

再发换班不换学生的

这里换班号的方法是错误的, 13楼, 14楼 有说明
@echo off & setlocal enableDelayedExpansion
for %%c in (A B C D) do (
  set "Max=10"
  for /l %%i in (0 1 9) do (set "ptClass%%i=%%i"& set Cnt%%i=0)
  for /l %%s in (1 1 100) do (
    set /a to_pt=!random! %% !Max!
    set /a "to=ptClass!to_pt!"
    for %%t in (!to!) do (
      set "X-%%t=!X-%%t! %%c-%%s"
      set /a Cnt%%t+=1
      if !Cnt%%t! geq 10 (
        set /a last=Max-1
        set /a tt=ptClass!to_pt!
        set /a ptClass!to_pt!=ptClass!last!
        set /a ptClass!last!=tt
        set /a Max-=1
      )
    )
  )
)
set "X-10=!X-0!"& set "X-0="
for /l %%i in (1 1 10) do set "X-%%i=!X-%%i! "& rem 加入尾部空格防止单数错误替换
echo 开后门之前...
set X-
pause
echo 开后门...
call :backDoor B-60 X-3
call :backDoor C-49 X-8
echo 开后门之后...
set X-
pause
exit /b
:backDoor 学生编号 班编号 [color=red] 错误后门方法 [/color]
for /l %%i in (1 1 10) do (
  if /i "X-%%i" neq "%2" (
    rem find 后是一个含尾空格的查找串 "%1 ", 避免将1位以上的数字错误处理
    (echo !X-%%i!|find /i "%1 ">nul)&&(
      (echo 调换: %1 所在的 X-%%i 班 ^<==^> %2 班)
      set tt=!X-%%i!& set X-%%i=!%2!& set "%2=!tt!"
      exit /b
    )
  )
)
exit /bCOPY

[ 本帖最后由 neorobin 于 2010-6-27 23:49 编辑 ]

TOP

假设两个后门学生都在一个班呢?
又或者都在3班或8班呢?
1

评分人数

    • batman: 这我真没想到,汗水。。。PB + 5
技术问题请到论坛发帖求助!

TOP

回复 13楼 的帖子

正要说这个, 用换班的方法会造成矛盾,
设换班号之前两个后门生其中一个在 M 班, 要去 P 班
而另一个在 N 班, 要去 Q 班
就存在两次班号调换, M<==>P, N<==>Q
这样, 当 M, N, P, Q 这四个数字中有相同, 但又不是 M=Q且P=N的情况, 就会至少使一个后门生到不了要去的班号.

单单调换学生时, 如果学生不属一个类别, 不会有问题, 如果有相同类别的后门生都要换班, 那么代码须要更复杂的设计
@echo off & setlocal enableDelayedExpansion
for %%a in (A B C D) do (
  for /l %%i in (1001 1 1100) do set "sStu=!sStu!%%a-%%i"
  set "sStu=!sStu:-1=-!"&  set "base=100"
  for /l %%x in (1 1 10) do (
    for /l %%i in (1 1 10) do (
      set /a "start=(!random!%%base)*5"
      for %%s in (!start!) do (
        set "choose=!sStu:~%%s,5!"
        for %%c in (!choose!) do (
          set "X-%%x=!X-%%x! %%c"
          set "sStu=!sStu:%%c=!"
          set /a base-=1
) ) ) ) )
(echo 开后门之前...)&set X-&pause
(echo 开后门...)&call :backDoor B-060 X-3 11&call :backDoor C-049 X-8 21
(echo 开后门之后...)&set X-&pause
exit /b
:backDoor 学生编号 班编号 班内目标号 如: C-049 安排到 X-8, C 起始于 #21
for /l %%i in (1 1 10) do (
  if /i "X-%%i" neq "%2" (
    (echo !X-%%i!|find /i "%1">nul)&&(
      for /f "tokens=%3 delims= " %%t in ("!%2!") do (
        (echo 调换: X-%%i 班的 %1 ^<==^> %2 班的 %%t )
        set "X-%%i=!X-%%i:%1=%%t!"
        set "%2=!%2:%%t=%1!"
      )  
      exit /b
) ) )
exit /bCOPY

[ 本帖最后由 neorobin 于 2010-6-28 00:17 编辑 ]

TOP

为了开这个后门,导致代码又长又多作许多无用功,汗,找不到更好的方法,先凑合着用
思路:
先将400名学生分成4组,再乱序,然后在每班每组按顺序取10个,
并同时记录下后门学生所在班级,再记录下3班一名高等生和8班一名差等生
最后把3班的这名高等生编到b60所在班,把b60强行编到3班
8班也是

:
@echo off&setlocal EnableDelayedExpansion
for %%a in (a b c d) do call :loop %%a
for /l %%a in (1 1 10) do (
   set /a t+=1,w+=10
   for %%i in (a b c d) do (
      for /l %%j in (!t! 1 !w!) do (
         set #%%a=!#%%a! !.%%i%%j!
         set tmp=!.%%i%%j!
         if "!.%%i%%j!"=="b60" set j=%%a
         if %%a equ 3 if "!tmp:~0,1!"=="b" if not "!tmp!"=="b60" set t3=!tmp!
         if "!.%%i%%j!"=="c49" set wen=%%a
         if %%a equ 8 if "!tmp:~0,1!"=="c" if not "!tmp!"=="c49" set t8=!tmp!
       )
    )
    set /a t=w
)
echo 两个后门学生原来所在班 !j!  !wen!&echo;
for %%a in (!j!) do set #%%a=!#%%a:b60=! !t3!
for %%a in (!wen!) do set #%%a=!#%%a:c49=! !t8!
set #3=!#3! b60
set #8=!#8! c49
for /l %%a in (1 1 10) do (
   echo %%a
   echo !#%%a!
   echo;
)
pause&exit
:loop
for /l %%i in (1 1 100) do set .%1%%i=%1%%i
for /l %%i in (1 1 100) do (
    set /a rnd=!random!%%100+1
    for %%j in (!rnd!) do set tmp=!.%1%%j!
    set .%1!rnd!=!.%1%%i!
    set .%1%%i=!tmp!
)
goto :EOFCOPY
技术问题请到论坛发帖求助!

TOP

返回列表