中国DOS联盟

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

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

中国DOS联盟论坛
现在时间是 2026-06-14 20:18
楼 主 [已结]排列组合 发表于 2008-06-29 05:35 ·  中国 山东 淄博 联通
银牌会员
★★★
积分 1,604
发帖 646
注册 2008-04-13 23:39
UID 115804
性别 男
状态 离线
随便给出一组字串 比如 a b c
罗列出a b c 所有的排列组合 即是输出 如下

a b c
a c b
b a c
b c a
c a b
c b a


我用笨方法,三重for循环能得到如此的结果,但字符数量不一定。。。
如此。。。求教高人。。。希望能总结出一个高效实用的方法。。。

[ Last edited by pusofalse on 2008-12-28 at 03:32 ]
本帖最近评分记录 (共 1 条) 点击查看详情
评分人分数时间
zzz19760225 +2 2017-11-30 13:27
心绪平和,眼藏静谧,无比安稳的火... Purification of soul...Just a false...^_^
2 这是我的代码 发表于 2008-06-29 10:22 ·  中国 山东 淄博 联通
银牌会员
★★★
积分 1,604
发帖 646
注册 2008-04-13 23:39
UID 115804
性别 男
状态 离线
忙活了一个早晨,结果却发现重大的BUG 就是只能三个字符时 才能排列出所有组合 多了或少了都会出错 只能3个 请教各位高人,有没有好的方法~

@echo off&setlocal enabledelayedexpansion
del ts.txt>nul 2>nul
set var=1 2 3
:1
if defined var5 set var=%var5%
for %%a in (%var%) do (
set dx=%%a
set/a mn+=1
set !mn!=%%a
call :lp
)

if defined had echo 完成&pause>nul&exit/b
for /l %%a in (%mn% -1 1) do set "var5=!var5!!%%a! "
set had=had
goto 1


:lp
set var1=!var:%dx%=!
for %%a in (%var1%) do (
set "var3=!var3!%%a "
)
>>ts.txt echo %var3%%dx%
set "%var3%%dx%=abcd"
set var3=


[ Last edited by pusofalse on 2008-6-29 at 10:29 AM ]
心绪平和,眼藏静谧,无比安稳的火... Purification of soul...Just a false...^_^
3 发表于 2008-06-29 11:04 ·  中国 湖南 株洲 电信
金牌会员
★★★★
永远的学习者
积分 3,105
发帖 1,276
注册 2008-03-08 13:00
UID 112398
性别 男
状态 离线
不知道这样合要求不:

@echo off&setlocal enabledelayedexpansion
if exist temp.txt del /q temp.txt
:begin
set code=abcd&set str=&set n=4
:again
set /a a=%random%%%%n%
set a=!code:~%a%,1!
set code=!code:%a%=!
set str=%str%%a%
set /a n-=1
if "%str:~3%" equ "" goto again
if defined var for %%i in (%var%) do if "%%i" equ "%str%" goto begin
echo %str%>>temp.txt
set var=%var% %str%
set /a m+=1
if %m% lss 24 goto begin
sort temp.txt&del /q temp.txt
pause>nul
批处理之家新域名:www.bathome.net
4 发表于 2008-06-29 11:07 ·  中国 山东 淄博 联通
银牌会员
★★★
积分 1,604
发帖 646
注册 2008-04-13 23:39
UID 115804
性别 男
状态 离线
ZW前辈给出的代码也是有BUG的。。。 只能排列四个字符的组合 如果多出几个 只保留前面四个。。。 如果少了,会出现以零为除数的错误。。。
随机给出的字串,字串数量未知。。。
心绪平和,眼藏静谧,无比安稳的火... Purification of soul...Just a false...^_^
5 发表于 2008-06-29 11:29 ·  中国 湖南 株洲 电信
金牌会员
★★★★
永远的学习者
积分 3,105
发帖 1,276
注册 2008-03-08 13:00
UID 112398
性别 男
状态 离线
Originally posted by pusofalse at 2008-6-29 11:07:
ZW前辈给出的代码也是有BUG的。。。 只能排列四个字符的组合 如果多出几个 只保留前面四个。。。 如果少了,会出现以零为除数的错误。。。
随机给出的字串,字串数量未知。。。

字符数不定确实是个大麻烦,下面的代码基本可以实现了(自己觉得好繁杂):

@echo off&setlocal enabledelayedexpansion
if exist temp.txt del /q temp.txt
:enter
cls&set /p codes=请输入字符组(字符间请用空格格开):
if not defined codes goto enter
for %%i in (%codes%) do set /a m+=1
set /a num=1,x=m,y=m-1
:lp
set /a num*=m
set /a m-=1
if %m% neq 0 goto lp
:begin
set code=!codes: =!&set str=&set /a n=x
:again
set /a a=%random%%%%n%
set a=!code:~%a%,1!
set code=!code:%a%=!
set str=%str%%a%
set /a n-=1
if "!str:~%y%!" equ "" goto again
if exist temp.txt for /f "delims=" %%i in (temp.txt) do if "%%i" equ "%str%" goto begin
echo %str%>>temp.txt
set /a m+=1
if %m% lss %num% goto begin
cls&sort temp.txt&del /q temp.txt
pause>nul


[ Last edited by zw19750516 on 2008-6-29 at 12:04 PM ]
本帖最近评分记录 (共 1 条) 点击查看详情
评分人分数时间
pusofalse +8 2008-06-29 11:34
批处理之家新域名:www.bathome.net
6 发表于 2008-06-29 11:35 ·  中国 山东 淄博 联通
银牌会员
★★★
积分 1,604
发帖 646
注册 2008-04-13 23:39
UID 115804
性别 男
状态 离线
真是太感谢了! 学习中~
心绪平和,眼藏静谧,无比安稳的火... Purification of soul...Just a false...^_^
7 发表于 2008-06-29 11:37 ·  中国 湖南 株洲 电信
金牌会员
★★★★
永远的学习者
积分 3,105
发帖 1,276
注册 2008-03-08 13:00
UID 112398
性别 男
状态 离线
Originally posted by pusofalse at 2008-6-29 11:35:
真是太感谢了! 学习中~

这样的方法当字符数到6位以上将会慢得吓人!,还是要需求别的方法了。
批处理之家新域名:www.bathome.net
8 发表于 2008-06-29 11:46 ·  中国 山东 淄博 联通
银牌会员
★★★
积分 1,604
发帖 646
注册 2008-04-13 23:39
UID 115804
性别 男
状态 离线
嗯 试过了,6位以下还好。。。另外,还有一个bug 输入类似b e e n 这样的其中有两个相同字符的字串时会出错
心绪平和,眼藏静谧,无比安稳的火... Purification of soul...Just a false...^_^
9 发表于 2008-06-29 11:52 ·  中国 重庆 九龙坡区 电信
版主
★★★★★
积分 9,023
发帖 5,017
注册 2007-05-31 19:39
UID 89899
性别 男
状态 离线
以前学习《算法设计》的时候写过这样的C代码,是一个递归算法。

/*本程序在TC2.0下运行通过*/
/*Algorithm 5.7 PERMUTATIONS1*/
#include<stdio.h>
int P;
void print(int P,int n)
{
int i;
printf("\n");
for(i=1;i<=n;i++)
printf("%d",P);
sleep(1);
}

void perm1(int m,int n)
{
int j,t;
if(m==n)
print(P,n);
else
for(j=m;j<=n;j++)
{
t=P;
P=P;
P=t;
perm1(m+1,n);
t=P;
P=P;
P=t;
}
}

main()
{
int j,n;
clrscr();
window(35,1,46,1);
textbackground(4);
textcolor(128);
clrscr();
printf("www.cndos.cn\n");
printf("Please input the value of n:");
scanf("%d",&n);
for(j=1;j<=n;j++)
P=j;
perm1(1,n);
printf("\nPress any key to end.");
getch();
}
10 发表于 2008-06-29 11:52 ·  中国 湖南 株洲 电信
金牌会员
★★★★
永远的学习者
积分 3,105
发帖 1,276
注册 2008-03-08 13:00
UID 112398
性别 男
状态 离线
相同的字符好处理的:
在批处理中加入for %%i in (%codes%) do set a=#%%i#&set b=!b! !a!,再做相应处理,具体的代码我就不写了,只是高位的效率问题好像用批处理是解决不了的,因为用我二楼的方法set var=%var% %str%是会受到字符总数限制的。

[ Last edited by zw19750516 on 2008-6-29 at 12:02 PM ]
批处理之家新域名:www.bathome.net
11 发表于 2008-06-29 13:37 ·  中国 陕西 移动(全省通用)
银牌会员
★★★★
钻石会员
积分 2,278
发帖 1,020
注册 2007-11-19 13:34
UID 103127
性别 男
状态 离线
@echo off&setlocal enabledelayedexpansion
set s1=a b c
for %%a in (!s1!) do (set s2=!s1:%%a=!
for %%b in (!s2!) do (set s3=!s2:%%b=!
for %%c in (!s3!) do (echo %%a%%b%%c
) ) )
pause


6位的代码类似
本帖最近评分记录 (共 1 条) 点击查看详情
评分人分数时间
xeibobin +2 2009-09-20 06:51
山外有山,人外有人;低调做人,努力做事。

进入网盘(各种工具)~~ 空间~~cmd学习
12 发表于 2008-06-29 13:47 ·  中国 湖南 株洲 电信
金牌会员
★★★★
永远的学习者
积分 3,105
发帖 1,276
注册 2008-03-08 13:00
UID 112398
性别 男
状态 离线
终于提高了一点点效率,本机测试排列六位数将近10分钟:

@echo off&setlocal enabledelayedexpansion
if exist pl.txt del /q pl.txt
:enter
cls&set /p codes=请输入三个以上的字符(字符应不相同并请用空格格开):
if not defined codes goto enter
for %%i in (%codes%) do set /a m+=1
if %m% lss 3 set m=0&goto enter
cls&echo 正在排列中,请稍候...
set /a num1=1,x=m,y=m-1
:lp
set /a num1*=m,m-=1
if %m% neq 0 goto lp
set /a num2=num1/6+1,sz=1
:begin
set code=%codes: =%&set str=&set n=%x%
:again
set /a a=%random%%%%n%,n-=1
set a=!code:~%a%,1!
set str=%str%%a%&set code=!code:%a%=!
if "!str:~%y%!" equ "" goto again
for /l %%a in (1,1,%sz%) do (
for %%i in (!var%%a!) do (
if "%%i" equ "%str%" goto begin

)
)
echo %str%>>temp.txt
set var%sz%=!var%sz%! %str%
set /a m+=1,z+=1
if %z% equ 6 set /a sz+=1,z=0
if %m% neq %num1% goto begin
sort temp.txt>pl.txt&del /q temp.txt&start pl.txt
批处理之家新域名:www.bathome.net
13 发表于 2008-06-29 14:07 ·  中国 陕西 移动(全省通用)
银牌会员
★★★★
钻石会员
积分 2,278
发帖 1,020
注册 2007-11-19 13:34
UID 103127
性别 男
状态 离线
7位用时2.28秒
timediff.bat 可在论坛p函数库里找到(用于计算两个时间点的差值)
@echo off&setlocal enabledelayedexpansion
set s1=a b c e d f g
set t=%time%
for %%a in (!s1!)do (set s2=!s1:%%a=!
for %%b in (!s2!)do (set s3=!s2:%%b=!
for %%c in (!s3!)do (set s4=!s3:%%c=!
for %%d in (!s4!)do (set s5=!s4:%%d=!
for %%e in (!s5!)do (set s6=!s5:%%e=!
for %%f in (!s6!)do (set s7=!s6:%%f=!
for %%g in (!s7!)do (echo %%a%%b%%c%%d%%e%%f%%g
) ) ) ) ) ) )
call timediff.bat %t% %time% 0
pause
山外有山,人外有人;低调做人,努力做事。

进入网盘(各种工具)~~ 空间~~cmd学习
14 发表于 2008-06-29 16:33 ·  中国 湖南 株洲 电信
金牌会员
★★★★
永远的学习者
积分 3,105
发帖 1,276
注册 2008-03-08 13:00
UID 112398
性别 男
状态 离线
Originally posted by plp626 at 2008-6-29 14:07:
7位用时2.28秒
timediff.bat 可在论坛p函数库里找到(用于计算两个时间点的差值)
@echo off&setlocal enabledelayedexpansion
set s1=a b c e d f g
set t=%time%
f ...

方法是好啊,很快,但请搞清楚楼主的题意:“字符数不定”。
批处理之家新域名:www.bathome.net
15 发表于 2008-06-29 17:19 ·  中国 陕西 西安 电信
铂金会员
★★★★
积分 5,212
发帖 2,478
注册 2007-02-08 23:39
UID 79003
性别 男
状态 离线
根据n生成一个n重套嵌的bat然后调用=。=


bat貌似用参数可以实现“递归”。。。不过没有实践这个。。。脑细胞。。。
本帖最近评分记录 (共 1 条) 点击查看详情
评分人分数时间
pusofalse +11 2008-12-18 12:39
S smile 微笑,L love 爱,O optimism 乐观,R relax 放松,E enthusiasm 热情...Slore
论坛跳转: