返回列表 发帖

【练习-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 编辑
@echo off&setlocal enableDelayedExpansion&set str=0123456789876543210&set "ml=是三类&goto:eof"&for /l %%i in (1000,1,9999) do call:main %%i
:main
set i=%1
set i1=%i:~0,1%
set i2=%i:~1,1%
set i3=%i:~2,1%
set i4=%i:~3,1%
if "%i%"=="8888" echo %1%ml:三=一%
if "%i:~1%"=="888" echo %1%ml:三=二%
if "%i:~2%"=="88" echo %1%ml%
if "%i:~3%"=="8" echo %1%ml:三=四%
if "%i:~2% %i2%"=="%i:~0,2% %i3%" echo %1%ml:三=二%
if "%i:~1,2%"=="%i:~3%%i:~3%" echo %1%ml%
if "%i:~3%"=="%i3%" echo %1%ml:三=四%
for /l %%j in (0,1,16) do (
if "%1"=="!str:~%%j,4!" echo %1%ml:三=二%
if "%i:~1%"=="!str:~%%j,3!" echo %1%ml%
if "%i:~0,3%"=="!str:~%%j,3!" echo %1%ml%)
if "%i1%%i2%"=="%i4%%i3%" if not "%i1%"=="%i2%" echo %1%ml:一=四%
if "%i1%%i3%"=="%i2%%i4%" if not "%i2%"=="%i4%" echo %1%ml%
if "%i:~0,2%"=="%i:~2%" if not "%i1%"=="%i2%" echo %1%ml%
echo %1是五类COPY
1

评分人数

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

TOP

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

TOP

回复 3# jinzeyu


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

TOP

回复 4# batman


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

TOP

利用for的嵌套,写出指定特征形式的数字,再排除不正确的。。。。。
思路不清晰,排除得我快累死了。。。。。还不知道对不对。。。。。。。
以后再也不做这种题了。。。。。。。。。
@echo off&SetLocal EnableDelayEdexpansion&cd /d "%~dp0"
if exist "第四类" goto :1
set "num1=0123456789"
set "num2=9876543210"
(for /l %%a in (0 1 9) do (
  if "%%a" leq "5" echo !num1:~%%a,4! & echo !num2:~%%a,4!
  if not "%%a"=="8" (
    echo %%a%%a%%a%%a
    echo %%a888
  )
))>第二类
(for /l %%a in (0 1 9) do (
  for /l %%b in (0 1 9) do (
    if not "%%b"=="8" (echo %%a%%b88)
    if not "%%b"=="%%a" (
      if not "%%b"=="8"  echo %%a%%b%%b%%b
      set /a "n=%%a-1"
      call set "n1=%%num1:~!n!,1%%"
      call set "n2=%%num2:~!n!,1%%"
      if %%a leq 6 if not "%%b"=="!n1!" if not "%%b"=="!num1:~%%a,1!"  echo  %%
b!num1:~%%a,3!
      if %%a leq 6 if not "%%b"=="!n2!" if not "%%b"=="!num2:~%%a,1!"  echo  %%
b!num2:~%%a,3!
      echo %%a%%a%%b%%b
      echo %%a%%b%%a%%b
    )
  )
))>第三类
(for /l %%a in (0 1 9) do (
  for /l %%b in (0 1 9) do (
    if not "%%b"=="%%a"  echo %%a%%b%%b%%a
    for /l %%c in (0 1 9) do (
      if not "%%a"=="%%b" if not "%%b"=="%%c"  if not "%%c"=="8" (
         if not "%%b%%c"=="67"  echo  %%a%%b%%c8
         echo %%a%%b%%c%%c
      )
    )
  )
))>第四类
:1
set /p "number=input:"
if "!number!"=="8888" echo 第一类 & goto :1
findstr  /m  "!number!"   第三类 第二类 第四类 || echo 第五类
echo -------------------------------------------------
goto :1COPY
1

评分人数

TOP

回复 6# QIAOXINGXING


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

TOP

回复 7# batman

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

TOP

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

TOP

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

TOP

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

参考答案
@echo off&setlocal enabledelayedexpansion
(for /l %%a in (10000,1,19999) do (
  set "str=%%a"&set "str=!str:~1!"&set "flag=五类"
  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
  if "!d!" equ "8" set "flag=四类"
  if "!c!" equ "!d!" set "flag=四类"
  if "!a!!b!" equ "!d!!c!" set "flag=四类"
  if "!c!!d!" equ "88" set "flag=三类"
  for %%a in (!b!) do if "!str:%%a=!" equ "!a!" set "flag=三类"
  if "!a!!b!" equ "!c!!d!" set "flag=三类"
  if "!a!!c!" equ "!b!!d!" set "flag=三类"
  for %%a in (1 2) do if "!b%%a!!c%%a!!d%%a!" equ "!b%%a!!b%%a!!b%%a!" set "flag=三类"
  if "!b!!c!!d!" equ "888" set "flag=二类"
  for %%a in (!a!) do if "!str:%%a=!" equ "" set "flag=二类"
  for %%a in (1 2) do if "!a!!b%%a!!c%%a!!d%%a!" equ "!a!!a!!a!!a!" set "flag=二类"
  if "!str!" equ "8888" set "flag=一类"
  echo !flag! !str!
))>list.txt
start list.txtCOPY
***共同提高***

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 的差值技巧:
@echo off & setlocal enabledelayedexpansion
> digit.txt (for /l %%i in (10000 1 19999) do (
    (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
    if !s:~-4!==8888 (set "t=1"
    ) else if !s:~-3!==888 (set "t=2"
    ) else for %%s in (000 -3-2-1 321) do if !w!!x!!y!==%%s set "t=2"
    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"
    if !t!==5 for %%s in (110 -1-10 101 -10-1) do if !w!!x!!y!==%%s set "t=3"
    if !t!==5 if !s:~-1!==8 (set t=4) else if !y!==0 (set t=4) else (
      for %%s in (011 0-1-1) do if !w!!x!!y!==%%s set t=4)
    echo !t! !s:~-4!
) )
start "" digit.txtCOPY
差值基准字符取最后一个字符, 该字符没必要在匹配比较式中出现
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

返回列表