Look-and-See (边看边说) 数列具有好玩儿而神秘的特性,本文简要介绍它和它衍生出来的康威常数。

沿革

1977年7月1-13日,国际奥林匹克数学竞赛在前南斯拉夫首都贝尔格莱德举行,赛间,荷兰队非正式地给英国队出了个难题(其实类似脑筋急转弯),大致是这样的:

1,11,21,1211,111221

上述数列的下一项是什么呢?

英国队未予答复...

故事并没有结束,后来,在剑桥大学执教的著名数学家约翰·霍顿·康威(John·Horton·Conway)从他的学生那儿拿到了这道题,他发现了其中的奥秘,并对它进行了分析和传播。

康威在1986年去普林斯顿大学接任了著名的约翰·冯·诺依曼(John von Neumann)教授的位子,继续教书。

特征

给定种子数 d (种子数在0到9之间,非1), 那么,该数列就可以具体化为:

d,1d,111d,311d,13211d,111312211d,31131122211d,…

如果种子数是1, 具体化后的数列就是本文开头的那个数列了。

如果种子数是22,那么,具体化后的数列的每一项的每个数字,都是2,并且每一项都是22。

当种子数不是22 时, 具体化后的数列的各项是依次增长的。


增长率

种子数不为22时,此数列的后项与前项比有极限,这个极限被称为康威常数,常用λ 表示。

λ ≈ 1.303577269034296391257099112152551890730702504659404875754861390628550...

我想知道:这里应该有图片,可是为什么51CTO的图片上传的“确认”按钮点了没效果呢?

由于无法上传,请查看我创建的百度词条“Look-and-say 数列” 中的配图.

(上图截取自维基百科: Look-and-say sequence , 我在百度百科为这个词建立了词条,感兴趣的可以去看下)

上图中的四条曲线各自是一个 Look-and-say 数列的图示: 红色的种子数是23,蓝色的是1,紫色的是13,绿色的是312。

随着 x 轴方向的变量不断变大,各个曲线的斜率趋向统一,极限值就是康威常数( Conway Constant )。

用途

看起来是无用之用的一个脑筋急转弯性质的数列,但康威却给出了不同的回答。

康威基于这个数列建立了 Cosmological theorem,解释了宇宙衰变(Cosmological decay),用这个数列解释了化学元素衰变和相对原子质量之间的关系。

实现

多种编程语言均可实现这个数列,现在我给出该数列在几种编程语言中的实现:

JavaScript 实现1

/*nodelas.js*/functionlookAndSay(str){returnstr.replace(/(.)\1*/g,function(seq,p1){returnseq.length.toString()+p1})}varnum="1";for(vari=10;i>0;i--){console.log(num);num=lookAndSay(num);}

JavaScript 实现2:

/**@Author:suifengtec*@Date:2017-08-2203:45:05*@LastModifiedby:suifengtec*@LastModifiedtime:2017-08-2203:51:02*//*nodelas1.js*/functionlookAndSay(digits){varresult='',chars=(digits+'').split(''),lastChar=chars[0],times=0;chars.forEach(function(nextChar){if(nextChar===lastChar){times++;}else{result+=(times+'')+lastChar;lastChar=nextChar;times=1;}});returnresult;}(functionoutput(seed,iterations){for(vari=0;i<iterations;i++){console.log(seed);seed=lookAndSay(seed);}})("1",10);

Lua语言的实现:

--@Author:suifengtec--@Date:2017-08-2203:51:07--@LastModifiedby:'suifengtec'--@LastModifiedtime:2017-08-2203:56:18--aluaimplementofthelook-and-saysequence--lualas.luafunctionlookAndSay(n)localt={1}returnfunction()localret={}fori,vinipairs(t)doift[i-1]andv==t[i-1]thenret[#ret-1]=ret[#ret-1]+1elseret[#ret+1]=1ret[#ret+1]=vendendt=retn=n-1ifn>0thenreturntable.concat(ret)endendendforiinlookAndSay(10)doprint(i)end

PHP 实现:

<?php/***@Author:suifengtec*@Date:2017-08-2203:57:46*@LastModifiedby:'suifengtec'*@LastModifiedtime:2017-08-2203:59:52*//*php-S127.0.0.1:9988http://127.0.0.1:9988/las.php*/functionlookAndSay($str){returnpreg_replace_callback('#(.)\1*#',function($matches){returnstrlen($matches[0]).$matches[1];},$str);}$num='1';foreach(range(1,10)as$i){echo$num.'<br/>';$num=lookAndSay($num);}

Python 实现:

#-*-coding:utf-8-*-#@Author:suifengtec#@Date:2017-08-2204:00:59#@LastModifiedby:'suifengtec'#@LastModifiedtime:2017-08-2204:02:27##LookandSay数列的Python实现#pythonlas.py#deflookAndSay(number):result=""repeat=number[0]number=number[1:]+""times=1foractualinnumber:ifactual!=repeat:result+=str(times)+repeattimes=1repeat=actualelse:times+=1returnresultnum="1"foriinrange(10):print(num)num=lookAndSay(num)


Rust 中的实现:

/*rustc-ors.exelas.rs&&rs*/fnlas(in_seq:&[i8])->Vec<i8>{assert!(!in_seq.is_empty());letmutresult=Vec::new();letmutcurrent_number=in_seq[0];letmutcurrent_runlength=1;foriin&in_seq[1..]{ifcurrent_number==*i{current_runlength+=1;}else{result.push(current_runlength);result.push(current_number);current_runlength=1;current_number=*i;}}result.push(current_runlength);result.push(current_number);result}fnmain(){letmutseq=vec![1];foriin0..10{println!("{}=>{:?}",i,seq);seq=las(&seq);}}

Go 语言的实现:

/**@Author:coolwp.com*@Date:2017-08-2201:55:09*@LastModifiedby:suifengtec*@LastModifiedtime:2017-08-2202:37:27**/packagemainimport("fmt""math""strconv""strings")//获取以1为种子数的Look-and-say数列任意位置的数字funcgetNumberOfLookAndSaySequeceSeed1(positionint)int{ifposition==1{return1}ifposition==2{return11}str:="11"fori:=3;i<=position;i++{str+="$"length:=len(str)tmp:=""cnt:=1forj:=1;j<length;j++{strSlice:=strings.Split(str,"")ifstrSlice[j]!=strSlice[j-1]{cntTmp:=strconv.Itoa(cnt)tmp+=cntTmptmp+=strSlice[j-1]cnt=1}else{cnt++}}str=tmp}v,err:=strconv.Atoi(str)//v,err:=strconv.ParseInt(str,10,64)iferr!=nil{return-1}ifv>math.MaxInt32{return-1}returnv}//给定任意种子数seed,获取LookAndSay数列的第position项funcgetNumberOfLookAndSaySequece(seedint,positionint)int{ifseed==22{return22}ifposition==1{returnseed}seedStr:=strconv.Itoa(seed)str:="2"+seedStrifposition==2{v,err:=strconv.Atoi(str)iferr!=nil{return-1}ifv>math.MaxInt32{return-1}returnv}fori:=3;i<position;i++{str+="$"length:=len(str)tmp:=""cnt:=1forj:=1;j<length;j++{strSlice:=strings.Split(str,"")ifstrSlice[j]!=strSlice[j-1]{cntTmp:=strconv.Itoa(cnt)tmp+=cntTmptmp+=strSlice[j-1]cnt=1}else{cnt++}}str=tmp}r,err:=strconv.Atoi(str)iferr!=nil{return-1}ifr>math.MaxInt32{return-1}returnr}funcmain(){position:=5a:=getNumberOfLookAndSaySequeceSeed1(position)seed:=1pos:=5b:=getNumberOfLookAndSaySequece(seed,pos)fmt.Println(a)fmt.Println(b)}

PS: 由于这个 js 不支持 Go 语言代码高亮,并且缩进也显示有问题, 所以请在粘贴后执行 go fmt。

结论

有一种声音认为:宇宙是一个程序,这个数列和康威常数用数字支持了这种说法。


本文首发酷威普和51CTO,转载需注明。