中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

中国DOS联盟论坛
现在时间是 2026-06-19 21:52
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [已结]排列组合 查看 6,102 回复 36
16 发表于 2008-06-29 19:18 ·  中国 湖南 株洲 电信
金牌会员
★★★★
永远的学习者
积分 3,105
发帖 1,276
注册 2008-03-08 13:00
18年会员
UID 112398
性别 男
状态 离线
脑袋想破了,还只能用替归法来算,以下代码在理论上适合10位内的排列,但不知怎么到了9位就出问题,郁闷啊:

@echo off&setlocal enabledelayedexpansion
if exist pl.txt del /q pl.txt
:set
cls&set /p s1=请输入字符组(字符间请用空格格开):
if not defined s1 goto set
for %%i in (%s1%) do set /a num+=1
for %%a in (%s1%) do (
set s2=!s1:%%a=!
set str=%%a
if "!str:~%num%!" neq "" echo !str!>>pl.txt
for %%b in (!s2!) do (
set s3=!s2:%%b=!
set str=%%a%%b
if "!str:~%num%!" neq "" echo !str!>>pl.txt
for %%c in (!s3!) do (
set s4=!s3:%%c=!
set str=%%a%%b%%c
if "!str:~%num%!" neq "" echo !str!>>pl.txt
for %%d in (!s4!) do (
set s5=!s4:%%d=!
set str=%%a%%b%%c%%d
if "!str:~%num%!" neq "" echo !str!>>pl.txt
for %%e in (!s5!) do (
set s6=!s5:%%e=!
set str=%%a%%b%%c%%d%%e
if "!str:~%num%!" neq "" echo !str!>>pl.txt
for %%f in (!s6!) do (
set s7=!s6:%%f=!
set str=%%a%%b%%c%%d%%e%%f
if "!str:~%num%!" neq "" echo !str!>>pl.txt
for %%g in (!s7!) do (
set s8=!s7:%%g=!
set str=%%a%%b%%c%%d%%e%%f%%g
if "!str:~%num%!" neq "" echo !str!>>pl.txt
for %%h in (!s8!) do (
set s9=!s9:%%h=!
set str=%%a%%b%%c%%d%%e%%f%%g%%h
if "!str:~%num%!" neq "" echo !str!>>pl.txt
for %%i in (!s9!) do (
set s10=!s9:%%i=!
set str=%%a%%b%%c%%d%%e%%f%%g%%h%%i
if "!str:~%num%!" neq "" echo !str!>>pl.txt
for %%j in (!s10!) do (
set str=%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j
if "!str:~%num%!" neq "" echo !str!>>pl.txt
))))))))))
start pl.txt


[ Last edited by zw19750516 on 2008-6-29 at 07:28 PM ]
批处理之家新域名:www.bathome.net
17 发表于 2008-06-29 21:29 ·  中国 陕西 西安 电信
银牌会员
★★★★
钻石会员
积分 2,278
发帖 1,020
注册 2007-11-19 13:34
18年会员
UID 103127
性别 男
状态 离线
用递归 我想核心的代码不会超过3行可以搞定,谁来挑战下?
zw兄:
你这个代码生成了临时文件,也不叫递归,你的代码可以归为“另类”
山外有山,人外有人;低调做人,努力做事。

进入网盘(各种工具)~~ 空间~~cmd学习
18 发表于 2008-06-29 21:34 ·  中国 广东 广州 电信
银牌会员
★★★
永远的菜鸟
积分 1,335
发帖 574
注册 2007-11-27 12:50
18年会员
UID 103929
性别 男
来自 广西
状态 离线
太多了麻烦,最主要是实现了就行了,想要排列更多的话,以此类推...
@echo off
setlocal enabledelayedexpansion
:begin
cls
set "n=0"
set /p s1=请输入8个以内的字符并用空格隔开:
for %%i in (%s1%) do (set /a n+=1)
if %n% gtr 8 goto :begin
for %%a in (!s1!) do (
if "%n%"=="1" (echo %%a) else (set s2=!s1:%%a=!)
for %%b in (!s2!) do (
if "%n%"=="2" (echo %%a%%b) else (set s3=!s2:%%b=!)
for %%c in (!s3!) do (
if "%n%"=="3" (echo %%a%%b%%c) else (set s4=!s3:%%c=!)
for %%d in (!s4!) do (
if "%n%"=="4" (echo %%a%%b%%c%%d) else (set s5=!s4:%%d=!)
for %%e in (!s5!) do (
if "%n%"=="5" (echo %%a%%b%%c%%d%%e) else (set s6=!s5:%%e=!)
for %%f in (!s6!) do (
if "%n%"=="6" (echo %%a%%b%%c%%d%%e%%f) else (set s7=!s6:%%f=!)
for %%g in (!s7!) do (
if "%n%"=="7" (echo %%a%%b%%c%%d%%e%%f%%g) else (set s8=!s7:%%g=!)
for %%h in (!s8!) do (
echo %%a%%b%%c%%d%%e%%f%%g%%h
))))))))
pause&goto :begin
19 发表于 2008-06-29 21:35 ·  中国 山东 淄博 联通
银牌会员
★★★
积分 1,604
发帖 646
注册 2008-04-13 23:39
18年会员
UID 115804
性别 男
状态 离线
我想这道题如果攻透了 会有很大用处的。。。
心绪平和,眼藏静谧,无比安稳的火... Purification of soul...Just a false...^_^
20 发表于 2008-06-30 00:18 ·  中国 重庆 电信
版主
★★★★★
积分 9,023
发帖 5,017
注册 2007-05-31 19:39
19年会员
UID 89899
性别 男
状态 离线
什么用处?生成暴力破解用的密码字典?
21 发表于 2008-06-30 01:05 ·  中国 山东 淄博 联通
银牌会员
★★★
积分 1,604
发帖 646
注册 2008-04-13 23:39
18年会员
UID 115804
性别 男
状态 离线
不只是暴力破解。。。总之就是与解码有关了。。。
心绪平和,眼藏静谧,无比安稳的火... Purification of soul...Just a false...^_^
22 发表于 2008-06-30 14:59 ·  中国 广西 百色 中移铁通
银牌会员
★★★
永远的菜鸟
积分 1,335
发帖 574
注册 2007-11-27 12:50
18年会员
UID 103929
性别 男
来自 广西
状态 离线
如果是猜测密码的话,把18楼的代码改成以下的也许更合适些吧
@echo off
setlocal enabledelayedexpansion
:begin
cls
for /l %%a in (1 1 10) do (set "s%%a=")
set "n="&set "var="&set "m="&set "count="
set /p var=请输入10个以内的字符(用不用空格隔开无所谓):
:more_
set "s1=!s1!!var:~,1! "
if not "!var:~1!"=="" set var=!var:~1!&goto :more_
for %%i in (%s1%) do (set /a m+=1)
if %m% gtr 10 (echo.&echo ...输入错误...&echo.&pause&goto :begin)
set /p n=请输入要组合的字符的数量(默认为全部):
set "t=%time%"
if "%n%"=="" set "n=%m%"
for %%a in (!s1!) do (
if "%n%"=="1" (set /a count+=1&echo %%a) else (set s2=!s1:%%a=!)
for %%b in (!s2!) do (
if "%n%"=="2" (set /a count+=1&echo %%a%%b) else (set s3=!s2:%%b=!)
for %%c in (!s3!) do (
if "%n%"=="3" (set /a count+=1&echo %%a%%b%%c) else (set s4=!s3:%%c=!)
for %%d in (!s4!) do (
if "%n%"=="4" (set /a count+=1&echo %%a%%b%%c%%d) else (set s5=!s4:%%d=!)
for %%e in (!s5!) do (
if "%n%"=="5" (set /a count+=1&echo %%a%%b%%c%%d%%e) else (set s6=!s5:%%e=!)
for %%f in (!s6!) do (
if "%n%"=="6" (set /a count+=1&echo %%a%%b%%c%%d%%e%%f) else (set s7=!s6:%%f=!)
for %%g in (!s7!) do (
if "%n%"=="7" (set /a count+=1&echo %%a%%b%%c%%d%%e%%f%%g) else (set s8=!s7:%%g=!)
for %%h in (!s8!) do (
if "%n%"=="8" (set /a count+=1&echo %%a%%b%%c%%d%%e%%f%%g%%h) else (set s9=!s8:%%h=!)
for %%i in (!s9!) do (
if "%n%"=="9" (set /a count+=1&echo %%a%%b%%c%%d%%e%%f%%g%%h%%i) else (set s10=!s9:%%i=!)
for %%j in (!s10!) do (
set /a count+=1&echo %%a%%b%%c%%d%%e%%f%%g%%h%%i%%j
))))))))))
echo.&echo 一共有 %count% 种组合&echo.
echo %t%
echo %time%
echo.&pause&goto :begin
23 发表于 2008-06-30 17:40 ·  中国 重庆 渝中区 联通
初级用户
★★
积分 198
发帖 89
注册 2007-09-06 23:22
18年会员
UID 96746
性别 男
来自 重庆
状态 离线
我用“插入法”,发现效率还不错,代码也简短:
@echo off&setlocal enabledelayedexpansion
set/p chr=请输入要排列的字母,以空格分开:
for %%i in (%chr%) do set a=%%i
set - %a%=ok&set chr=!chr:%a%=!
for %%i in (%chr%) do call :out %%i
for /f "delims=-= tokens=1" %%i in ('set -') do echo %%i
pause>nul

:out
for /f "delims=-= tokens=1" %%i in ('set -') do (
set - %1%%i=ok
for %%j in (%%i) do (
for %%k in (%%i) do (set str=!str! %%k&if %%j==%%k set str=!str! %1)
set -!str!=ok&set str=
)
set -%%i=
)
24 回23楼 发表于 2008-06-30 18:51 ·  中国 广西 百色 中移铁通
银牌会员
★★★
永远的菜鸟
积分 1,335
发帖 574
注册 2007-11-27 12:50
18年会员
UID 103929
性别 男
来自 广西
状态 离线
经测试当输入7个数的时候,23楼的代码花费了三十几秒,而22楼的只用了几秒,试试??
要上班了,明天再来看结果,哈哈
25 发表于 2008-06-30 20:41 ·  中国 重庆 渝中区 联通
初级用户
★★
积分 198
发帖 89
注册 2007-09-06 23:22
18年会员
UID 96746
性别 男
来自 重庆
状态 离线
肯定,call得太多自然效率低,我的关键是不限制字符数目。
26 发表于 2008-12-01 16:31 ·  中国 重庆 联通
中级用户
★★
积分 363
发帖 162
注册 2007-04-22 21:31
19年会员
UID 86104
性别 男
状态 离线
如果给出的字符有重复就出错了!如:abbcd 又如:12321
可以修改去掉这个BUG吗
27 发表于 2008-12-17 17:19 ·  中国 广东 揭阳 电信
银牌会员
★★★★
SuperCleaner
积分 2,362
发帖 1,133
注册 2008-02-02 21:36
18年会员
UID 110072
性别 男
状态 离线
文、代码:523066680
blog: http://hi.baidu.com/523066680
发表于:http://www.cn-dos.net/forum/viewthread.php?tid=41243&fpage=1&highlight=&page=2 27楼

先贴代码

@echo off&setlocal enabledelayedexpansion
title code by hi.baidu.com/523066680
errorcommand>list.x 2>nul
echo,允许字符串重复,字符数不定,空格什么的字符就别试了哈. &echo.
set /p str="输入将被枚举排列情况的字符串(形式如:abcd): "
call :fo "%str%" ""
echo,--------已将信息导入 list.x文件 请检查.
pause
exit

:fo
if %1=="" (echo,%~2 &echo,%~2>>list.x&goto :eof)
if not defined _%~1 (set _%~1=-1)
set str=%~1

:foa
set /a _%~1+=1,foa=_%~1,fob=foa+1
call :fo "!str:~0,%foa%!!str:~%fob%!" "%~2!str:~%foa%,1!"
set str=%~1
set /a foa=_%~1
if not "!str:~%foa%,-1!"=="" (goto :foa)
set "_%~1="
goto :eof



我来了,黑板报出完了,心情无比放松,看中这道题,"研究"了几天,有点结果了,分享下.
主要内容 1.谈谈前面楼的代码
2.分享我在解题过程中学到的东西
首先谈谈楼上的内容
以 plp626 提出的多重for最为快速,虽然只能对指定数量的字符,但是可以修改啊,
22楼修改的不错,我觉得能到10个字符就可以满足需求了,尤其是速度就像直接type答案一样快.
但是作为一个学者,寻求更好的办法是有必要的.于是23楼的代码超短(Good!),且符合要求
虽然没来得及理解,暂时发现的问题是:
当我输入6个字符时,结束的时候按Enter居然不退出,估计
可能死循环了.又看了下,汗,请大家测试的时候在pause>nul后面加exit
另外,输入字符数多运行时间长是很自然的事情,我觉得不用挑这个毛病.

本人认为23楼代码很短,精悍,值得学习下的.

下面先说说本人解题过程学到的东西:
[主要是想要讨论call 的参数递归,关于这道题 ,上次看到batman 有快速的解法,
我就不转载了 期待 batman 大哥 续帖
]

1.也想对plp626代码改进,玩了一下用%var% 代表 一条命令执行的方法,下面给出理解版:

@echo off
set fo="for %%1 in (a b c) do (for %%2 in (a b c) do ("
set end="))"

%fo:"=%
echo %%1 %%2
%end:"=%
pause


感觉太好玩了,不够"自动化"对吧?ok 我们用for 来决定要用几重for ,曾试着重组那个多重For的思路,
不过变量跟符号太多了,实在搞不下去,停工,思路别浪费,做别的. 用这个思路实现:
根据用户输入的符号,列出这些符号包括本身的所有组合
这是个简单点的题目,例如输入 1 2 则输出 1 1 , 1 2 , 2 1 , 2 2 好处主要是允许输入字符数不定.
虽然不了解"密码字典",不过感觉上要做的话这个代码应该更适合(比如说密码是223456的时候).
代码如下:

@echo off &setlocal enabledelayedexpansion
title code by hi.baidu.com/523066680
set "fo=" &set "end=" &set "n=0"
set /p "str=输入字符,以空格隔开: "
for %%a in (%str%) do set /a n+=1

for /l %%x in (1,1,%n%) do (
set fo="for %%%%x in (%str%) do (!fo!"
set end="!end!)"
set echo=!echo! %%%%x
)

%fo:"=%
echo %echo%
%end:"=%
pause



2.call 参数 回归
实现这个,我觉得可能Call可以实现,记得call
返回的时候,接下来的东西都是原来的,会不会参数也是原来的?



所以,不能期待set 的变量也能有"重叠的记忆功能" ,要么加上编号,但会很繁杂的.

-----------------以下内容谈论call 参数
废话说多了,开始探究call有多强大(call 参数返回 理解版):

@echo off
call :a 123
:a
echo %1

:b
if %1==123 (call :a 456) else (goto :eof)
echo %1
pause
exit


还算好理解吧? 来个多层的,玩转call:

@echo off
echo,call :fo "abcd"
call :fo "abcd"
pause
exit

:fo
if %1=="" (echo,参数1已经没有字符了,返回call,接下一句 &goto :eof)
set str=%~1

:foa
echo,call :fo "%str:~1%"
call :fo "%str:~1%"

echo 已返回,现参数1的值为 %~1
goto :eof
::一定很郁闷对吧,后面一句echo 咋显示4次,奥妙尽在goto :eof 因为本身就是被call了多次啊.


越玩越有趣啊, 自己那个代码就不打算详细分析了,写这篇文章不是晕大家的,所以我也主要用中文描述,讲一些可能用的上的东西.

温馨提示:很多问题阻碍了我很久,而我最后一次理清所有思路,是在关上电脑的时候,可见:经常对着电脑不利于思考啊.
----------------末
本人知识及能力实在有限,感觉这样分层的call并分层的返回 应该就是前面楼说的 "递归" 了吧
希望有资料的人把相关资料分享下哈. 现在感觉像是进入了完全不知道的逻辑领域....

[ Last edited by 523066680 on 2008-12-19 at 10:41 ]
本帖最近评分记录 (共 3 条) 点击查看详情
评分人分数时间
pusofalse +13 2008-12-18 12:35
moniuming +15 2008-12-21 12:44
xeibobin +2 2009-09-20 06:56
28 发表于 2008-12-18 10:36 ·  中国 广东 揭阳 电信
银牌会员
★★★★
SuperCleaner
积分 2,362
发帖 1,133
注册 2008-02-02 21:36
18年会员
UID 110072
性别 男
状态 离线
我写的这么辛苦 到网吧发表还得花钱,怎能不顶起来?

要是没人鸟 我以后也懒得写了....

[ Last edited by 523066680 on 2008-12-18 at 11:06 ]
29 发表于 2008-12-18 11:51 ·  中国 福建 三明 电信
中级用户
★★
积分 458
发帖 211
注册 2006-07-26 19:42
19年会员
UID 59307
状态 离线
有些时候还是留给人自由思考的空间好。思路仅作为讨论用,而且是写得越简单越好,如果写得过于详细,容易造成思维定势。

一点建议,请勿见怪。
本帖最近评分记录 (共 1 条) 点击查看详情
评分人分数时间
523066680 +5 2008-12-19 10:25
┌───────┐
├→学习→实践→┤
└───────┘
30 发表于 2008-12-19 10:24 ·  中国 广东 揭阳 电信
银牌会员
★★★★
SuperCleaner
积分 2,362
发帖 1,133
注册 2008-02-02 21:36
18年会员
UID 110072
性别 男
状态 离线
说的很好 有道理 , 我决定把 文章改下
只讨论我过程中学到的批处理技术
论坛跳转: