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

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

[复制链接]
发表于 2008-9-6 21:49:57 | 显示全部楼层

来个另类的

要生成个临时文件b.bat:
  1. @echo off&setlocal enabledelayedexpansion
  2. set /p num=请输入字符:
  3. set "s=abcdefghijklnmopqrstuvwxyz"&set "nums=%num%"
  4. :lp
  5. set /a n+=1
  6. set "str1=%str1% %n%"
  7. set "ss=%ss%str%n%"&set "k=%k%)"
  8. set "_%n%=%num:~,1%"&set "num=%num:~1%"
  9. if defined num goto lp
  10. echo ^@echo off^&setlocal enabledelayedexpansion>b.bat
  11. for /f "skip=1 delims=" %%a in (%~fs0) do (
  12.     set /a x+=1
  13.     if !x! equ 9 goto loop
  14.     if !x! equ 1 (
  15.        echo set "num=%nums%">>b.bat
  16.        ) else (
  17.        if !x! neq 2 if !x! neq 6 echo %%a>>b.bat
  18.     )
  19. )
  20. :loop
  21. set "a=%%%%%s:~,1%"&set "b=%ss:~,4%"&set "c=%ss:~4,4%"
  22. set "str=!str!^!_%a%^!"
  23. if "%c%" equ "" set "c=flag"  
  24. echo for %a% in (^^^!%b%^^^!) do (set "%c%=^!%b%:%a%=^!">>b.bat
  25. set "s=%s:~1%"&set "ss=%ss:~4%"
  26. if defined ss goto loop
  27. echo echo !str!>>b.bat
  28. echo %k%>>b.bat
  29. echo pause^>nul>>b.bat
  30. endlocal&b
复制代码

[ 本帖最后由 batman 于 2008-9-6 22:06 编辑 ]

评分

参与人数 2PB +15 收起 理由
terse + 5
pusofalse + 10 不可谓不高!学习!

查看全部评分

 楼主| 发表于 2008-9-7 13:53:46 | 显示全部楼层
想给多点分  怎么总是错误啊
发表于 2008-9-7 16:55:27 | 显示全部楼层

回复 17楼 的帖子

terse前辈是不是输入空格了 abad 要这样的。
发表于 2011-5-21 15:02:11 | 显示全部楼层
效率还可以,但不支持重复字符。
7个字符,5040组合,用时不到15秒。

  1. @echo off&SETLOCAL ENABLEDELAYEDEXPANSION
  2. set "str=a b c d e f g"
  3. set time1=!time!
  4. for %%i in (%str%) do (
  5.     set /a n+=1,_%%i=n
  6. )
  7. echo, !str!
  8. for /l %%a in (1,1,10000000) do (
  9.     set "last="&set "flag="&set "pos=0"
  10.     for %%b in (!str!) do (
  11.         set /a pos+=1
  12.         if defined last (
  13.             set /a n1=_%%b,n2=_!last!
  14.             if !n1! gtr !n2! set flag=!last! !pos!
  15.             set "last=%%b"
  16.         ) else (
  17.             set "last=%%b"
  18.         )
  19.     )
  20.     if not defined flag call :end %%a
  21.     for /f %%b in ("!flag!") do for %%c in (!str!) do if !_%%c! gtr !_%%b! set "th=%%c"
  22.     for /f "tokens=1,3" %%b in ("!flag! !th!") do (
  23.         set "temp=!str:%%b=#!"
  24.         set "temp=!temp:%%c=%%b!"
  25.         set "str=!temp:#=%%c!"
  26.     )
  27.     set "ppos="&set "cut1="&set "cut2="&set "array="
  28.     for %%b in (!str!) do (
  29.         set /a ppos+=1
  30.         for /f "tokens=2" %%c in ("!flag!") do (
  31.             if !ppos! geq %%c (
  32.                 set "cut2=!cut2! %%b"
  33.             ) else (
  34.                 set "cut1=!cut1! %%b"
  35.             )
  36.         )
  37.     )
  38.     for %%i in (!cut2!) do (
  39.         set "array=%%i !array!"
  40.         for %%j in (!array!) do (
  41.             if %%i gtr %%j (
  42.                 set "array=!array:%%i=#!"
  43.                 set "array=!array:%%j=%%i!"
  44.                 set "array=!array:#=%%j!"
  45.             )
  46.         )
  47.     )
  48.     set str=!cut1! !array!
  49.     echo,!str!
  50. )
  51. :end
  52. echo,一共%1个排列. !time1!--^>!time!
  53. pause>nul&exit
复制代码
发表于 2011-5-21 18:19:26 | 显示全部楼层
本帖最后由 wankoilz 于 2011-5-22 09:05 编辑

既然老帖被挖出来了,俺也来凑热闹。
支持重复字符,我这里测试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
复制代码
发表于 2011-5-21 19:04:25 | 显示全部楼层
本帖最后由 zm900612 于 2011-5-22 13:16 编辑

【该思路已有先例,523066680较早提出】
我认为for嵌套递归始终是最快的方案,所以构思了一个基于for /l递归的新思路,唯一的缺陷是for嵌套理论上限62层[A-Za-z0-9],本代码由于作者偷懒,功能不够强大,仅兼容低于10层,而且不能有重复项...
  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 /l %%a in (2 1 %n%) do (
  11.         set /a last=%%a-1
  12.         set "for=for %%%%a in (^!tmp%%a^!) do ((set tmp!last!=^!tmp%%a: %%%%a = ^!)&!for!)"
  13. )
  14. ::为str构建相应层数的for嵌套
  15. set tmp%n%=%str%
  16. %for%
  17. ::执行组装而成的for嵌套
  18. echo 共有%z%种组合 开始于%t% 结束于%time%
  19. pause
复制代码
发表于 2011-5-21 19:13:13 | 显示全部楼层
楼上是字符插入的方法啊。
发表于 2011-5-21 19:22:54 | 显示全部楼层
22# caruko


??
不懂...
发表于 2011-5-21 19:24:26 | 显示全部楼层
反正5040种组合耗时3秒,应该算不错的成绩了
发表于 2011-5-21 21:06:01 | 显示全部楼层
楼上是字符插入的方法啊。
caruko 发表于 2011-5-21 19:13

是字符插入法。
发表于 2011-5-21 21:22:30 | 显示全部楼层
你们怎么会认为是字符插入呢?这段代码和我所理解的字符插入的概念一点关系都没有呀,看来原有的注释太少,弄详细点:
  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
复制代码
发表于 2011-5-21 21:27:35 | 显示全部楼层
那个%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
复制代码
发表于 2011-5-21 21:31:13 | 显示全部楼层
噢,发现27楼代码就是6楼代码,只是21楼代码是对这种思路的改进
发表于 2011-5-22 09:02:29 | 显示全部楼层
本帖最后由 wankoilz 于 2011-5-22 09:03 编辑

我是用的字符插入法,呵呵。
楼上构造for嵌套虽然不错,但效率还是不及20楼。
把21楼代码的%for%改成(%for%)>a.txt,且去掉for中的set/a z+=1 之后效率有所提升,测试8个字符40320个组合耗时近8秒。
发表于 2011-5-22 09:39:54 | 显示全部楼层
要速度就不能call,那么6楼的思路是最快的,

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

16楼和21楼的思路就是如此。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-16 19:16 , Processed in 0.013879 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表