Batch file 批量-查找置换

Batch file 批量-查找置换,batch-file,combinations,permutation,Batch File,Combinations,Permutation,我是批处理新手,我想知道我是否能按顺序找出所有的数字组合 在本例中,我有49个1-49之间的数字,我必须选择6个数字作为结果 例如: 1 2 3 4 5 6 1 2 3 4 5 7 ... 1 2 3 4 5 49 1 2 3 4 6 7 1 2 3 4 6 8 等等 这是我的旧代码: @echo off>NEWFILE&setLocal启用延迟扩展 设置a=44 设置b=45 设置c=46 组d=47 设置e=48 设定f=49 对于1中的/L%%a!A.做 对于2 1中的/L%%b

我是批处理新手,我想知道我是否能按顺序找出所有的数字组合

在本例中,我有49个1-49之间的数字,我必须选择6个数字作为结果

例如:

1 2 3 4 5 6 
1 2 3 4 5 7 
...
1 2 3 4 5 49 
1 2 3 4 6 7 
1 2 3 4 6 8
等等

这是我的旧代码:

@echo off>NEWFILE&setLocal启用延迟扩展 设置a=44 设置b=45 设置c=46 组d=47 设置e=48 设定f=49 对于1中的/L%%a!A.做 对于2 1中的/L%%b!B做 对于/L%%c,在3 1中!C做 对于4 1中的/L%%d!D做 对于/L%%e在5 1中!E做 对于6 1中的/L%%f!F做 回声。%%a%%b%%c%%d%%e%%f >>新文件 后藤:EOF 然而,它返回:

1 2 3 4 5 6
1 2 3 4 5 7
...
1 2 3 4 5 49
1 2 3 4 6 6
出现了两个6


我似乎无法修复它,请帮助,非常感谢

以后,请展示一些代码,说明您试图自己解决问题,说明您遇到了什么问题,输出结果不符合预期,等等。类似的问题是我的要求。为我编写的代码在这里通常不受欢迎。我无法理解你是如何在不显示任何代码的情况下获得投票权的,但这是生活

在这个例子中,我发现这个问题很有趣,所以我想我应该继续,让你开始。挑战:接受。这里有一个方法

@回音 延迟扩展 集合系列=1 2 3 4 5 6 :循环 回声%系列% 如果%series%==44 45 46 47 48 49转到:EOF 对于%s系列%do中的/f代币=1-6%%a 集合/a i1=%%a,i2=%%b,i3=%%c,i4=%%d,i5=%%e,i6=%%f+1 如果i6!全球技术法规49套/a i5+=1,i6=i5+1 如果i5!全球技术法规48套/a i4+=1,i5=i4+1,i6=i5+1 如果i4!全球技术法规47套/a i3+=1,i4=i3+1,i5=i4+1,i6=i5+1 如果i3!全球技术法规46套/a i2+=1,i3=i2+1,i4=i3+1,i5=i4+1,i6=i5+1 如果i2!全球技术法规45套/a i1+=1,i2=i1+1,i3=i2+1,i4=i3+1,i5=i4+1,i6=i5+1 集合系列=!i1!i2!i3!i4!i5!i6! 转到环路 这里有另一个更有效的解决方案

@回音 延迟扩展 集合系列=1 2 3 4 5 6 设置总数=0 对于1,1,44 do中的/L%%a 集合/a i2=%%a+1 对于/L%%b英寸!i2!,1,45做什么 集合/a i3=%%b+1 对于信用证%%c英寸!i3!,1,46做什么 集合/a i4=%%c+1 对于/L%%d in!i4!,1,47做什么 集合/a i5=%%d+1 对于/L%%e in!i5!,1,48做什么 集合/a i6=%%e+1 对于/L%%f英寸!i6!,1,49做什么 rem//取消对该回音的注释以观察进度,这会严重降低效率 rem回声%%a%%b%%c%%d%%e%%f 集合/a总计+=1 迄今为止的回声总数:!全部的 rem//应该经过13983816次迭代
将来,请展示一些代码,说明您试图自己解决问题,说明您在哪里遇到了问题,输出不符合预期,等等。类似于这里的问题是我的要求。为我编写的代码在这里通常不受欢迎。我无法理解你是如何在不显示任何代码的情况下获得投票权的,但这是生活

在这个例子中,我发现这个问题很有趣,所以我想我应该继续,让你开始。挑战:接受。这里有一个方法

@回音 延迟扩展 集合系列=1 2 3 4 5 6 :循环 回声%系列% 如果%series%==44 45 46 47 48 49转到:EOF 对于%s系列%do中的/f代币=1-6%%a 集合/a i1=%%a,i2=%%b,i3=%%c,i4=%%d,i5=%%e,i6=%%f+1 如果i6!全球技术法规49套/a i5+=1,i6=i5+1 如果i5!全球技术法规48套/a i4+=1,i5=i4+1,i6=i5+1 如果i4!全球技术法规47套/a i3+=1,i4=i3+1,i5=i4+1,i6=i5+1 如果i3!全球技术法规46套/a i2+=1,i3=i2+1,i4=i3+1,i5=i4+1,i6=i5+1 如果i2!全球技术法规45套/a i1+=1,i2=i1+1,i3=i2+1,i4=i3+1,i5=i4+1,i6=i5+1 集合系列=!i1!i2!i3!i4!i5!i6! 转到环路 这里有另一个更有效的解决方案

@回音 延迟扩展 集合系列=1 2 3 4 5 6 设置总数=0 对于1,1,44 do中的/L%%a 集合/a i2=%%a+1 对于/L%%b英寸!i2!,1,45做什么 集合/a i3=%%b+1 对于信用证%%c英寸!i3!,1,46做什么 集合/a i4=%%c+1 对于/L%%d in!i4!,1,47做什么 集合/a i5=%%d+1 对于/L%%e in!i5!,1,48做什么 集合/a i6=%%e+1 对于/L%%f英寸!i6!,1,49做什么 rem//取消对该回音的注释以观察进度,这会严重降低效率 rem回声%%a%%b%%c%%d%%e%%f 集合/a总计+=1 迄今为止的回声总数:!全部的 rem//应该经过13983816次迭代
考虑到存在13983816个唯一排列,问题是计算密集型的。看

Rojo的答案应该是可行的,但是GOTO和重复的FOR/F解析和IF逻辑会大大降低速度

如果使用嵌套FOR/L循环,代码速度会快得多

@echo off
setlocal enableDelayedExpansion
for /l %%A in (1 1 44) do (
  set /a start=%%A+1
  for /l %%B in (!start! 1 45) do (
    set /a start=%%B+1
    for /l %%C in (!start! 1 46) do (
      set /a start=%%C+1
      for /l %%D in (!start! 1 47) do (
        set /a start=%%D+1
        for /l %%E in (!start! 1 48) do (
          set /a start=%%E+1
          for /l %%F in (!start! 1 49) do (
            echo %%A %%B %%C %%D %%E %%F
          )
        )
      )
    )
  )
)
这对我来说仍然是难以忍受的缓慢
et此脚本将结果打印到屏幕上。我估计在我的机器上需要1.25小时。将输出重定向到文件大约快5倍,大约15分钟。

考虑到存在13983816个唯一排列,问题是计算密集型的。看

Rojo的答案应该是可行的,但是GOTO和重复的FOR/F解析和IF逻辑会大大降低速度

如果使用嵌套FOR/L循环,代码速度会快得多

@echo off
setlocal enableDelayedExpansion
for /l %%A in (1 1 44) do (
  set /a start=%%A+1
  for /l %%B in (!start! 1 45) do (
    set /a start=%%B+1
    for /l %%C in (!start! 1 46) do (
      set /a start=%%C+1
      for /l %%D in (!start! 1 47) do (
        set /a start=%%D+1
        for /l %%E in (!start! 1 48) do (
          set /a start=%%E+1
          for /l %%F in (!start! 1 49) do (
            echo %%A %%B %%C %%D %%E %%F
          )
        )
      )
    )
  )
)

让这个脚本将结果打印到屏幕上的速度仍然慢得令人无法忍受。我估计在我的机器上需要1.25小时。将输出重定向到文件大约快5倍,大约15分钟。

当你发布问题时,你应该发布你解决问题的努力,描述使用的方法和你遇到的问题;否则,您可能会得到类似的答案,而根本没有任何解释,例如:

编辑:正如用户dbenham和aschipfl所指出的,我的原始代码有一个小错误:set/ai=M-1行应该放在:nextSet标签之后。这是正确的代码:

@echo off
setlocal EnableDelayedExpansion

set "N=%1"
set "M=%2"

set "line="
for /L %%i in (1,1,%M%) do (
   set "C[%%i]=%%i"
   set "line=!line! ^!C[%%i]^!"
)

:nextSet
   set /A i=M-1
   for /L %%j in (!C[%M%]!,1,%N%) do (
      set "C[%M%]=%%j"
      echo %line%
   )

   :nextPos
   set "C=!C[%i%]!"
   if %C% equ %N% (
      set /A i-=1
      if !i! equ 0 goto :EOF
      goto nextPos
   )
   for /L %%i in (%i%,1,%M%) do (
      set /A C+=1,C[%%i]=C
   )
   if !C[%M%]! gtr %N% goto nextPos

goto nextSet
显然,更正后的代码生成的结果数量要大得多,而此版本速度特别慢…:

下面的新版本使用了与dbenham解决方案完全相同的代码;其唯一的优点是,您可以非常简单地更改用于生成结果的参数:

@echo off
setlocal EnableDelayedExpansion

set "N=%1"
set "M=%2"

set /A j=N-M, prev=0
set "for=" & set "line=" & set "endfor="
for /L %%i in (1,1,%M%) do (
   set /A j+=1
   set "for=!for! set /A start=!prev!+1 & for /L %%%%i in (^!start^!,1,!j!) do ("
   set "line=!line! %%%%i"
   set "endfor=!endfor!)"
   set "prev=%%%%i"
)
REM ECHO !FOR! echo !LINE! %ENDFOR%
%for% echo %line% %endfor%
输出示例:

C:\> test.bat 6 4
 1 2 3 4
 1 2 3 5
 1 2 3 6
 1 2 4 5
 1 2 4 6
 1 2 5 6
 1 3 4 5
 1 3 4 6
 1 3 5 6
 1 4 5 6
 2 3 4 5
 2 3 4 6
 2 3 5 6
 2 4 5 6
 3 4 5 6
要获得结果,请使用:test.bat 49 6

第二次编辑:添加了更快的方法

当需要解决的问题是一个过程花费的时间过长时,一个明显的替代方法是使用更快的编程语言。下面使用的解决方案有点类似于批处理文件编程:

@if (@CodeSection == @Batch) @then

@echo off
echo Start: %time%
cscript //nologo //E:JScript "%~F0" > result.txt
echo End:   %time%
goto :EOF

@end

// JScript code section

for ( var A=1; A <= 44; ++A ) {
   for ( var B=A+1; B <= 45; ++B ) {
      for ( var C=B+1; C <= 46; ++C ) {
         for ( var D=C+1; D <= 47; ++D ) {
            for ( var E=D+1; E <= 48; ++E ) {
               for ( var F=E+1; F <= 49; ++F ) {
                  WScript.Echo(A,B,C,D,E,F);
               }
            }
         }
      }
   }
}

这是一个批处理JScript混合脚本;用.BAT扩展名保存它。这个程序在我便宜又慢的笔记本电脑上用了不到9分钟就生成了一个239 MB的文件,共13983816行。

当你发布一个问题时,你应该发布你解决它的努力,描述你使用的方法和遇到的问题;否则,您可能会得到类似的答案,而根本没有任何解释,例如:

编辑:正如用户dbenham和aschipfl所指出的,我的原始代码有一个小错误:set/ai=M-1行应该放在:nextSet标签之后。这是正确的代码:

@echo off
setlocal EnableDelayedExpansion

set "N=%1"
set "M=%2"

set "line="
for /L %%i in (1,1,%M%) do (
   set "C[%%i]=%%i"
   set "line=!line! ^!C[%%i]^!"
)

:nextSet
   set /A i=M-1
   for /L %%j in (!C[%M%]!,1,%N%) do (
      set "C[%M%]=%%j"
      echo %line%
   )

   :nextPos
   set "C=!C[%i%]!"
   if %C% equ %N% (
      set /A i-=1
      if !i! equ 0 goto :EOF
      goto nextPos
   )
   for /L %%i in (%i%,1,%M%) do (
      set /A C+=1,C[%%i]=C
   )
   if !C[%M%]! gtr %N% goto nextPos

goto nextSet
显然,更正后的代码生成的结果数量要大得多,而此版本速度特别慢…:

下面的新版本使用了与dbenham解决方案完全相同的代码;其唯一的优点是,您可以非常简单地更改用于生成结果的参数:

@echo off
setlocal EnableDelayedExpansion

set "N=%1"
set "M=%2"

set /A j=N-M, prev=0
set "for=" & set "line=" & set "endfor="
for /L %%i in (1,1,%M%) do (
   set /A j+=1
   set "for=!for! set /A start=!prev!+1 & for /L %%%%i in (^!start^!,1,!j!) do ("
   set "line=!line! %%%%i"
   set "endfor=!endfor!)"
   set "prev=%%%%i"
)
REM ECHO !FOR! echo !LINE! %ENDFOR%
%for% echo %line% %endfor%
输出示例:

C:\> test.bat 6 4
 1 2 3 4
 1 2 3 5
 1 2 3 6
 1 2 4 5
 1 2 4 6
 1 2 5 6
 1 3 4 5
 1 3 4 6
 1 3 5 6
 1 4 5 6
 2 3 4 5
 2 3 4 6
 2 3 5 6
 2 4 5 6
 3 4 5 6
要获得结果,请使用:test.bat 49 6

第二次编辑:添加了更快的方法

当需要解决的问题是一个过程花费的时间过长时,一个明显的替代方法是使用更快的编程语言。下面使用的解决方案有点类似于批处理文件编程:

@if (@CodeSection == @Batch) @then

@echo off
echo Start: %time%
cscript //nologo //E:JScript "%~F0" > result.txt
echo End:   %time%
goto :EOF

@end

// JScript code section

for ( var A=1; A <= 44; ++A ) {
   for ( var B=A+1; B <= 45; ++B ) {
      for ( var C=B+1; C <= 46; ++C ) {
         for ( var D=C+1; D <= 47; ++D ) {
            for ( var E=D+1; E <= 48; ++E ) {
               for ( var F=E+1; F <= 49; ++F ) {
                  WScript.Echo(A,B,C,D,E,F);
               }
            }
         }
      }
   }
}

这是一个批处理JScript混合脚本;用.BAT扩展名保存它。这个程序在我便宜又慢的笔记本电脑上用了不到9分钟就生成了一个239 MB的文件,其中有13983816行。

我刚刚准确地编写了这个嵌套for/L循环解决方案,但一个该死的电话阻止了发布。当我注释掉echo语句时,它大约在5分钟左右完成,fwiw。总之,+1。@rojo我尝试了两种方法并找到了两种效果,但dbenham的方法似乎更快。我刚刚编写了这个嵌套的for/L循环解决方案,但一个该死的电话阻止了发布。当我注释掉echo语句时,它大约在5分钟左右完成,fwiw。总之,+1。@rojo我尝试了两种方法,发现两种方法都有效,但dbenham的方法似乎更快。你的算法有严重问题。正确的结果应该有13983816行,而不是4774行。我注意到您的输出只有39行,其中第二个值在使用49和6的参数调用时为3。据我所知,解决方法应该非常简单:移动标签:nextSet向上设置一行以显示在行集合/A I=M-1之前。为了性能起见,我准备建议进行以下更改:1。移动行集合C=!C[%i%]!在if%C%块之后;2.在标签后面插入set/A C=C[%i%]+i-M:nextPos;3.将if%C%eq%N%替换为if%C%gtr%N%;4.删除行如果!C[%M%]!全球技术法规%N%;然而,尽管这些更改避免了额外的goto循环和多个for/L%%i循环,但它们使我的计算机上的代码速度降低了约65%,奇怪的是,将输出重定向到nul并使用参数20和5。你知道这是为什么吗?set/A是一只如此缓慢的野兽吗?@dbenham你说得对!我在代码和脑海中错放了一行:@aschipfl:没有办法让这段代码更快;查看我的编辑…这段代码是否在短时间内生成了正确的结果?如果是这样,我可以请你选择它作为最佳答案,并对其进行投票吗?你的算法有严重错误。正确的结果应该有13983816行,而不是4774行。我注意到
您的输出只有39行,其中第二个值在使用49和6参数调用时为3。据我所知,解决方法应该非常简单:移动标签:nextSet up一行,在行集合/A I=M-1之前显示。为了性能起见,我准备建议进行以下更改:1。移动行集合C=!C[%i%]!在if%C%块之后;2.在标签后面插入set/A C=C[%i%]+i-M:nextPos;3.将if%C%eq%N%替换为if%C%gtr%N%;4.删除行如果!C[%M%]!全球技术法规%N%;然而,尽管这些更改避免了额外的goto循环和多个for/L%%i循环,但它们使我的计算机上的代码速度降低了约65%,奇怪的是,将输出重定向到nul并使用参数20和5。你知道这是为什么吗?set/A是一只如此缓慢的野兽吗?@dbenham你说得对!我在代码和脑海中错放了一行:@aschipfl:没有办法让这段代码更快;查看我的编辑…这段代码是否在短时间内生成了正确的结果?如果是这样,我可以请你选择它作为最佳答案,并对其进行投票吗?结束问题的方法是对答案进行反馈,并选择一个作为最佳答案;这样做会将问题标记为已回答,并为OP和回答者都打分。在问题标题中添加“关闭”或任何其他类似的横幅是本网站不使用的做法。关闭问题的方式是对答案进行反馈,并选择一个作为最佳答案;这样做会将问题标记为已回答,并为OP和回答者都打分。在问题标题中添加关闭或任何其他类似的横幅是本网站不使用的做法。