请教一个通用算法(50分)

  • 主题发起人 主题发起人 xf163
  • 开始时间 开始时间
X

xf163

Unregistered / Unconfirmed
GUEST, unregistred user!
一个字符串,(位数可以不固定,假设为N位(N<20)),其每位可能取值范围可以自行规定.
(类似10进制,逢9进1,十六进制逢F进1,现可以自由定义取值范围)
现假设字符串为13位,可能取值有0..9,A..Z.(遇9变A,遇Z则进一位)
求一算法,假设字串初始值为'ABCD000000WXS',问'ABCD0000000WXS'+1000的值是多少?
 
从问题上看
1、你是想计算上述字符串的用十进制表示的结果
2、加数1000是十进制的数
如果想计算它,可以参考我们计算十进制的方法(你的进制是36进制吧)
比如有10进制数为 123456 它实际上的计算方法为:
1X10^5 + 2X10^4 + 3X10^3 + 4X10^2 + 5X10^1 + 6 = 123456
方法归纳为
m
 --------
/
/ N X (M^n)
/
/
-----
n = 0
其中 N 为你的字符串中的数字
   M 为你的进制数(比如你的例子,应该是36进制吧)
   n 为当前数字的位置(从0开始算起)
   m 最高位数字的位置
以上不知我的理解是否对路?
 
对于这个特例可以这样理解,我想用递归去做这样的一个函数,实现通用性,其中字符长度和可能取值希望用变量带入(这样才有通用性),但我不会做这样的递归函数.
 
对了,ABCD0000000WXS+1000 得出的数是字符传还是36进制的数。??
 
还有你这里是加1000 是否还可以加ABCEDLL2009这样的字符串。
 
返回值当然是字符串.简单起见,可以只加数字.当然也支持加字符.
 
看看我做的,不是通用的,但是只要你改变里面的变量,诸如数组的长度定义变成函数参数就可以变成通用的。  给分。。。
var a,b,c:string;
i,j:integer;
arint,brint,crint:array of integer;
//ABCD0000000WXS+1000
begin

b:='ABCD8888888WXS';
c:='1000';
SetLength(arint,14);
SetLength(brint,4);
SetLength(crint,14);
for i:=0 to length(b)-1do
begin
if (byte(b[i+1])<58) and (byte(b[i+1])>47) then
arint:=strtoint(b[i+1])
else
arint:=byte(b[i+1])-55;
end;

for i:=0 to length(c)-1do
begin
if (byte(c[i+1])<58) and (byte(c[i+1])>47) then
brint:=strtoint(c[i+1])
else
brint:=byte(c[i+1])-55;
end;

if length(b)>length(c) then
begin
j:=0;
for i:=length(b)-1do
wnto 0 do
begin
if i>(length(b)-length(c)-1) then
begin
if J+brint[i-10]+arint<36 then
begin
crint:=brint[i-10]+arint+j;
j:=0;
end
else
begin
crint:=brint[i-10]+arint+j-36;
j:=1;
end;
end
else
crint:=j+arint;
end;
// if brint[1]>35 then
brint 没有考虑最高位进位
end
else
begin
// change
end;
Memo1.Lines.Clear;
for i:=0 to length(crint)-1do
Memo1.Lines.Add(inttostr(crint));
a:='';
for i:=0 to length(crint)-1do
begin
if (crint>=0) and (crint<=9) then
a:=a+inttostr(crint) // inttostr
else
a:=a+chr(crint+55);
end;
Memo1.Lines.Add(a);
end;
 
感谢:duhai_lee:
但你将'ABCD8888888WXS'+1000=‘ABCD8888889WXS’是错的。
(可用字符有0-9,A-Z)。当然你的程序改一下算 将'ABCD8888888WXS'+1000是没问题的。
我的初衷是: ‘ABCD8888888WXS’+1=ABCD8888888WXT
+2=ABCD8888888WXU
+8=ABCD8888888WY0

也许我没能说清楚,我要的是类似i=i+1(因为默认是十进制,我们不需要设计算法去算它,但现在进制变了,如何用一个通用的算法去实现。)的问题。就算是十进制,也应该有个算法的。
有点像:
Func addString(.....):string;
var A,B,c_string:string;
i:integer;
begin

c_string:='ABCD000000WXS';
--此变量应该由调用函数时带入
i:=13;--最右边一位现在是13,也应该是调用函数时带入
A :=copy(c_string,1,i-1);
B:=copy(c_string,i,1);
B=B+1
if B in('0..9','A..Z')
then
c_string:=A+B
else
begin
....
这里应该可以递归调用Func addstring(....) 函数
我就不会写了。。。。。(烦指点)
end;


 
因为:‘ABCD8888888WXS’+1=ABCD8888888WXT
+2=ABCD8888888WXU
+8=ABCD8888888WY0
所以:
'ABCD8888888WXS'+1000=‘ABCD8888889WXS’
不对吗???为什么错了???????
那'ABCD8888888WXS'+10=‘ABCD8888889WYS’????????对吗?
 
你是不是想穷举别人的密码啊?
我有个程序支持xf163的需求:
不过我没有把数字和字母合在一起,字母是一个函数,数字也是一个函数。如
‘ABCD8888888WXS’+1=ABCD8888888WXT
+2=ABCD8888888WXU
+8<>ABCD8888888WY0(不是0)而是ABCD8888888WYA
可以自己定义需要加多少。
 
穷举密码?呵呵,同志们想到哪去了!我是看到一个软件的一个字段(主键PK值),采用了这种算法,我自己二次开发的外挂程序想和他的PK值保持一致。所以需要研究其算法……否则我就不敢往他的表里加数据了(要是Pk值重复了就不好玩了)
DuHai_lee的算法成了字符串相加,我要的是这个递归函数和运算1000遍后的结果……应该是我没说清楚,不怪Duhai_lee. 分我会给的。不够我还可以加。
 
我已找到其算法的调用接口了,谢谢各位。
 
后退
顶部