标题: [挑战] 批处理寻找所有条件里相同的数字 [打印本页]
作者: flyinspace 时间: 2008-10-17 13:20 标题: [挑战] 批处理寻找所有条件里相同的数字
假设有如下数字:
2190717
219117
2199817
2190517
2191417
21921917
为了大量数据统计的需要,我用一句话生成类似的数据
for /l %%i in (1,1,100) do echo 219%%i17>>1.txt
在这堆数据里,都有 219 的前缀和 17 的后缀,而中间的数据是随机的。
现在,我们的题目来了:
利用批处理,找出 219 的前缀 和 17 的后缀,并将去掉后的结果输出到2.txt
输出的结果类似:
1
2
3
……
100
前提:219 和 17在题目中是未知的,所以我们需要找出这2个未知的数据。。(这也是这里的难点)
作者: pusofalse 时间: 2008-10-17 13:47
有意思的题目,好好想想。。。
作者: batman 时间: 2008-10-17 16:56
写了个删除前缀的(后缀亦然),效率不怎么高:- @echo off&setlocal enabledelayedexpansion
- set /p str=<1.txt
- :lp
- for /f "delims=" %%i in ('findstr "%var%%str:~,1%" 1.txt') do set /a n+=1
- if not defined num set "num=%n%"
- if "%n%" equ "%num%" (
- set "var=%var%%str:~,1%"&set "str=%str:~1%"
- set "n=0"&goto lp
- )
- for /f "delims=" %%i in (1.txt) do (
- set "str=%%i"
- echo !str:%var%=!
- )
- pause>nul
复制代码
作者: pusofalse 时间: 2008-10-17 17:09
- @echo off&setlocal enabledelayedexpansion
- set /p str=<a.txt
- set /a n=-1
- :loop
- set/a n+=1
- for /f "delims=" %%a in (a.txt) do (
- set "var=%%a"
- if "!var:~%n%,1!" neq "!str:~%n%,1!" set "x=%n%"
- set "str=%%a"
- )
- if not defined x goto loop
- for /f "delims=" %%i in (a.txt) do (
- set "var=%%i"
- echo !var:~%x%!
- )
- pause
复制代码
也来一个,同样只是去掉前缀。输出结果跟batman版主的代码有点出入。
作者: batman 时间: 2008-10-17 17:23
思维定向了,一直想先把前缀提出来,pusofalse版主的代码证明了并不要提出来。
作者: pusofalse 时间: 2008-10-17 17:34
再修改下,能正确输出1,2,3、、、、100。- @echo off&setlocal enabledelayedexpansion
- cd.>a.txt
- set/a r=%random%,d=!random!,n=-1
- for /l %%a in (1 1 100) do set "_!random!!random!=%r%%%a%d%"
- for /f "tokens=2 delims==" %%i in ('set _') do echo>>a.txt %%i
- set /p str=<a.txt
- :loop
- set/a n+=1,m+=1
- for /f "delims=" %%a in (a.txt) do (
- set "var=%%a"
- if "!var:~%n%,1!" neq "!str:~%n%,1!" if not defined x set "x=%n%"
- if "!var:~-%m%,1!" neq "!str:~-%m%,1!" if not defined y set "y=%m%"
- set "str=%%a"
- )
- for %%a in (x y) do if not defined %%a goto loop
- set/a y-=1
- for /f "delims=" %%i in (a.txt) do (
- set "var=%%i"
- echo !var:~%x%,-%y%!
- )
- pause>nul
复制代码
[ 本帖最后由 pusofalse 于 2008-10-17 18:28 编辑 ]
作者: youxi01 时间: 2008-10-17 19:16
我在思考一个问题,或者询问楼主:
在这里,究竟是人工识别前缀还是要求自动识别?
作者: flyinspace 时间: 2008-10-17 19:21
原帖由 youxi01 于 2008-10-17 19:16 发表
我在思考一个问题,或者询问楼主:
在这里,究竟是人工识别前缀还是要求自动识别?
当然是自动识别前缀和后缀来呀。。
若是人工识别,这个题目就没有难度了。。
这个是对字符串知识的一次总结。。
作者: 随风 时间: 2008-10-17 20:43
:- @echo off&setlocal enabledelayedexpansion
- set /p var=<a.txt
- set q=%var:~0,1%
- set h=%var:~-1%
- for /f "delims=:" %%a in ('findstr /n "." a.txt') do set /a z=%%a
- :loop
- for /f "delims=:" %%a in ('findstr /n "^%q%" a.txt') do set /a x=%%a
- if %x% equ %z% (
- set /a m+=1
- set "q=!q!!var:~1,1!"
- set "var=!var:~1!"
- goto loop
- )
- :loop2
- for /f "delims=:" %%a in ('findstr /n "%h%$" a.txt') do set /a x=%%a
- if %x% equ %z% (
- set /a j+=1&set var=!var:~0,-1!
- set h=!var:~-1,1!!h!
- goto loop2
- )
- for /f "delims=" %%a in (a.txt) do (
- set "str=%%a"
- echo !str:~%m%,-%j%!
- )
- pause
复制代码
作者: namejm 时间: 2008-10-17 23:08
既然前缀和后缀是未知的,又怎么找得出来呢?楼主提供的条件让人不解,难道是说,如果前缀和后缀重复的次数达到一定次数之后,就要把这些数据过滤掉?
作者: zqz0012005 时间: 2008-10-17 23:45
和JM有相同的疑问,假如有下面的数据:
2190717
2190117
2190117
2193117
2191117
这要比较很多组才能判断出正确的前缀和后缀吧?效率很难保证
作者: youxi01 时间: 2008-10-18 00:48
同楼上
个人感觉,在这方面,机器的效率还是比不上人脑的
作者: batman 时间: 2008-10-18 11:31
我觉得楼主的意思还是表明清楚了,这个每行的前缀和后缀也是能通过程度自动判断出来
的,但用纯批处理来完成这样一个过程必定存在效率问题,因为用批肯定是要进行逐字符
判断的,当遇到大型的文本时,这样的处理将会慢得不可形容。所以,这样的题目其实际
价值并不会太大。。。
作者: namejm 时间: 2008-10-18 12:43
楼主的意思并没有表明清楚,因为楼主并没有说清楚什么样的字符串才算前缀,什么样的字符串才算后缀,既然前缀后缀的含义都没有交代清楚,又怎么能让程序判断哪些是前缀哪些是后缀呢——楼主已经注明了,219和17仅仅是举例,它们是未知的,是需要通过程序来判断,这是问题的关键。
作者: wxcute 时间: 2008-10-18 15:16 标题: 据pusofalse四楼代码而改
- @echo off
- setlocal enabledelayedexpansion
- call :loop n-1 fx
- call :loop -n lx
- set/a fx=fx,lx=lx+1
- for /f "delims=" %%i in (1.txt) do (
- set "var=%%i"
- echo !var:~%fx%,%lx%!
- )
- pause
- goto :eof
- :loop
- set/a n+=1
- set/a m=%1
- for /f "delims=" %%a in (1.txt) do (
- set "var=%%a"
- if not "!str!"=="" if not "!str:~%m%,1!"=="!var:~%m%,1!" set "%2=%m%"
- set "str=%%a"
- )
- if not defined %2 goto loop
- set n=
复制代码
作者: batman 时间: 2008-10-18 17:52
原帖由 namejm 于 2008-10-18 12:43 发表
楼主的意思并没有表明清楚,因为楼主并没有说清楚什么样的字符串才算前缀,什么样的字符串才算后缀,既然前缀后缀的含义都没有交代清楚,又怎么能让程序判断哪些是前缀哪些是后缀呢——楼主已经注明了,219和17仅 ...
我理解的就是,文本每行前面和后面都包含有的字符串就是前缀和后缀。
作者: rat 时间: 2008-10-18 21:59
-
- @echo off && setlocal enabledelayedexpansion
- call :i l +
- call :i r -
- set /a r+=1
- for /f %%a in (1.txt) do set "v=%%a" && echo !v:~%l%,%r%!>>2.txt
- goto :eof
-
- :i
- set "?=%2"
- set "s="
- if "%?%"=="+" (set i=0) else (set i=-1)
- :repeat
- for /f %%a in (1.txt) do set "v=%%a" && set "s=!s!!v:~%i%,1!"
- set "v=!v:~%i%,1!"
- set "s=!s:%v%=!"
- if not defined s (set /a i%?%=1 && goto repeat) else (set %1=%i%)
复制代码
作者: flyinspace 时间: 2008-10-19 12:17
我的思路是这样的。
假设有1000组数据。。
任意取两个数据进行比较,取相同的数据作为参考量。
假设 2910117
2910217
这两个数据,就取到了 2910 这个参考。
然后进行一次 Findstr /r "^2910" 的输出查找,看找到的数据量是否有1000条。
若不满足1000条,则取 291 查找,看是否有1000条。直到满足
或者
一个一个的向后取值
例如 findstr /r "^2" 直到不满足条件为止。。
不过,我发现你们的代码可能更适合一些了 。。
继续研究一下,看是否有BUG呢。
作者: everest79 时间: 2008-10-20 03:50
得到前辍使用sort +n来识别
sort +1 & sort +2 & sort +3
作者: lovelymorning 时间: 2008-11-1 19:18
原帖由 flyinspace 于 2008-10-19 12:17 发表
我的思路是这样的。
假设有1000组数据。。
任意取两个数据进行比较,取相同的数据作为参考量。
假设 2910117
2910217
这两个数据,就取到了 2910 这个参考。
然后进行一次 Findstr /r "^2910" ...
按照您这个思路,干脆叫cmd去跳楼吧。。。
这么比较,都不知要花费多少时间在这里面。。。何况比到最后,都不一定能比出个结果。。。就算有结果了。。。也不一定正确。。。
作者: lorn1234 时间: 2009-1-11 14:53
原帖由 batman 于 2008-10-17 16:56 发表
写了个删除前缀的(后缀亦然),效率不怎么高:@echo off&setlocal enabledelayedexpansion
set /p str=nul
有点问题,把生成的1.txt取反后得到的结果有BUG,对这行7171912 删前缀得到的结果是912
[ 本帖最后由 lorn1234 于 2009-1-12 00:55 编辑 ]
作者: netbenton 时间: 2009-4-21 00:36
用sort 排序一次后,只需比较第一条和最后一条记录即可得出前缀了。
=========================
set /p one=<a.txt
...测串长
for /f "delims=" %%a in (a.txt) do (set str=%%a
set f1=!str:~1,1!
set f2=!str:~2,1!
set f3=!str:~3,1!
...根据串长动态生成行数,变%var1%代替代码行
set r1=!str:~-1!
set r2=!str:~-2!
set r3=!str:~-3!
...
)
最后再与第一条记录的比较就可以得到前后缀了。
作者: netbenton 时间: 2009-4-22 13:43 标题: 做出来了
- @echo off
- set $=!
- setlocal enabledelayedexpansion
- (for /l %%i in (1,1,100) do echo 219%%i17)>%~n0.txt
- set /p var=<%~n0.txt
- set com=
- set bom=
- for /l %%a in (0,1,32) do (
- set "bom=!bom!&set #b%%a!$!str:~-%%a,1!$!=!$!str:~-%%a,1!$!"
- if "!var:~%%a,1!"=="" goto :scok
- set "com=!com!&set #c%%a!$!str:~%%a,1!$!=!$!str:~%%a,1!$!"
- )
- :scok
- set com=!com:~1!
- set bom=!bom:~1!
- set "bom=!bom:*&=!"
-
- for /f %%i in (%~n0.txt) do (set str=%%i
- %com%
- %bom%
- )
- set var=
- set tou=
- for /f "tokens=1,2 delims==" %%a in ('set #c') do (set str=%%a
- if "!str:~2,1!"=="!var!" goto :oktou
- set tou=!tou!%%b
- set var=!str:~2,1!
- )
- :oktou
- set wei=
- set var=
- for /f "tokens=1,2 delims==" %%a in ('set #b') do (set str=%%a
- if "!str:~2,1!"=="!var!" goto :okwei
- set wei=%%b!wei!
- set var=!str:~2,1!
- )
- :okwei
- echo %tou:~,-1% %wei:~1%
- pause
复制代码
[ 本帖最后由 netbenton 于 2009-4-22 18:25 编辑 ]
作者: 随风 时间: 2009-4-22 14:17 标题: 回复 24楼 的帖子
Q:所发代码不止一行时请用 code 把代码扩起来
A:如何用code把代码扩起来 ,请点我。
未细看你的代码,但若你是按22楼所说的思路来解的话,可能有考虑不周的地方。
楼主题意描述不清,我们假设所谓的 前缀和后缀 是指所有行都有的特征。
如果你sort排序后得到的第一行和最后一行分别是以下两行,能得到正确结果吗?
假设前缀为 1234
后缀为 4321
sort排序后
第一行为 1234555674321
最后一行为 12345556743214321
作者: netbenton 时间: 2009-4-22 18:42
回版主:
不好意思,偶知道怎么加code,只是回贴时,粘贴后就马上点发表了,没注意,谢谢提醒。
以后一定注意。
偶在22楼是没有表达得清楚,并且有很大错误,不好意思。
其实是想说:
方法一,sort后可以对比前后行仅仅得出前缀。后缀没有解决。(发现确实不行)
方法二,(24楼代码)则可以分别得出前、后缀,并且速度还可以。(可行,但与22楼表达的有点不同)
完整代码如下(文本文件名与批处理文件名关联了,1000行记录3秒内完成替换):
-
- @echo off
- set $=!
- setlocal enabledelayedexpansion
- (for /l %%i in (1,1,1000) do echo 219%%i17)>%~n0.txt
- set /p var=<%~n0.txt
- set com=
- set bom=
- for /l %%a in (0,1,32) do (
- set "bom=!bom!&set #b%%a!$!str:~-%%a,1!$!=!$!str:~-%%a,1!$!"
- if "!var:~%%a,1!"=="" goto :scok
- set "com=!com!&set #c%%a!$!str:~%%a,1!$!=!$!str:~%%a,1!$!"
- )
- :scok
- set com=!com:~1!
- set bom=!bom:~1!
- set "bom=!bom:*&=!"
- for /f %%i in (%~n0.txt) do (set str=%%i
- %com%
- %bom%
- )
- set var=
- set tou=
- for /f "tokens=1,2 delims==" %%a in ('set #c') do (set str=%%a
- if "!str:~2,1!"=="!var!" goto :oktou
- set tou=!tou!%%b
- set var=!str:~2,1!
- )
- :oktou
- set wei=
- set var=
- for /f "tokens=1,2 delims==" %%a in ('set #b') do (set str=%%a
- if "!str:~2,1!"=="!var!" goto :okwei
- set wei=%%b!wei!
- set var=!str:~2,1!
- )
- :okwei
- set tou=%tou:~,-1%&set wei=%wei:~1%
- ::前面的找前后缀,后面的进行替换
- (for /f %%i in (%~n0.txt) do (set str=#%%i#
- set str=!str:#%tou%=!
- echo !str:%wei%#=!
- ))>%~n0dest.txt
- start %~n0dest.txt
- pause
复制代码
[ 本帖最后由 netbenton 于 2009-4-22 19:03 编辑 ]
作者: 随风 时间: 2009-4-22 19:22 标题: 回复 26楼 的帖子
能把思路说说吗?看代码太累了!
作者: netbenton 时间: 2009-4-22 22:37
根据第一行的长度,取得动态代码行:
内容为:set #c0!str:~0,1!=!str:~0,1!&set #c1!str:~1,1!=!str:~1,1! ...
%com%=从串首开始
%bom%=从串尾开始
变量定义规则: #c+列号+字符=字符
这样会根据各列字符,动态定义变量,如果同一列有不同字符,则会定义多个变量,否则只有一个
for +set 最后判断同一列是否有二个以上变量,即可知道是否为前/后缀结束
[ 本帖最后由 netbenton 于 2009-4-22 22:43 编辑 ]
作者: 基拉freedom 时间: 2009-7-13 14:58
恩
这个有点像在许多字符串中找到相同的字符串~
作者: Seter 时间: 2009-8-16 09:00
为什么我还是没看懂题目...
既然是自动截开头,,那么219开头也可以被认为21开头啊..
作者: caruko 时间: 2009-12-7 17:48
sort 之后,第一行与最后一行,对比分析,应该可以得到前缀吧
后缀的话,开始是想,二进制后几位也相同,用>> 移位,然后 mod 2 , 如果移位后,最后一位都是0或者1,那么MOD值也相同,如果有0有1,那么MOD值就不同,然后根据移位的位数,来分析后缀。
测试了下,咳..数字运算只能支持2^32,数字过长就没办法了..
只能当作字符串测试了,检查 %str:~-n+1,-n% 是不是相同了..效率估计不高
[ 本帖最后由 caruko 于 2009-12-8 11:41 编辑 ]
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |