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

【练习-068】批处理号码筛选练习

本帖最后由 batman 于 2012-2-29 10:25 编辑

出题目的:
  强化新手对字符截取和if判断的理解
加分原则:
  满分20分,其中解题思路7分,思路描述3分,代码运行效率4分,代码简洁4分,书写规范2分,
  本帖内同一id累计加分不超过40分(请大家在加分时注意)
  如管理层和技术组解题分值减半
  跟帖讨论的视情况加分,最高不超过10分
相关要求:
  请新手自觉独立解题不得抄袭别人代码(可以借鉴)
  请测试代码成功后再发帖
  请最好附上思路说明
题目如下:
  编写批处理代码对所有4位号码进行筛选归类,归类原则如下:
    一类 8888
    二类 x888 aaaa abcd
    三类 xx88 xaaa xabc aabb abab
    四类 xxx8 xxaa abba
    五类 其余的号码
    其中
      x表示不等于其后一位数值的任意数值
                 aaaa为除8888以外的4连号如0000 xaaa xxaa以此类推
      abc abcd代表顺子如123 321 1234 4321
      aabb为形如1122的号码 abab为形如1212的号码 abba为形如1221的号码
***共同提高***

穷举法 挨个试..

本帖最后由 jinzeyu 于 2012-2-29 11:25 编辑
  1. @echo off&setlocal enableDelayedExpansion&set str=0123456789876543210&set "ml=是三类&goto:eof"&for /l %%i in (1000,1,9999) do call:main %%i
  2. :main
  3. set i=%1
  4. set i1=%i:~0,1%
  5. set i2=%i:~1,1%
  6. set i3=%i:~2,1%
  7. set i4=%i:~3,1%
  8. if "%i%"=="8888" echo %1%ml:三=一%
  9. if "%i:~1%"=="888" echo %1%ml:三=二%
  10. if "%i:~2%"=="88" echo %1%ml%
  11. if "%i:~3%"=="8" echo %1%ml:三=四%
  12. if "%i:~2% %i2%"=="%i:~0,2% %i3%" echo %1%ml:三=二%
  13. if "%i:~1,2%"=="%i:~3%%i:~3%" echo %1%ml%
  14. if "%i:~3%"=="%i3%" echo %1%ml:三=四%
  15. for /l %%j in (0,1,16) do (
  16. if "%1"=="!str:~%%j,4!" echo %1%ml:三=二%
  17. if "%i:~1%"=="!str:~%%j,3!" echo %1%ml%
  18. if "%i:~0,3%"=="!str:~%%j,3!" echo %1%ml%)
  19. if "%i1%%i2%"=="%i4%%i3%" if not "%i1%"=="%i2%" echo %1%ml:一=四%
  20. if "%i1%%i3%"=="%i2%%i4%" if not "%i2%"=="%i4%" echo %1%ml%
  21. if "%i:~0,2%"=="%i:~2%" if not "%i1%"=="%i2%" echo %1%ml%
  22. echo %1是五类
复制代码
1

评分人数

    • batman: 书写有点不规范PB + 11

TOP

有几个问题:
  如7378算四类吗
  如1331算四类吗
  如1313算三类吗
  如1133算三类吗

TOP

回复 3# jinzeyu


    是的,顶楼应该描述得很清楚吧。。。
***共同提高***

TOP

回复 4# batman


    哦 我还以为也是连续数字呢

TOP

利用for的嵌套,写出指定特征形式的数字,再排除不正确的。。。。。
思路不清晰,排除得我快累死了。。。。。还不知道对不对。。。。。。。
以后再也不做这种题了。。。。。。。。。
  1. @echo off&SetLocal EnableDelayEdexpansion&cd /d "%~dp0"
  2. if exist "第四类" goto :1
  3. set "num1=0123456789"
  4. set "num2=9876543210"
  5. (for /l %%a in (0 1 9) do (
  6.   if "%%a" leq "5" echo !num1:~%%a,4! & echo !num2:~%%a,4!
  7.   if not "%%a"=="8" (
  8.     echo %%a%%a%%a%%a
  9.     echo %%a888
  10.   )
  11. ))>第二类
  12. (for /l %%a in (0 1 9) do (
  13.   for /l %%b in (0 1 9) do (
  14.     if not "%%b"=="8" (echo %%a%%b88)
  15.     if not "%%b"=="%%a" (
  16.       if not "%%b"=="8"  echo %%a%%b%%b%%b
  17.       set /a "n=%%a-1"
  18.       call set "n1=%%num1:~!n!,1%%"
  19.       call set "n2=%%num2:~!n!,1%%"
  20.       if %%a leq 6 if not "%%b"=="!n1!" if not "%%b"=="!num1:~%%a,1!"  echo  %%
  21. b!num1:~%%a,3!
  22.       if %%a leq 6 if not "%%b"=="!n2!" if not "%%b"=="!num2:~%%a,1!"  echo  %%
  23. b!num2:~%%a,3!
  24.       echo %%a%%a%%b%%b
  25.       echo %%a%%b%%a%%b
  26.     )
  27.   )
  28. ))>第三类
  29. (for /l %%a in (0 1 9) do (
  30.   for /l %%b in (0 1 9) do (
  31.     if not "%%b"=="%%a"  echo %%a%%b%%b%%a
  32.     for /l %%c in (0 1 9) do (
  33.       if not "%%a"=="%%b" if not "%%b"=="%%c"  if not "%%c"=="8" (
  34.          if not "%%b%%c"=="67"  echo  %%a%%b%%c8
  35.          echo %%a%%b%%c%%c
  36.       )
  37.     )
  38.   )
  39. ))>第四类
  40. :1
  41. set /p "number=input:"
  42. if "!number!"=="8888" echo 第一类 & goto :1
  43. findstr  /m  "!number!"   第三类 第二类 第四类 || echo 第五类
  44. echo -------------------------------------------------
  45. goto :1
复制代码
1

评分人数

TOP

回复 6# QIAOXINGXING


    兄弟是不是想复杂了,这个思路应该很好理的。。。
***共同提高***

TOP

回复 7# batman

估计是,,,,,,,坐等答案公布。。。。。。

TOP

不知道有没有简洁的代码 我的太复杂了...一堆if

TOP

4个 FOR 循环 省了字符截取 一味的 IF IF

TOP

本帖最后由 batman 于 2012-3-29 09:05 编辑

参考答案
  1. @echo off&setlocal enabledelayedexpansion
  2. (for /l %%a in (10000,1,19999) do (
  3.   set "str=%%a"&set "str=!str:~1!"&set "flag=五类"
  4.   set /a a=!str:~,1!,b=!str:~1,1!,c=!str:~2,1!,d=!str:~-1!,b1=b+1,b2=b-1,c1=c+2,c2=c-2,d1=d+3,d2=d-3
  5.   if "!d!" equ "8" set "flag=四类"
  6.   if "!c!" equ "!d!" set "flag=四类"
  7.   if "!a!!b!" equ "!d!!c!" set "flag=四类"
  8.   if "!c!!d!" equ "88" set "flag=三类"
  9.   for %%a in (!b!) do if "!str:%%a=!" equ "!a!" set "flag=三类"
  10.   if "!a!!b!" equ "!c!!d!" set "flag=三类"
  11.   if "!a!!c!" equ "!b!!d!" set "flag=三类"
  12.   for %%a in (1 2) do if "!b%%a!!c%%a!!d%%a!" equ "!b%%a!!b%%a!!b%%a!" set "flag=三类"
  13.   if "!b!!c!!d!" equ "888" set "flag=二类"
  14.   for %%a in (!a!) do if "!str:%%a=!" equ "" set "flag=二类"
  15.   for %%a in (1 2) do if "!a!!b%%a!!c%%a!!d%%a!" equ "!a!!a!!a!!a!" set "flag=二类"
  16.   if "!str!" equ "8888" set "flag=一类"
  17.   echo !flag! !str!
  18. ))>list.txt
  19. start list.txt
复制代码
***共同提高***

TOP

本帖最后由 batman 于 2012-3-27 10:07 编辑

在此对本题进行一下说明:
  其实本题真的不难,主要还在于判断的技巧性。总的来说有两种筛选的方法,一种是由低级向高级的筛选法,
我们就叫做正向筛选法吧(如11楼)。对任一个四位数我们先将它暂定为五类(set "flag=五类"),然后逐步
判断它是不是符合四、三、二、一类的标准,如果符合标准,flag变量就被重新赋值,最后输出flag的值(?类)
。另一种方法就是由高级向低级的筛选,我们就叫做反向筛选法。对任一个四位数我们先判断它是不是一类,如果
是就标识为一类号码,否则继续判断是不是二类,如果是就标识为二类号码,否则继续以此类推向下判断,最后将
数字标识为它属于的类别。
  这两种筛选方法各有千秋,总体上来说正向筛选法效率较差但代码相对会简单些,就是一行一行的if语句写下
来,而反向筛选法效率较高但代码会相对复杂点,因为其中涉及到数层的if嵌套。
  另外说下筛选中的难点(正反向一样),个人认为最难的就是abcd和abc顺子的判断,但是只要你抓住了这
类号码的特点,也不是很难的事。因为无论是正顺还是反顺,几个数值间肯定是一个以1或-1为差的等差数列,
所以我们只要将后面的数值依次减上其与第一个数值a的差,然后判断生成的新数值是不是一个aaaa 或aaa就可
以了。
***共同提高***

TOP

回复 12# batman
从五至一的筛选可以用set
从一至五的筛选可以用findstr
感觉效率不会差别太大
当然没有实测也不敢确定

顺子其实也没什么难的
就目前的需要还用不到判断+1和-1
直接罗列出二/三类中所有的顺子组合
然后一次findstr即可
天的白色影子

TOP

本帖最后由 neorobin 于 2012-3-28 17:09 编辑

借鉴 batman 的差值技巧:
  1. @echo off & setlocal enabledelayedexpansion
  2. > digit.txt (for /l %%i in (10000 1 19999) do (
  3.     (set s=%%i)& set /a w=!s:~1,1!,x=!s:~2,1!,y=!s:~3,1!,z=!s:~4,1!,w-=z,x-=z,y-=z,t=5
  4.     if !s:~-4!==8888 (set "t=1"
  5.     ) else if !s:~-3!==888 (set "t=2"
  6.     ) else for %%s in (000 -3-2-1 321) do if !w!!x!!y!==%%s set "t=2"
  7.     if !t!==5 if !s:~-2!==88 (set t=3) else for %%s in (00 21 -2-1) do if !x!!y!==%%s set "t=3"
  8.     if !t!==5 for %%s in (110 -1-10 101 -10-1) do if !w!!x!!y!==%%s set "t=3"
  9.     if !t!==5 if !s:~-1!==8 (set t=4) else if !y!==0 (set t=4) else (
  10.       for %%s in (011 0-1-1) do if !w!!x!!y!==%%s set t=4)
  11.     echo !t! !s:~-4!
  12. ) )
  13. start "" digit.txt
复制代码
差值基准字符取最后一个字符, 该字符没必要在匹配比较式中出现
0000 ~ 9999 共 10000 个序列:
1 类: 1
2 类: 32
3 类: 351
4 类: 1698
5 类: 7918

TOP

rem 对x的位置严格限定后得到的结果,与楼上的不同,没仔细看谁有问题
rem class1: 1
rem class2: 26          不包含8x88 88x8 888x
rem class3: 424     不包含88xx aaax abcx以及其它x变化位置的模式
rem class4: 1700    不包含8xxx aaxx xaax以及其它xx变化位置的模式
rem class5: 7868
天的白色影子

TOP

返回列表