标题: 【练习-015】批处理随机取值练习 [打印本页]
作者: batman 时间: 2008-8-25 09:39 标题: 【练习-015】批处理随机取值练习
出题目的:
掌握利用random进行随机取值技巧
解题要求:
代码通用、高效
尽量简洁
尽量不生成临时文件
加分规则:
1 思路独特基准分5分
2 代码高效、通用基准分4分
3 技巧高超基准分3分
4 代码简洁基准分2分
5 完美代码加分15分
题目如下:
已知有1-26与a-z的一一对应,如1对应a 10对应j 26对应z,要求用批处理
从1-26 a-z这52个值中(全视为值)随机抽取10个互不相同的值并显示出来,
注意如同1和a 24和x 26和z这样的取值均视为相同不合要求。
解题限制:
暂无限制。
------------------------------------------------------------------------------------------------
目前的最佳答案见:16楼本人的解
[ 本帖最后由 batman 于 2008-8-30 13:10 编辑 ]
作者: wangwei4106 时间: 2008-8-25 09:46
呵呵
你昨天不是做好了吗?
我这还有你写的代码。
作者: 523066680 时间: 2008-8-25 10:28
这是题目 给大家锻炼的。并不是有了一种方法 就不用做题了
作者: more 时间: 2008-8-25 13:04
哈哈,恭喜if exist成为技术组成员了!!!
废话就不多说了,不知是不是这样?
- @echo off
- Setlocal Enabledelayedexpansion
- set "var1=a b c d e f g h i j k l m n o p q r s t u v w x y z"
- for /l %%a in (1 1 26) do (set "var2=!var2!%%a ")
- for %%a in (%var1%) do (set /a "nn+=1"&set "!nn!=%%a"&set "%%a=!nn!")
- echo %var1%&echo %var2%&echo.
- :lp
- set /a "bt=%random%%%26+1","aa=%random%%%2+1"
- for /f "tokens=%bt%" %%a in ("!var%aa%!") do (
- if defined .%%a goto :lp
- if defined .!%%a! goto :lp
- set "ech=!ech! %%a"
- set ".%%a=ok"&set ".!%%a!=ok"
- )
- set /a mm+=1
- if %mm% lss 10 goto :lp
- echo %ech%
- for %%a in (%var1%) do (set ".%%a="&set ".!%%a!=")
- set "mm=0"&set "ech="
- pause>nul&goto :lp
复制代码
作者: batman 时间: 2008-8-25 14:11
楼上的代码写得复杂且效率低,但答案还是对的,加分鼓励。
作者: pusofalse 时间: 2008-8-25 14:26
- @echo off&setlocal enabledelayedexpansion
- for %%i in (a b c d e f g h i j k l n m o p q r s t u v w x y z) do set "letter=!letter! %%i"
- for /l %%a in (1 1 26) do set "num=!num! %%a"
- :loop
- set/a n=%random%%%26+1
- if defined .%n% goto loop
- set .%n%=a
- if defined a (set var=%letter%) else set var=%num%
- for /f "tokens=%n%" %%a in ("%var%") do set/p=%%a <nul
- if not defined a (set a=a) else set "a="
- set/a m+=1
- if %m% neq 10 goto loop
- pause>nul
复制代码
等看BATMAN兄的代码。
[ 本帖最后由 pusofalse 于 2008-8-25 14:34 编辑 ]
作者: batman 时间: 2008-8-25 15:02
&&pusofalse版主代码已经比较完美了,就是在效率上还存在一点小问题,其实对于这种
随机取值的问题在取值基数和取值个数差值较大时(如从1-100中随机取10个不同的数)
使用if判断返回还是可以的,但一旦取值基数和取值个数差值小甚至为0时(如从1-100中
随机取100个不同的数)这种方法就解决不了问题了,所以对于此类问题个人建议使用乱序
来进行处理,下面就以从1-100中随机取100个不同的数为例给出代码:- @echo off&setlocal enabledelayedexpansion
- for /l %%i in (1,1,100) do set "_!random!!random!!random!!random!=%%i"
- for /f "tokens=2 delims==" %%i in ('set _') do set /p=%%i <nul
- pause>nul
复制代码
作者: more 时间: 2008-8-25 15:08
将4楼及6楼的代码改一下,貌似4楼的效率要比6楼的高些喔.
必须要承认的是6楼的想法比我的好多了,呵呵...
但是用时却比我的多,不知为何...
4楼:- @echo off
- Setlocal Enabledelayedexpansion
- set "var1=a b c d e f g h i j k l m n o p q r s t u v w x y z"
- for /l %%a in (1 1 26) do (set "var2=!var2!%%a ")
- for %%a in (%var1%) do (set /a "nn+=1"&set "!nn!=%%a"&set "%%a=!nn!")
- Rem echo %var1%&echo %var2%&echo.
- :lp1
- echo %time%
- :lp
- set /a "bt=%random%%%26+1","aa=%random%%%2+1"
- for /f "tokens=%bt%" %%a in ("!var%aa%!") do (
- if defined .%%a goto :lp
- if defined .!%%a! goto :lp
- set "ech=!ech! %%a"
- set ".%%a=ok"&set ".!%%a!=ok"
- )
- set /a mm+=1
- if %mm% lss 10 goto :lp
- for %%a in (%var1%) do (set ".%%a="&set ".!%%a!=")
- set "mm=0"
- echo %ech%&echo %time%
- set "ech="
- pause>nul&cls&goto :lp1
复制代码
6楼:- @echo off&setlocal enabledelayedexpansion
- for %%i in (a b c d e f g h i j k l n m o p q r s t u v w x y z) do set "letter=!letter! %%i"
- for /l %%a in (1 1 26) do set "num=!num! %%a"
- :lp
- echo %time%
- :loop
- set/a n=%random%%%26+1
- if defined .%n% goto loop
- set .%n%=a
- if defined a (set var=%letter%) else set var=%num%
- for /f "tokens=%n%" %%a in ("%var%") do set "wow=!wow! %%a"
- if not defined a (set a=a) else set "a="
- set/a m+=1
- if %m% neq 10 goto loop
- for /l %%a in (1 1 26) do (set ".%%a=")
- set "m=0"
- echo %wow%&echo %time%
- set "wow="
- pause>nul&cls&goto :lp
复制代码
作者: pusofalse 时间: 2008-8-25 15:33
兄的学习态度太好了。
测试了一下,兄的代码平均间隔在0.02秒之内,我的代码差不多是0.03s。
的确慢了,可能是用了if defined 的缘故
[ 本帖最后由 pusofalse 于 2008-8-25 15:34 编辑 ]
作者: 523066680 时间: 2008-8-25 15:34
各位也都发表啦,我的也放出来啦 偶的还是原来的样子- @echo off&setlocal enabledelayedexpansion
- set /a a=0,act=0
- for %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
- set /a a+=1
- set n!a!=%%a)
- :act
- set /a act+=1
- :act-1
- set /a n=%random%%%27
- if %n% equ 0 set n=1
- if not defined _%n% (
- if %random:~-1% lss 5 (set number%act%=%n%) else (set number%act%=!n%n%!)
- set _%n%=exist
- ) else (goto :act-1)
- echo !number%act%!
- if %act% lss 10 goto :act
- pause
复制代码
再小小修改代码,测试获得字母Z的频数,用来测试前面的代码随机性是否良好- @echo off&setlocal enabledelayedexpansion
- set /a a=0,act=0
- for %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
- set /a a+=1
- set n!a!=%%a)
- set test=0
- :act
- set /a act+=1
- set /a n=%random%%%27
- if %n% equ 0 set n=1
- if %random:~-1% lss 5 (set number%act%=%n%) else (set number%act%=!n%n%!)
- if !number%act%! equ z (set /a test+=1)
- if %act% lss 520 goto :act
- echo,520次 有%test%次出现z
- pause
复制代码
----------------
本楼第一段代码出现概率不平衡问题,请参照11楼和13楼的说法
[ 本帖最后由 523066680 于 2008-8-25 20:58 编辑 ]
作者: more 时间: 2008-8-25 15:44
其实10楼的这部分代码可以这样写的- set /a n=%random%%%27
- if %n% equ 0 set n=1
复制代码
复制代码
作者: batman 时间: 2008-8-25 16:10
原帖由 523066680 于 2008-8-25 15:34 发表
各位也都发表啦,我的也放出来啦 偶的还是原来的样子@echo off&setlocal enabledelayedexpansion
set /a a=0,act=0
for %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
set /a a+=1
set ...
必须要指出你的问题了:
代码书写极不规范,基本忽略了代码的可阅读性和美观性,在充分发挥兄弟的特长的基础上还请在这方面多下点功夫。。。
作者: itrui 时间: 2008-8-25 17:53
原帖由 more 于 2008-8-25 15:44 发表
其实10楼的这部分代码可以这样写的set /a n=%random%%%27
if %n% equ 0 set n=1set /a n=%random%%%26+1
我觉得不是可以那样写,而是应该那样写,否则出现1的概率比其他数都大了1倍。随机应该要求概率一样。
作者: 523066680 时间: 2008-8-25 20:55
原帖由 itrui 于 2008-8-25 17:53 发表
我觉得不是可以那样写,而是应该那样写,否则出现1的概率比其他数都大了1倍。随机应该要求概率一样。
啊 这位真够细心啊!谢谢各位的指教!我会好好努力的!
作者: pusofalse 时间: 2008-8-25 22:14
你说的,随机的概率应该相等。
那么你写为if %n% equ 0 set n=1
出现1的概率也会比其他数多一倍。
我觉得没有绝对的概率相等,底数的概率总会多于其他数。
作者: batman 时间: 2008-8-26 12:09 标题: 下面给出本人的解:
- @echo off&setlocal enabledelayedexpansion
- for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
- set /a n+=1,a=!random!%%2
- if !a! equ 0 (
- set "_!random!!random!!random!=%%i"
- ) else (
- set "_!random!!random!!random!=!n!"
- )
- )
- for /f "tokens=2 delims==" %%i in ('set _') do (
- set /a n-=1
- if !n! equ 15 pause>nul&goto :eof
- set /p=%%i <nul
- )
复制代码
[ 本帖最后由 batman 于 2008-8-26 12:13 编辑 ]
作者: mkl 时间: 2008-8-27 20:15
- @echo off&setlocal enabledelayedexpansion
- :jj
- set aa=1
- for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
- set !aa!=%%i &set /a aa=!aa!+1
- )
- set va=1
- :tj
- set /a dd=%random%%%26+1 &set/a ss=%random%%%2
- if %ss%==0 (set/p=%dd% <nul) else set/p=!%dd%! <nul
- set/a va+=1
- if %va% lss 11 goto tj
- pause>nul
复制代码
作者: batman 时间: 2008-8-27 20:23
楼上没考虑重复的情况?
作者: mkl 时间: 2008-8-28 21:02
考虑后如下,但效率低- @echo off&setlocal enabledelayedexpansion
- :jj
- set aa=1 &set "bb="
- for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
- set !aa!=%%i &set /a aa=!aa!+1
- )
- set va=1
- :tj
- set /a dd=%random%%%26+1 &set/a ss=%random%%%2
- echo %bb% |find "%dd: =%">nul 2>nul &&goto tj
- set bb=%bb% %dd%
- if %ss%==1 (set/p=%dd% <nul) else set/p=!%dd%! <nul
- set/a va+=1
- if %va% lss 11 goto tj
- pause>nul
复制代码
作者: mkl 时间: 2008-8-28 21:20
原帖由 batman 于 2008/8/26 12:09 发表
@echo off&setlocal enabledelayedexpansion
for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
set /a n+=1,a=!random!%%2
if !a! equ 0 (
set "_!random!!random!!ra ...
请问 set_ 是什么意思?还有那个 set "_!random!!random!!random!=%%i 呢?
作者: batman 时间: 2008-8-29 00:51
原帖由 mkl 于 2008-8-28 21:20 发表
请问 set_ 是什么意思?还有那个 set "_!random!!random!!random!=%%i 呢?
请在我的代码的第一个for循环后加入一个set _运行看看,其实set _就是显示所有以_字符
打头的变量,具体可在cmd中键入set /?查询。
作者: 随风 时间: 2008-8-30 18:32
16楼 方法确实巧妙,不错。。!
作者: netbenton 时间: 2009-5-2 17:25 标题: 来一个规规矩矩的
取到一个剔除一个
- @echo off&setlocal enabledelayedexpansion
- set "str=a b c d e f g h i j k l m n o p q r s t u v w x y z "
- for %%i in (%str%) do (set/a #+=1,%%i=#)
- for /l %%a in (1,1,10) do (
- set/a asc=!random!%%#*2,#-=1
- for %%b in (!asc!) do (set asc=!str:~%%b,1!)
- for %%b in (!asc!) do (set str=!str:%%b =!&set/a $=!random!%%2,1/$ 2>nul||set asc=!%%b!)
- echo !asc!
- )
- pause
复制代码
作者: batman 时间: 2009-5-2 20:01
楼上会存在效率问题,特别是用到了||管道符。
[ 本帖最后由 batman 于 2009-5-2 20:03 编辑 ]
作者: netbenton 时间: 2009-5-2 23:31
测试了一下,“||”管道操作虽然要比其它管道操作快,但是比起if还是要慢好多,相当于if 用时的5~8倍。
改为用if 判断。综合测度速度不错。
- @echo off&setlocal enabledelayedexpansion
- set "str=a b c d e f g h i j k l m n o p q r s t u v w x y z "
- for %%i in (%str%) do (set/a #+=1,%%i=#)
- for /l %%a in (1,1,10) do (
- set/a asc=!random!%%#*2,#-=1
- for %%b in (!asc!) do (set asc=!str:~%%b,1!)
- for %%b in (!asc!) do (set str=!str:%%b =!&set/a $=!random!%%2&if !$! equ 0 set asc=!asc!)
- echo !asc!
- )
- pause
复制代码
作者: zhouyongjun 时间: 2009-6-16 23:15
- @echo off&setlocal enabledelayedexpansion
- set "str=a b c d e f g h i j k l m n o p q r s t u v w x y z"
- for %%i in (%str%) do set/a n+=1&set "_!n!=!n! %%i"
- :loop
- set/a m=%random%%%26+1,n=%random%%%2+1
- if not defined #%m% (
- for /f "tokens=1,2" %%1 in ("!_%m%!") do (
- <nul set/p=%%%n% &set/a num+=1,#%m%=0
- )
- )
- if %num% lss 10 goto loop
- echo/&pause
复制代码
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |