[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
  1. @echo off & setlocal enableDelayedExpansion
  2. for %%c in (A B C D) do (
  3.   set "Max=10"
  4.   for /l %%i in (0 1 9) do (set "ptClass%%i=%%i"& set Cnt%%i=0)
  5.   for /l %%s in (1 1 100) do (
  6.     set /a to_pt=!random! %% !Max!
  7.     set /a "to=ptClass!to_pt!"
  8.     for %%t in (!to!) do (
  9.       set "X-%%t=!X-%%t! %%c-%%s"
  10.       set /a Cnt%%t+=1
  11.       if !Cnt%%t! geq 10 (
  12.         set /a last=Max-1
  13.         set /a tt=ptClass!to_pt!
  14.         set /a ptClass!to_pt!=ptClass!last!
  15.         set /a ptClass!last!=tt
  16.         set /a Max-=1
  17.       )
  18.     )
  19.   )
  20. )
  21. set "X-10=!X-0!"& set "X-0="
  22. for /l %%i in (1 1 10) do set "X-%%i=!X-%%i! "& rem 加入尾部空格防止单数错误替换
  23. echo 开后门之前...
  24. set X-
  25. pause
  26. echo 开后门...
  27. call :backDoor B-60 X-3 11
  28. call :backDoor C-49 X-8 21
  29. echo 开后门之后...
  30. set X-
  31. pause
  32. exit /b
  33. :backDoor 学生编号 班编号 班内目标号 C-49 安排到 X-8, C 起始于 #21
  34. for /l %%i in (1 1 10) do (
  35.   if /i "X-%%i" neq "%2" (
  36.     (echo !X-%%i!|find /i "%1">nul)&&(
  37.       for /f "tokens=%3 delims= " %%t in ("!%2!") do (
  38.         (echo 调换: X-%%i 班的 %1 ^<==^> %2 班的 %%t )
  39.         set "X-%%i=!X-%%i:%1 =%%t !" & rem 带尾部空格防止双数被当成单数替换,
  40.         set "%2=!%2:%%t =%1 !"       & rem 例: B-12 会当作 B-1 与 2
  41.       )  
  42.       exit /b
  43.     )
  44.   )
  45. )
  46. exit /b
复制代码

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

评分人数

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

TOP

回复 7楼 的帖子

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

TOP

回复 9楼 的帖子

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

TOP

再发换班不换学生的

这里换班号的方法是错误的, 13楼, 14楼 有说明
  1. @echo off & setlocal enableDelayedExpansion
  2. for %%c in (A B C D) do (
  3.   set "Max=10"
  4.   for /l %%i in (0 1 9) do (set "ptClass%%i=%%i"& set Cnt%%i=0)
  5.   for /l %%s in (1 1 100) do (
  6.     set /a to_pt=!random! %% !Max!
  7.     set /a "to=ptClass!to_pt!"
  8.     for %%t in (!to!) do (
  9.       set "X-%%t=!X-%%t! %%c-%%s"
  10.       set /a Cnt%%t+=1
  11.       if !Cnt%%t! geq 10 (
  12.         set /a last=Max-1
  13.         set /a tt=ptClass!to_pt!
  14.         set /a ptClass!to_pt!=ptClass!last!
  15.         set /a ptClass!last!=tt
  16.         set /a Max-=1
  17.       )
  18.     )
  19.   )
  20. )
  21. set "X-10=!X-0!"& set "X-0="
  22. for /l %%i in (1 1 10) do set "X-%%i=!X-%%i! "& rem 加入尾部空格防止单数错误替换
  23. echo 开后门之前...
  24. set X-
  25. pause
  26. echo 开后门...
  27. call :backDoor B-60 X-3
  28. call :backDoor C-49 X-8
  29. echo 开后门之后...
  30. set X-
  31. pause
  32. exit /b
  33. :backDoor 学生编号 班编号 [color=red] 错误后门方法 [/color]
  34. for /l %%i in (1 1 10) do (
  35.   if /i "X-%%i" neq "%2" (
  36.     rem find 后是一个含尾空格的查找串 "%1 ", 避免将1位以上的数字错误处理
  37.     (echo !X-%%i!|find /i "%1 ">nul)&&(
  38.       (echo 调换: %1 所在的 X-%%i 班 ^<==^> %2 班)
  39.       set tt=!X-%%i!& set X-%%i=!%2!& set "%2=!tt!"
  40.       exit /b
  41.     )
  42.   )
  43. )
  44. exit /b
复制代码

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

TOP

回复 13楼 的帖子

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

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

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

TOP

我先后给出的代码分别采用了两种思路:

第 1 种. 在每一类学生里, 每 100 个学生逐个排进随机的班号里, 须对班号排满 10 个与否计数判断处理
第 2 种. 在每一类学生里, 每 100 个学生先行编进线性表(字符串实现),
然后, 10 个班依次在表里随机取出 10 个学生,
每取出一个学生后, 随机索引的上限逐次减 1, 线性表中对应的学生编号也删除掉
直到安排好所有 400 名学生进入 全部 10 个班

后门: 找出后门生所在的班, 再与后门生要去的目标班里的同类的第一个学生调换
因为两个后门生, 分属不同的 B 和 C 类, 所以代码上不用考虑两次(最多可能)调换之间的矛盾.

TOP

回复 18楼 的帖子

我的解法中 c49 不可能是 3 班的第一个学生, C 类的学生只能是第 21--30 个的范围之内, B 类只会和其他班的 B 类学生调换, 而且不同类别的学生 在一个班内部的编号不可能相同:
A: 1--10
B: 11-20
C: 21-30
D: 31-40
只要题目不要求有多于一个的同类的后门生都要安排, 我的代码不须进一步复杂

TOP

回复 15楼 的帖子

以下为 cmd 输出重定向到文件的方法 摘取 随风 15 楼代码的一次输出
3班
a72 a13 a8 a95 a25 a91 a29 a37 a92 a54 b25 b70 b3 b55 b32 b47 b28 b52  b99 c50 c72 c40 c100 c57 c54 c95 c96 c38 c42 d97 d34 d57 d92 d22 d63 d61 d16 d37 d24 b99 b60

5班
a52 a36 a75 a70 a99 a68 a33 a50 a84 a24 b35 b100 b7 b46 b23 b14 b69 b16 b59 b40  c37 c69 c76 c29 c93 c94 c23 c67 c70 d42 d20 d80 d49 d53 d7 d21 d54 d75 d81 c27

8班
a90 a15 a9 a74 a39 a7 a57 a23 a78 a67 b8 b31 b48 b68 b37 b27 b97 b80 b34 b20 c5 c7 c75 c26 c56 c82 c98 c62 c13 c27 d84 d27 d3 d98 d64 d30 d82 d87 d74 d26 c49

发现 b 类和 c 类学生总会多出一个, 有可能在同一个班, 也可能在不同的班:
此次输出中, 3 班有 2 个 b99, 而 5 班和 8 班各有一个 c27

用 notepad++ 查找输出文件中的 b 和 c 计数, 总是得到 101 个结果.

TOP

再发一个

:: 生成 1--100 的随机数序列, 删除掉 后门生编号, 平分进 10 个班,
:: 但 X-10 班会少分两个学生.
:: 将 3 班的第 1 个 B 类学生剪切给 10 班, 再把 B-060 加入 3 班
:: 将 8 班的第 1 个 C 类学生剪切给 10 班, 再把 C-049 加入 8 班
  1. @echo off&setlocal enableDelayedExpansion&mode con cols=126
  2. for /l %%i in (1001 1 1100) do set "sStu=!sStu!S-%%i"
  3. set "sStu=!sStu:-1=-!"
  4. for %%a in (A B C D) do (
  5.   set sS=!sStu:S=%%a!& set sS=!sS:B-060=!& set "sS=!sS:C-049=!"
  6.   set "UP=100" & if %%a geq B if %%a leq C set "UP=99"
  7.   for /l %%x in (1 1 10) do (for /l %%i in (1 1 10) do (
  8.       if !UP! gtr 0 ( set /a "start=!random!%%UP*5"
  9.         for %%s in (!start!) do (for %%c in (!sS:~%%s^,5!) do (
  10.           set "X-%%x=!X-%%x! %%c"& set "sS=!sS:%%c=!"& set /a UP-=1
  11. ) ) ) ) ) )
  12. echo 开后门之前:&set X-& set "X-10=!X-10!!X-3:~60,6!!X-8:~120,6!"
  13. set X-3=!X-3:~0,60! B-060!X-3:~66!& set "X-8=!X-8:~0,120! C-049!X-8:~126!"
  14. echo 开后门之后:&set X-&pause
复制代码

TOP

嘿嘿, 这次的 word 字数统计比 batman 22楼的少

  1. @echo off&setlocal enabledelayedexpansion
  2. for %%t in (A B C D) do (
  3.         for /l %%i in (1001 1 1100) do set "#%%t!random:~-2!%%i=%%i"
  4.         for /f "tokens=2 delims==" %%n in ('set #%%t') do set "U=!U!%%t-%%n "
  5.         set U=!U:-1=-!
  6.         set "U=!U:B-060 =!      "& set "U=!U:C-049 =!      "
  7.         for /l %%s in (0 60 540) do ( set /a V=%%s/60+1
  8.                 for %%c in (x-!V!) do set "%%c=!%%c!!U:~%%s,60!"
  9.         )
  10.         set "U="
  11. )
  12. set "X-10=!X-10:      =!!X-3:~60,6!!X-8:~120,6!"
  13. set X-3=!X-3:~0,60!B-060 !X-3:~66!& set "X-8=!X-8:~0,120!C-049 !X-8:~126!"
  14. set X&pause
复制代码
这次 100 个学生表的次序 采用了 set 输出排序, set 输出一系列变量是会按变量名的次序来排列的, 但事先安排 100 个变量名仅前部相同, 变量值却是 1--100 中的任意一个, 且没有变量值相同的情况, 而且 1--100 每个值都是安排到了一个随机生成的变量名的变量, 再用 set 输出, 输出的变量名是按正常次序来的, 但变量的值却成了无规则的乱序了, 部分示例如下:
#A0074=74
#A0134=34
#A0270=70
#A0352=52
#A0381=81
#A0497=97
#A0550=50
#A0553=53
#A063=3
#A0658=58

TOP

才发现我 33 楼的乱序方法居然是和 batman 22 楼一样的, 有巧合但也有特色: 做完代码才发现 33 楼居然没有用一个 if.

batman 好像认为 set 排乱序不太好, 我可真想不到还有什么更简洁的方式.

TOP

回复 36楼 的帖子

听你说正在学习编程规范, 一点好奇: 难道你不是计算机专业的(当然你可以不答我)
你这帖的代码, 我没大细看, 但 发现 echo off 和 setlocal 没用 & 放在同一行了,
set /a 后面的运算符也都前后都空出一个空格了.
这点上我提一个题外话, 至少我在做一些代码时自己犯了一个狭念:
把代码做浮华性的 "简化", 甚时在变量名上做不必要的简化, 略到只用一个字母.

什么样的代码才是好的? 正确, 高效, 易读, 而所谓 "简洁", 应是代码具备了实质上内在的品质而自然表现出的外在品质.

TOP

返回列表