记一道有趣的算法题

191 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情

我正在参加 码上掘金体验活动,详情:show出你的创意代码块

前言

今天一个朋友问我这样一道算法题,感觉还挺有趣,在此记录一下。

描述

现有一本密码本,第一位是1,第二位是2,第三位是4,从第四位开始,每位都是其前三位之和,密码本的长度最大为50。现在输入n段字符,请将字符加密(当前字母对应密码本位数,右移该位数的值,即为加密)后返回。 例:abc =》 bdg

分析

首先我们可以确定,密码本遵循斐波那契数列,并且是有限的。所以第一步,我们需要将密码本创建出来。 接下来,最重要的一点就是偏移字母了,z右移又会从a开始,以此找规律,我们会得到偏移的关键公式:偏移结果=97+(当前数字ASCII+偏移值-97)%26

97a122z
123a148z
149a174z

接下来就是具体编码实现了:

//创建密码本
const fib = [1,2,4]
for(let i = 3;i < 50;i++){
  fib[i] = fib[i-1] + fib[i-2] + fib[i-3]
}
function encrypt(n,...data) {
  //n 为需要加密的字段数
  //data 数组存储需要加密的详细字段
  
  //定义结果数组
  const result = []
  //循环加密,直至最后一段
  while(n > 0){
    //定义一个数组变量辅助我们存储加密的字符串
    let str = []
    //对传进来的字段从后往前开始加密,遍历字段的每个字符串,将加密之后的结果存储到str数组中
    for(let i = 0;i < data[n-1].length;i++){
      //套用公式加密
      str.push(String.fromCharCode(97 +( data[n-1][i].charCodeAt()+fib[i]-97)%26))
    }
    //结果数组从头部添加 加密之后的数组,调用join转为字符串
    result.unshift(str.join(''))
    //n-1,一段密文已经加密结束
    n--
  }
  //当所有密文加密结束后,返回结果数组
  return result
}
console.log(encrypt(3,'abc','zdcaaw','saygsdyag'));//[ 'bdg', 'afghnu', 'tccnfbqdz' ]

总结

本篇文章记录了一道有趣的算法,并做了简单实现,但是,还有部分瑕疵。例如:没处理空字符串的情况,或者需要加密的字段中间有空等情况。各位看官有兴趣可自行完善,并优化。