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

[其他] 【已解决】BAT:多次随机组合不重复的字符,如何控制各字符总数均等

本帖最后由 思想之翼 于 2023-9-3 16:29 编辑

从 00-99 中,随机抽取50个不重复的字符,组成1行,每行50列。
随机1000次,组成1000行,每行50列,共有50000个字符。
在这50000个字符中,若想控制 00 01 02...97 98 99 的每个字符,出现个数均为500个,BAT代码能否实现?

例如:
00 01 02 03...48 49
00 01 02 03...49 50
...
50 51 52 53...98 99

在上述行列中,00共有500个,01共有500个 ... 99共有500个。
1

评分人数

    • Batcher: 感谢给帖子标题标注[已解决]字样PB + 2

本帖最后由 qixiaobin0715 于 2023-9-8 12:50 编辑

我是说代码不使用两两互补“法”。
不是说不能出现两两互补的情况。

TOP

本帖最后由 思想之翼 于 2023-9-9 17:02 编辑

回复 40# qixiaobin0715
n=2,两两互补

TOP

本帖最后由 qixiaobin0715 于 2023-9-12 09:12 编辑

实际上可以将楼主顶楼的例子改成更通用的问题:
1.从00-99中,随机抽取50个不重复的字符,组成1行,每行50列。
2.抽取n次组成n行。(n为偶数)
3.最终的文本要控制每个字符个数均等,即00-99每个字符均要出现n/2次。
代码中n要求自定义,可以随意更改,只要是偶数即可。不使用两两互补法。
1

评分人数

    • 思想之翼: 举一反三,透过现象看本质。技术 + 1

TOP


这是一个数学中的排列问题》从n个元素中取出m个不同元素的不同排列数,如果m=n,则变为全排列问题。
本帖可变为两个全排列问题,例如00-99被分成00-49和50-99两组(亦可被分成奇数和偶数两组),各组完成500(次/行)全排列共合成1000行,正好满足lz的要求。
其后就是如何用bat/cmd/vbs/js/ps/...更显其能,实现每组(如00-49和50-99,或奇数组和偶数组)的500次/行全排列...
1

评分人数

TOP

回复 37# buyiyang
这是预料之中的事,后面生成的行属于查漏补缺,参见说明第2点。由于前面使用给定字符的频率陆续达到楼主所说的500次,这些字符在后面不能再继续使用,这些字符不再被设置为变量,请看代码第9行,所以可选的字符会越来越少,就会造成你所说的现象。
我觉得这种情况应当无关大局。如果非要消除这种情况的出现,可以通过调整部分 行的顺序来解决,方法很多,在这里举2个例子供参考:
1.掐头藏尾法或者叫移花接木法
思路是把前面若干行移到最后。
比如把前100行保存为2.txt,其余保存为1.txt,用copy或其它命令将2.txt合并到1.txt末尾。
替换第22行代码如下
  1. if %%i leq 100 (
  2.     echo,!str!>>2.txt
  3. ) else (
  4.     echo,!str!
  5. )
复制代码
然后将1.txt和2.txt在代码pause前完成合并。

实际上叫障眼法更准确。  
2.二次排列法
替换代码第22行
  1. echo,!random!:!str!
复制代码
在pause前增加如下代码
  1. sort 1.txt>2.txt
  2. (for /f "tokens=1*" %%i in (2.txt) do echo,%%j)>1.txt
  3. del 2.txt
复制代码
1

评分人数

TOP

回复 36# qixiaobin0715


    这个算法也不错,不过会导致最后几十行连续含有相同的数字。

TOP

本帖最后由 qixiaobin0715 于 2023-9-5 13:13 编辑

回复 23# pd1
以下代码根据你在23楼的思路写的,由于比较匆忙,看起来不是很明晰,未考虑效率问题,测试约1分钟左右。简要说明如下:
1.每次循环需要得到100个给定字符使用次数。(第17行)
2.判断给定的字符使用次数是否达到上限,若达到上限则忽略,否则按正常方法设置变量,以便继续使用。(第9行)
3.判断给定的字符尚可使用的次数是否达到剩余行数,若是,则本次优先使用(通过在未达到剩余行数上限的字符的变量名前加上字母,使达到剩余行数的字符变量在后面的循环中优先排在前面)。(第19、6-10行)
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /l %%i in (1,1,1000) do (
  4.         for /l %%j in (0,1,99) do (
  5.         set num=0%%j
  6.         if !@%%j! equ 0 (
  7.             set _!random!_%%j=!num:~-2!
  8.         ) else (
  9.             if !#%%j! neq 500 set _a!random!_%%j=!num:~-2!
  10.         )
  11.     )
  12.     set n=0
  13.     for /f "tokens=1-3 delims==_" %%a in ('set _') do (
  14.         set /a n+=1
  15.         if !n! leq 50 (
  16.             set str=!str! %%c
  17.             set /a #%%b+=1
  18.         )
  19.         set /a @%%b=1000-%%i-500+#%%b
  20.         set _%%a_%%b=
  21.     )
  22.     echo,!str!
  23.     set str=
  24. ))>1.txt
  25. pause
复制代码
4

评分人数

    • pd1: 还没看懂 批处理长一点我看着就费劲技术 + 1
    • 思想之翼: 感谢分享技术 + 1
    • buyiyang: 好算法技术 + 1
    • 77七: 高手!技术 + 1

TOP

  1. $arr1=100..199 -replace '^1'
  2. 1..500|%{
  3.     $arr=$arr1|Get-Random -Count 100
  4.     $arr[0..49] -join ' '
  5.     $arr[50..99] -join ' '
  6. } > 结果.txt
复制代码
根据17楼思路,代码还能再短,反正这个数据量也不大,计算量也小
1

评分人数

TOP

本帖最后由 77七 于 2023-9-5 13:58 编辑

回复 33# 77七


   我写了个比较复杂的...
  1. @echo off
  2. >2.txt echo 35 70 39 96 45 26 79 86 40 72 92 46 31 68 95 71 65 73 58 90 29 89 10 82 50 42 94 84 01 34 17 93 06 32 74 07 44 76 37 08 55 47 53 22 23 88 13 16 66 19
  3. >>2.txt echo 55 02 23 30 70 56 53 42 25 33 48 29 79 09 66 98 24 80 11 94 93 13 61 73 40 43 68 67 51 76 26 37 19 59 35 75 95 96 90 63 22 64 69 97 41 15 54 77 86 83
  4. setlocal enabledelayedexpansion
  5. for /f "delims=" %%a in (2.txt) do (
  6.         for %%b in (%%a) do (
  7.                 set /a #%%b+=1
  8.         )
  9. )
  10. for /f "delims=" %%a in (2.txt) do (
  11.         for %%b in (%%a) do (
  12.                 if !#%%b! equ 2 (
  13.                         if not defined ##%%b (
  14.                                 set str1=%%b !str1!
  15.                                 set str2=%%b !str2!
  16.                                 set /a m+=1
  17.                                 set ##%%b=1
  18.                         )
  19.                 ) else (
  20.                         set /a n+=1
  21.                         set _!random!_!n!=%%b
  22.                 )
  23.         )
  24. )
  25. for /f "tokens=2 delims==" %%a in ('set _') do (
  26.         if !m! lss 50 (
  27.                 set str1=%%a !str1!
  28.                 set /a m+=1
  29.         ) else (
  30.                 set str2=%%a !str2!
  31.         )
  32. )
  33. call :1 "!str1!"
  34. call :1 "!str2!"
  35. pause & exit
  36.         :1
  37.         setlocal
  38.         for %%a in (%~1) do (
  39.                 set /a k+=1
  40.                 set @!random!_!k!=%%a
  41.         )
  42.         for /f "tokens=2 delims==" %%a in ('set @') do (
  43.                 set newstr=%%a !newstr!
  44.         )
  45.         echo !newstr!
  46.         endlocal
复制代码
1

评分人数

bat小白,请多指教!谢谢!

TOP

如果对打乱排序后的结果,再处理,比如以两行为单位,随机排序这100个”数字“,每行不重复,让结果更随机一些,还挺有意思...感觉还是稍微有点难度...
  1. 35 70 39 96 45 26 79 86 40 72 92 46 31 68 95 71 65 73 58 90 29 89 10 82 50 42 94 84 01 34 17 93 06 32 74 07 44 76 37 08 55 47 53 22 23 88 13 16 66 19
  2. 55 02 23 30 70 56 53 42 25 33 48 29 79 09 66 98 24 80 11 94 93 13 61 73 40 43 68 67 51 76 26 37 19 59 35 75 95 96 90 63 22 64 69 97 41 15 54 77 86 83
复制代码


我抽取了结果的两行(不是互补的),在写,还没有写出来...
bat小白,请多指教!谢谢!

TOP

回复 30# qixiaobin0715


    大家互相交流是好事,能学到自己想要的都是好事。采用互补的2行的这种很巧妙,而且运行很快,生成的数据也能用。我是没想到这种方式

TOP

回复 28# buyiyang


    我试着py写,和你遇到一样的问题,我是把50000个数放一起,转set去重然后取50个  然后把这50个数从5万个数里剔除掉  然后再循环  也是到970-980左右 出现剩下的数字重复了取不到50个了
所以还是得设计算法来处理,我就水平有限,搞不定了
1

评分人数

TOP

回复 23# pd1
又看了看,开始回复23楼的帖子也是文不对题,没有理解你所说的意思,抱歉。

TOP

本帖最后由 buyiyang 于 2023-9-4 14:43 编辑

回复 26# pd1


    0-9随机10行每个数出现5次就会互补。

TOP

返回列表