[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

【练习-020】批处理根据输入列出组合

如输入a b a


输入 a b c d e a b

写了一个效率很不高到7位的话 就要近50秒
难度是要能处理相同字符组合
贴出就加分
2天后来加分

建议把临时文件名改为纯数字,这样每次循环还可以省去两个set

TOP

本帖最后由 wankoilz 于 2011-5-22 15:20 编辑

32楼的代码来自20楼...
楼上分析的在理,但就32楼代码而言for/f读取算不上频繁吧,8个字符执行7次for/f

TOP

32楼用偏移的办法确实更好,如果是8个排列项,那这种方法就避开了!7次的set和for /l,从而弥补了for /f频繁读写对效率的影响,这种用for /f从文件读取的思路真是太妙了

TOP

32# wankoilz


没测试,
真如你说的话,看来有更快的算法,先收藏。。

TOP

本帖最后由 wankoilz 于 2011-5-22 11:42 编辑

6楼并非最快吧...
把6楼代码构造成求8个字符40320个组合,且去掉set/a flag+=1,耗时8秒。
  1. @echo off&setlocal enabledelayedexpansion
  2. set var=a b c d e f g h
  3. echo %time%
  4. (for %%i in (!var!) do (
  5.     set var1=!var:%%i=!
  6.     for %%j in (!var1!) do (
  7.     set var2=!var1:%%j=!
  8.     for %%k in (!var2!) do (
  9.     set var3=!var2:%%k=!
  10.     for %%l in (!var3!) do (
  11.     set var4=!var3:%%l=!
  12.     for %%m in (!var4!) do (
  13.     set var5=!var4:%%m=!
  14.     for %%n in (!var5!) do (
  15.     set var6=!var5:%%n=!
  16.     for %%o in (!var6!) do (
  17.     set var7=!var6:%%o=!
  18.     for %%p in (!var7!) do (
  19.     echo %%i %%j %%k %%l %%m %%n %%o %%p
  20.     )))))))))>c.txt
  21. echo %time%
  22. pause
复制代码
同样的求8个字符40320个组合,下面的耗时不到4秒:
  1. @echo off&setlocal enabledelayedexpansion
  2. set/p s=请输入,用一个空格分开:
  3. echo %time%
  4. set f1=a.txt
  5. set f2=b.txt
  6. >!f1! echo !s:~,1!&set s=!s:~1!
  7. set len=1
  8. for %%a in (%s%) do (
  9.     (for /f %%b in (!f1!) do (
  10.         set tmp=%%b
  11.         for /l %%c in (0,1,!len!) do echo !tmp:~,%%c!%%a!tmp:~%%c!
  12.     ))>!f2!
  13.     set t=!f1!
  14.     set f1=!f2!
  15.     set f2=!t!
  16.     set/a len+=1
  17. )
  18. echo %time%
  19. start %f1%&del/f %f2%
  20. pause
复制代码
我在想for嵌套得太深了是不是会影响效率...
1

评分人数

TOP

最老老实实的枚举法没人关注。。。
怎样对字符串进行可重复组合?
http://www.bathome.net/viewthrea ... muid=29086#pid78176
从一组数字中取任意个数字之和在一个数值范围内
http://www.bathome.net/viewthrea ... muid=29086#pid77555

TOP

要速度就不能call,那么6楼的思路是最快的,

为了短小,我们可以构造一个“制造函数的函数”来制造6楼那个代码,从而支持可变字符个数的排列

16楼和21楼的思路就是如此。。。

TOP

本帖最后由 wankoilz 于 2011-5-22 09:03 编辑

我是用的字符插入法,呵呵。
楼上构造for嵌套虽然不错,但效率还是不及20楼。
把21楼代码的%for%改成(%for%)>a.txt,且去掉for中的set/a z+=1 之后效率有所提升,测试8个字符40320个组合耗时近8秒。

TOP

噢,发现27楼代码就是6楼代码,只是21楼代码是对这种思路的改进

TOP

那个%for%运行起来就是这个效果:
  1. @echo off&setlocal enabledelayedexpansion&set tmp5=a b c de f
  2. for %%5 in (!tmp5!) do (
  3. set tmp4=!tmp5:%%5 =!
  4. for %%4 in (!tmp4!) do (
  5. set tmp3=!tmp4:%%4 =!
  6. for %%3 in (!tmp3!) do (
  7. set tmp2=!tmp3:%%3 =!
  8. for %%2 in (!tmp2!) do (
  9. set tmp1=!tmp2:%%2 =!
  10. for /f "delims=" %%1 in ("!tmp1:%%2=!") do (
  11. echo %%5 %%4 %%3 %%2 %%1
  12. )
  13. )
  14. )
  15. )
  16. )
  17. pause
复制代码
很明显是最土的办法...只是我改进思路后,在执行之前可以自动定义层数,然后用一个变量存储了整个for嵌套,实际运行的代码就是这样子:
  1. @echo off&setlocal enabledelayedexpansion&set tmp5=a b c de f
  2. for %%5 in (!tmp5!) do ((set tmp4=!tmp5:%%5 =!)&for %%4 in (!tmp4!) do ((set tmp3=!tmp4:%%4 =!)&for %%3 in (!tmp3!) do ((set tmp2=!tmp3:%%3 =!)&for %%2 in (!tmp2!) do ((set tmp1=!tmp2:%%2 =!)&for /f "delims=" %%1 in ("!tmp1:%%2=!") do echo %%5 %%4 %%3 %%2 %%1 ))))
  3. pause
复制代码

TOP

你们怎么会认为是字符插入呢?这段代码和我所理解的字符插入的概念一点关系都没有呀,看来原有的注释太少,弄详细点:
  1. @echo off&setlocal enabledelayedexpansion
  2. set str= a b c d e f g
  3. set t=%time%
  4. for %%a in (%str%) do (
  5.         set /a n+=1,"tmp+=^!tmp"
  6.         set "echo=%%!n! !echo!"
  7. )
  8. ::初始化
  9. set "for=for /f %%1 in ("^^!tmp1:%%2 =^^!") do (set /a z+=1)&echo %echo%"
  10. ::定义最里层的for
  11. for /l %%a in (2 1 %n%) do (
  12.         set /a last=%%a-1
  13.         set "for=for %%%%a in (^!tmp%%a^!) do ((set tmp!last!=^!tmp%%a: %%%%a = ^!)&!for!)"
  14. rem 定义for嵌套,一层包一层...
  15. )
  16. ::为str构建相应层数的for嵌套
  17. set tmp%n%=%str%
  18. %for%
  19. ::执行组装而成的for嵌套,改成echo !for!就明白了
  20. echo 共有%z%种组合 开始于%t% 结束于%time%
  21. pause
复制代码

TOP

楼上是字符插入的方法啊。
caruko 发表于 2011-5-21 19:13

是字符插入法。

TOP

反正5040种组合耗时3秒,应该算不错的成绩了

TOP

22# caruko


??
不懂...

TOP

返回列表