NBR-hugh / freecodecamp-practice

Practice everyday
0 stars 0 forks source link

FCC:Basic Algorithm Scripting (50 hours) #18

Open NBR-hugh opened 8 years ago

NBR-hugh commented 8 years ago

16个小任务:

Get Set for our Algorithm Challenges Complete

Reverse a String Incomplete   * 完整反向一个字符串 17min

Factorialize a Number Incomplete   * 数的阶乘 1h40min

Check for Palindromes Incomplete   * 检查回文 2h23min

Find the Longest Word in a String Incomplete   * 寻找一个字符串中最长的单词 35min

Title Case a Sentence Incomplete   * 2h45min

Return Largest Numbers in Arrays Incomplete   * 返回数组中的最大值 45min

Confirm the Ending Incomplete   *确定结尾? 30min

Repeat a string repeat a string Incomplete   *重复字符串 10min

Truncate a string Incomplete   *缩短字符 40min

Chunky Monkey Incomplete   *矮胖的猴子 30min

Slasher Flick Incomplete   *惊悚电影 5min

Mutations Incomplete   *突变 33min

Falsy Bouncer Incomplete   * 27min

Seek and Destroy Incomplete   *寻找并且破坏 1h15min

Where do I belong Incomplete   *我属于哪里 23min

Caesars Cipher Incomplete   *凯撒密码 2h10min

NBR-hugh commented 8 years ago

预计3天完成,平均每天5个 BEGING

NBR-hugh commented 8 years ago

Reverse a String Incomplete   * 完整反向一个字符串

分析

程序

function reverseString(str) {
  var arr = [];
  var newarr=[];
  var newString;
  arr = str.split('');
  newarr = arr.reverse();
    newString = newarr.join('');
  return newString;
}
}

reverseString("hello");
NBR-hugh commented 8 years ago

Factorialize a Number 数字的阶乘

分析

输入数字n>>得到从1到n的整数>>得到这些整数的积 var >> ? >>reduce(*)

难点在于:如何从n得到从1到n的整数数列?

方案一:

  var arr=[];
function factorialize(num) {
  for (var i=num;i>0;i--){
    arr.push(i);
  }
var singleVal = arr.reduce(function(previousVla,currentVla){
  return previousVla * currentVla;
},1);
}

无法得出结果,进行测试,发现整数数组可以得出,但是连乘有问题

转换问题:问题出在哪里?如何实现连乘?

方案1:采用reduce

  var result=arr.reduce(function(a,b){
    return a+b;
  },0);

方案2:采用for循环实现连乘

 for(var j=num-1;j>=0;j--){
    result *= arr[j];
 } 

因此,我以为要三个一起输出: image

结果…… image 然后我就崩溃了…… 没道理5,10可以,20 不行呀,看了代码三遍,还是看不出问题,只能请求搜索与帮助……help!!!

———————————————————————————————————— find the answer on forum 这位网友的答案: image 因此,问题的症结在于var arr=[];的位置,将其放入function内便通过挑战

function factorialize(num) {
   var arr=[];
    var result = 1;
  for (var i=num;i>0;i--){
    arr.push(i);
  }
  for (var j=num-1;j>=0;j--){
    result *= arr[j];
 } 
 return result;
}

factorialize(5);

反省

  1. 设置变量时要注意适用范围,是局部还是全局,否则回出现奇诡的问题;
  2. 这里出项了框架效应,想着怎么能把数组用上,但其实直接用for循环累乘即可解决问题;

遗留问题

为什么reduce无法使用?

NBR-hugh commented 8 years ago

Check for Palindromes 检查回文

要求:

  1. Return true if the given string is a palindrome. Otherwise, return false.【是回文true,不是false】
  2. remove all non-alphanumeric characters (punctuation, spaces and symbols)【除去标点,空格,符号】
  3. turn everything lower case in order to check for palindromes.【将所有都变成小写来检查回文】

<-- 以下混乱区域,开始时混乱思绪

分析

!-->

方案

但是依然没用,array1与2还有3都是反的,是因为js是动态语言,=是双向的而非单向的?陷入困境

 var exp = /[a-z]/gi;
  var array2=str.match(exp);
  var str1=array2.join('');
  var array3=array2.reverse();
  var str2=array3.join('');

解决方案2数组均变的问题,或者数组无法进行==的比较? 但是出现新问题:大小写忘记转化了 所以,如何实现将所有字母转化成小写?

var exp = /[a-z]/gi;
  var array2=str.match(exp);
  var str1=array2.join('');
  str1 = str1.toLowerCase();
  var array3=array2.reverse();
  var str2=array3.join('');
  str2 = str2.toLowerCase();

 if (str1===str2){
    return true;
  }else { return false;}

采用.toLowerCase()输出小写,终于大部分搞定,剩下2个问题: image 发现也要考虑数字,就在[a-z]中加入[a-10-9],然后就通过了……

total:2h23min

反省

遗留问题

NBR-hugh commented 8 years ago

Find the Longest Word in a String   寻找句子中最长单词的长度

要求

  1. 结果是一个数字
  2. 最长单词的长度

功能分析

  1. 将句子转变成以单词为元素的数组
  2. 表达单词元素的长度,
  3. 将字符数组转化为字长数字数组
  4. 对长度大小进行比较
  5. 比较要历遍整个数组

开始解决

方案1

function findLongestWord(str) {
  var arr=str.split(' '); //将句子变成单词元素的数组
  var arr1= arr.map(function(str){  //将单词元素的数组变为字长的数字数组
    return str.length;       
  });
   var arr2=arr1.sort(function(a,b){ //将字长数字元素从大到小排列
     return b-a;
   });

  var result=arr2[0]; //取数组第一个即最大的数字

  return result; //结束函数,得出结果
}

findLongestWord("The quick brown fox jumped over the lazy dog");

扩展问题

假如要输出最大字长对应的单词呢?

NBR-hugh commented 8 years ago

Title Case a Sentence 对一个句子首字母大写

要求

  1. 每个单词首字母大写
  2. 保证每个单词除了首字母以外都是小写

功能分析

  1. 将句子转化成单词单位的数组;
  2. 将每个数组元素的第一个字母变成大写;
  3. 将每个数组元素的除第一个字母之外的字母变成小写;
  4. 将数组转化成句子;

开始解决

功能1,4为老问题,2与3为新问题,其实也是同一串问题: 如何对数组的元素进行编辑?再进一层,假如元素是字符,如何对某一元素的特定位置的字母进行操作,或者是全体元素批量操作?当直到操作的方法时,如何将字母变成大写/小写? 【根据array的标准库有需要面对元素的操作;目前只能是采用循环操作历遍;将单词元素再拆分成字母元素的数组,对首个元素进行操作】

方案1

function titleCase(str) {
 var arr=str.split(' '); //将句子转化成单词单位的数组
  var arr2;
  var str3;

  var test=arr.map(function(str2){  // 用map对每个元素再拆分成数组,对第一个元素进行大写
     arr2=str.split('');
   arr2[2]=arr2[2].toUpperCase();
     str3=arr2.join('');
 });
  return arr2;
}

返回结果为 image 失败原因:再第二层拆分的结果都变成一个数组了,并没有形成我想象中数组套数组的形式,因此map不可用,在尝试循环结构;

方案2

function titleCase(str) {
 var arr=str.split(' '); //将句子转化成单词单位的数组
 var arr1;

  for(i=arr.length-1;i>=0;i--){ 
     arr1=arr[i].split('');   //arr1=arr[4].split=["p","o","t"]

     arr1[0]=arr1[0].toUpperCase();//第一位大写 arr1[4]=["P","o","t"]
    for(j=arr1.lenth-1;i>0;i--){    //从最高到第二位小写 arr1[4]=["P","o","t"]
      arr1[j]=arr1[j].toLowerCase();

    }

     arr[i]=arr1.join('');            // arr[4]="Pot"
  }

  return arr2;
}

titleCase("I'm a little tea pot");

返回结果: image

发现方案二出错原因,toLowerCase是对字符串的操作,不是对数组元素的操作,或许可以直接在将句子拆分成数组之前就转化成全部小写,然后再执行首字母大写的操作?试试方案三

方案三

方案三的思路是直接对字符串进行操作,但全部转化成小写没问题,首字母大写无法对字符串进行操作,因为字符串的方括号表达只能读不能写,要修改还是得转化成数组

function titleCase(str) {
   var str1=str.toLowerCase(); 
   var arr1=str1.split(' '); 
    for (var i=arr1.length-1;i>=0;i--){
     var arr2=arr1[i].split('');  //将每个单词分成字母元素的数组 arr2=["h","e","r","e"]
      arr2[i]=arr2[i].toUpperCase();  // 将这个单词的字母元素数组首位变成大写arr2=["H","e","r","e"]
      arr1[i]=arr2.join('');   //将字母元素组成的单词数组连成原来句子数组的单词元素 arr[0]="Here"
    }
      str1=arr1.join(' ');  //将每个首字母大写的单词连成句子
  return arr1;
}

titleCase("HERE IS MY HANDLE HERE IS MY SPOUT");

错误提示类型错误,当i=0时here变成Here成功,添加循环就出现问题,提示类型错误,于是删除循环,以i=1测试,发现is 变成iS,于是明白变量设置错误,将 arr2[i]=arr2[i].toUpperCase();变为 arr2[0]=arr2[0].toUpperCase();就通过挑战,正确的代码如下:

function titleCase(str) {
   var str1=str.toLowerCase();   //所有字符串变成小写
   var arr1=str1.split(' ');    // 将句子划分成以单词为元素的句子数组
   for (var i=arr1.length-1;i>=0;i--){  //对每个单词元素执行首字母大写的循环操作,直到所有单词都首字母大写
     var arr2=arr1[i].split('');  //将每个单词分成字母元素的数组 arr2=["h","e","r","e"]
      arr2[0]=arr2[0].toUpperCase();  // 将这个单词的字母元素数组首位变成大写arr2=["H","e","r","e"]
      arr1[i]=arr2.join('');   //将字母元素组成的单词数组连成原来句子数组的单词元素 arr[0]="Here"
   }
      str1=arr1.join(' ');  //将每个首字母大写的单词连成句子
  return str1; 
}

titleCase("HERE IS MY HANDLE HERE IS MY SPOUT");

total:2h45min

反省总结:

  1. 标准库的.join()等方法无法发挥作用时,很大一部分原因是()没有加,或是()内的变量设置出错,还要多多熟悉;
  2. 心浮气躁是大忌,抱着一定可以解决问题的必胜信念,在思路清晰的情况下对所有可能进行尝试与记录,记录看似多花时间,却比放在脑子更加可靠,可靠的一点点推进优于不可靠的往复无谓的脑子尝试;
NBR-hugh commented 8 years ago

Return Largest Numbers in Arrays 返回数组中最大值

要求

  1. Return an array consisting of the largest number from each provided sub-array. 【即返回一个由每个次级数组的最大值组成的数组】

功能分析

  1. 选择一个次级数组
  2. 在这个数组中比较大小
  3. 得到这个数组的最大值
  4. 对每个次级数组循环执行相同操作
  5. 得到每个次级数组的最大值,组成一个数组

开始解决

首先,第一个问题,如何实现数组内元素的比较大小? 1.用sort从大到小排列,取第一个; 2.直接用a,b,c三变量的循环比较,a与b比较,留最大值于c;

首先先尝试第一种,拿第一个次级数组做实验:

arr[0]=arr[0].sort(function(a,b){
       return b-a;
    }); 

[4, 5, 1, 3]变成[5,4,3,1],ok; 其次,实现循环

 for (i=arr.length-1;i>=0;i--){

    arr[i]=arr[i].sort(function(a,b){
       return b-a;
    });   

    }

结果: image,ok;

再次,提取每个次级数组的的首个元素,

var max=arr[i][0];
      result.push(max);

result的 结果是最大值的数列,ok;得到方案一;

方案1

function largestOfFour(arr) {
  var result=[];
    for (var i=arr.length-1;i>=0;i--){

    arr[i]=arr[i].sort(function(a,b){
       return b-a;
    });
    var max=arr[i][0];
      result.push(max);
    }
  // You can do this!
  return result;
}

largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]);

但是依然无法通过考验,通过测试发现是元素的顺序不对,提示里是正序,自己的程序运行出来的是倒序,因此修改循环条件,将原来的从 右到左改成从左到右,将for的循环条件从var i=arr.length-1;i>=0;i-- 改成 var i=0;i<=arr.length-1;i++,通过挑战。

通关代码

function largestOfFour(arr) {
  var result=[];
    for (var i=0;i<=arr.length-1;i++){

    arr[i]=arr[i].sort(function(a,b){
       return b-a;
    });
    var max=arr[i][0];
      result.push(max);
    }
  // You can do this!
  return result;
}

largestOfFour([[13, 27, 18, 26], [4, 5, 1, 3], [32, 35, 37, 39], [1000, 1001, 857, 1]]);

反省

  1. 随手贴上参考资料
NBR-hugh commented 8 years ago

Truncate a string 缩短字符

要求

  1. 若是限定字符数大于3,显示限定字符数的字符,并且在后面添加...
  2. 若是小于等于3,依然显示限定字符数的字符,但是不加...

------------------------------- 审题错误,要求2版---------------------------------------

  1. 若num>3且num>=length,输出str
  2. 若num>3且num<length,输出num-3,再cancat“...”
  3. 若num<=3且num>=length,输出 num,再cancat“...”
  4. 若num<=3且num<length,输出num,在cancat“...”

开始解决

根据要求,得到方案1:

方案1

function truncateString(str, num) {
  // Clear out that junk in your trunk
  if (num>3){
    str=str.slice(0,num);
    str=str.concat("...");
  }else{
    str=str.slice(0,num);
  }
  return str;
}

truncateString("A-tisket a-tasket A green and yellow basket", "A-tisket a-tasket A green and yellow basket".length);

发现理解错误,限定字符的数字是包括...的数字,而且字符数大于或者等于句子字长时也不能显示..,修改要求.,根据要求第二版得到方案二

方案2

function truncateString(str, num) {
  // Clear out that junk in your trunk
  if (num>3&&num<str.length){    //若num>3且num<length,输出num-3,再cancat“...”
    str=str.slice(0,num-3);
    str=str.concat("...");
  }else if(num>3&&num>=str.length){   //若num>3且num>=length,输出str
    str=str;
  }else if(num<=3){                   //3. 若num<=3且num>=length,输出 num,再cancat“...”
                                       //4. 若num<=3且num<length,输出num,在cancat“...”
    str=str.slice(0,num);
    str=str.concat("...");
  }
  return str;
}

truncateString("A-tisket a-tasket A green and yellow basket", "A-tisket a-tasket A green and yellow basket".length);

成功

NBR-hugh commented 8 years ago

Repeat a string repeat a string 重复输出字符串

要求

  1. 重复输出给定的字符串num次
  2. 假如num非负数,输出空字符串

功能分析

  1. 假如num>0,重复n次;
  2. 加如num<=0,输出空字符串;

开始解决

根据功能分析直接写出第一个方案,重复n次输出字符串用到这个命令:str.repeat(num);分支用if实现

方案1

function repeatStringNumTimes(str, num) {
  // repeat after me
  if(num>0){
    str=str.repeat(num);
  }else{
    str="";
  }
  return str;
}

repeatStringNumTimes("abc", 3);

成功

NBR-hugh commented 8 years ago

Confirm the Ending 确认结尾

要求

  1. 给出的str的末尾要和target一致输出true,否则输出false; 2.str是句子要末尾的单词一致,是单词要末尾的字母一致;

功能分析

  1. 将字符串以空格划分成数组arr
  2. 如果数组length<=1,则为单词,在用“”分割成数组2,取数组2末尾元素与target对比,判断; 3.如果length>1,则为句子,直接取末尾元素与target对比,判断;

开始解决

根据功能分析,得到方案一

方案一

function confirmEnding(str, target) {
  // "Never give up and good luck will find you."
  var arr=str.split(" ");  //1. 将字符串以空格划分成数组arr
  var arr1;
  var a,b;

  if (arr.length<=1){
     arr1=arr[0].split("");  //2. 如果数组length<=1,则为单词,**在用“”分割成数组2**,取数组2末尾元素
        a=arr1.length;
        b=arr1[a-1];
  }else{                   //3.如果length>1,则为句子,直接取末尾元素
        a=arr.length;
        b=arr[a-1];
  }

  if(b==target){             //末尾元素与target对比,判断;
    return true;
  }else{ return false;}

}

confirmEnding("Open sesame", "same") ;

发现一个不符合: image

那么在句子的分支内还要再做调整,依然要分割出字幕数组2,然后取target的字长的倒数几个字母与target想比较, 后来又想到不用分割,直接slice截取试试是否可行,以此命令实现:b=b.slice(-target.length); 得到方案二: *\ 方案二

function confirmEnding(str, target) {
  // "Never give up and good luck will find you."
  var arr=str.split(" ");  //1. 将字符串以空格划分成数组arr
  var arr1;
  var a,b;

  if (arr.length<=1){
     arr1=arr[0].split("");  //2. 如果数组length<=1,则为单词,**在用“”分割成数组2**,取数组2末尾元素
        a=arr1.length;
        b=arr1[a-1];
  }else{                             //3.如果length>1,则为句子,直接取末尾元素
        a=arr.length;
        b=arr[a-1];               //取末尾元素
        b=b.slice(-target.length);    //截取末尾元素与target等长的字母并返回值
  }

    if(b==target){             //末尾元素与target对比,判断;
    return true;
  }else{ return false;}     

}
confirmEnding("Open sesame", "same") ;

成功

NBR-hugh commented 8 years ago

Chunky Monkey 矮胖的猴子??(不懂这个标题)

要求

1.写一个function实现将目标array 按size的长度分组,并且形成一个二维数组

功能分析

  1. 用slice提取size的新数组,
  2. 将得到的数组push到一个新的空数组
  3. 循环以上过程,在i*size< =arr.length 的情况下
  4. 如果i>arr.length 时,arr(i*size+1)

开始解决

按照功能呢分析,实现3的时候就直接通过挑战了……运气真好…… 程序如下:

function chunkArrayInGroups(arr, size) {
  // Break it up.
  var arr2=[];
  for(var i=0;i*size < arr.length;i++){     //循环
  var arr1=arr.slice(0+i*size,size+i*size);  //将arr用size分开,得到子数组
      arr2.push(arr1);                      //将该子数组push到新数组 
  }
  return arr2;
}

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2);
NBR-hugh commented 8 years ago

Slasher Flick

删除目标位置的所有元素,剩下的元素形成一个新数组,直接slice搞定,太简单了

function slasher(arr, howMany) {
  // it doesn't always pay to be first
    var arr1=arr.slice(howMany);
  return arr1;
}

slasher([1, 2, 3], 2);
NBR-hugh commented 8 years ago

Mutations 突变

功能分析

  1. 将次位数组拆分成一个新数组arr1;
  2. 用arr1首位对arr首位元素执行index,得到一个数a;
  3. 循环动作2,假如a<0,跳出循环;

开始解决

按照功能分析的思路,得到方案1

方案1

function mutation(arr) {
  var arr1=arr[1].split('');            //arr1=["h","e","y"]
  var a;
  for(var i=0;i<=arr1.length-1;i++){    //历遍arr1的每个字母
    a=arr[0].indexOf(arr1[i]);          //判断arr1内字母在arr[0]中的位置,若没有a=-1
    if (a<0){ return false;}            // 如果a=-1<0,那么输出false;
  }

  return true;                          //假如循环结束都没false,那就是true
}

mutation(["hello", "hey"]);

有个致命的问题,没有统一大小写,于是加了2条命令,如果再多,就可以写循环;

方案2


function mutation(arr) {
  arr[0]=arr[0].toLowerCase();          //首位元素小写化
  arr[1]=arr[1].toLowerCase();          //次位元素小写化

  var arr1=arr[1].split('');            //arr1=["h","e","y"]
  var a;
  for(var i=0;i<=arr1.length-1;i++){    //历遍arr1的每个字母
    a=arr[0].indexOf(arr1[i]);          //判断arr1内字母在arr[0]中的位置,若没有a=-1
    if (a<0){ return false;}            // 如果a=-1<0,那么输出false;
  }

  return true;                          //假如循环结束都没false,那就是true
}

mutation(["hello", "hey"]);

完成

NBR-hugh commented 8 years ago

Falsy Bouncer 去除falsy值

要求

1.去除数列里所有的falsy值,这些值包括 false, null, 0, "", undefined, and NaN.

  1. 建议使用•Boolean Objects•Array.prototype.filter()

功能分析

  1. 用Boolean object 判断是否Falsy 值
  2. 根据T/F结果决定改元素是否加入结果数组 2.用filter历遍数组,对原数组每个元素执行该判断

开始解决

只要看懂帮助,此题容易,hint里的建议指令帮了大忙

function bouncer(arr) {
  // Don't show a false ID to this bouncer.
  var arr1=[];                  //设立一个新数组
  arr.filter(function(val){     //用filter设立筛选标准
    var x=Boolean(val);         //判断元素val是否Falsy values,是的话false,不是则true
    if (x===true){              //如果结果为true,将该元素添加到新数组
      arr1.push(val);
    }
  });
  return arr1;
}

bouncer([7, "ate", "", false, 9]);
NBR-hugh commented 8 years ago

Seek and Destroy 寻找并摧毁

要求

  1. 寻找函数第一argument的数组内与后面的argument相同的元素,并且删除;

参考

对filter的实验

 [1, 2, 3, 1, 2, 3].filter(function(val){
      return (val!=2);
    });

输出没有内容,必须赋值才有输出:

 var arr1= [1, 2, 3, 1, 2, 3].filter(function(val){
      return (val!=2);
    });

argument失效解决

function destroyer(arr,v1,v2,v3) { // Remove all the values

var arr1= arr.filter(function(val){ var a=arguments[2]; return (val!=a); });

return arr1; }

destroyer([1, 2, 3, 1, 2, 3], 2, 3);

argument[2]没有反应,将var a;在函数前赋予才有反应,局部变量与全局变量的关系还是没有摸透,下次统一在开头的地方赋予变量;

方案1:

function destroyer(arr) {
  // Remove all the values
  var a;
  var arr1;
  for(var i=1;i< arguments.length;i++){
  a=arguments[i];
  arr1= arr.filter(function(val){
     return (val!=a);
    });
  }
  return arr1;

}

destroyer([1, 2, 3, 1, 2, 3], 2, 3);

但输出的结果是[1,2,1,2],问题出在循环,而也警告function不能包含在loop内,所以更改方案2

方案2

方案2不采用循环,选择直接在判断里并列筛选条件

function destroyer(arr) {
  // Remove all the values
  var a,b,c;
  var arr1;
  a=arguments[1];
  b=arguments[2];
  c=arguments[3];
  arr1= arr.filter(function(val){
     return (val!=a && val!=b && val!=c);
    });

  return arr1;

}

destroyer([1, 2, 3, 1, 2, 3], 2, 3);

成功通过,但是感觉可以再精简一点,所以试试不用赋值a,b,c,直接带入argument,系统报错,推断abc为全局变量,因此可用于新function,但argument为局部变量,直接赋值指的是新function的argument,而不是总函数输入的argument

反省

本来可以半小时做完的项目,又因为陷入死局动弹不得,结果早上起来一看就发现问题的所在,每次陷入死局时请设置思考时限,时限内未完成则描述问题,写下实验思路与卡顿点,先进行下一个;

NBR-hugh commented 8 years ago

Where do I belong 我属于哪里?

要求

  1. 将arr排序
  2. 比较num与arr内的元素,找到大于他的最小元素
  3. 输出该元素的排序后的位置值

功能分析

  1. 输入arr与num
  2. 将arr用sort排序
  3. 将arr内的元素从小到大与num比较,当num>元素时,跳出比较;
  4. 输出这个元素排序后的位置值;

开始解决

首先排序,ok;

 arr=arr.sort(function(a,b){
    return a-b;
  });

其次,用for循环比较,得到方案1

方案1

function getIndexToIns(arr, num) {
  // Find my place in this sorted array

  arr=arr.sort(function(a,b){
    return a-b;
  });
  for(var i=0;i<arr.length;i++){
    if(arr[i]>=num){
      return i;
    }
  }

  return arr;
}

getIndexToIns([5, 3, 20, 3], 5);

但有一个要求没符合,即未考虑到数组内最大值仍然小于num的情况,对比较的条件进行编辑,得到方案2

方案2

function getIndexToIns(arr, num) { // Find my place in this sorted array

arr=arr.sort(function(a,b){ //排序 return a-b; }); for(var i=0;i<arr.length;i++){ //循环历遍arr元素 if( arr[arr.length-1]>=num && arr[i]>=num){ //如果arr最大值大于等于num下某个元素大于num,输出i return i; }else if(arr[arr.length -1]<num){ //如果arr最大值小于num,输出数组长度 return arr.length; } }

return arr; }

getIndexToIns([5, 3, 20, 3], 5);

NBR-hugh commented 8 years ago

Caesars Cipher 凯撒密码(编码与解码)

功能分析

  1. 读懂ROT13的加密原理,一张图足矣: image
  2. 实现一一转化即可
  3. !!! 还要对标点符号实现保留,即只编码大写字母

开始解决

首先想到的方案是将输出slipt成数组,再通过for循环,用switch的in case转化;但看到参考的命令: •String.prototype.charCodeAt() •String.fromCharCode() 都不熟悉,就想学着用看看; 在阮一峰的教程中看到该命令的介绍: image 在结合密码规则可知支付的Unicode码点有此对应关系:output=input+13;因此得到方案1

方案一

思路是将字符转化成码数,再进行+13,再将码数转化成字符输出,但遇到困难,str.charCodeAt(4);参数只能一个个转化,不能一整歌字符串转化,所有还是得划分成数组; 上述思路错误,是相互转化,M前+13,M后-13;

function rot13(str) { // LBH QVQ VG!
  var arr = str.split(' ');              //arr= ["SERR","PBQR","PNZC"]
  var arr1,arr2;
  var num1,num2;
  var str1;
      for(var i=0;i<arr.length;i++){     
        for(var j=0;j<arr[i].length;i++){
          arr1=arr[i].split('');                       //arr1=["S","E","R","R"]
          num1 = arr1.charCodeAt(j);                  //  "s" >> num1=83
          if(num1>=77){                                //在M前的字母加13
            num1 += 13;
          }else{num1 -=13;}                           //M后的减13
          arr1[j]=String.fromCharCode(num1);           
        }
          arr[i]=arr1.join('');
      }
      str = arr.join(' ');
  return str;

}

// Change the inputs below to test
rot13("SERR PBQR PNZC");

提示错误:typeerror: object doesn't support property or method 'charCodeAt',注意字母的对应,以及修改了一些小错误得到方案2

方案2

function rot13(str) { // LBH QVQ VG!
  var arr = str.split(' ');              //arr= ["SERR","PBQR","PNZC"]
  var arr1,arr2;
  var num1,num2;
  var str1;
      for(var i=0;i<arr.length;i++){    
        arr1=arr[i].split('');                                   //arr1=["S","E","R","R"] 
        for(var j=0;j<arr1.length;j++){                                                    
          num1 = arr1[j].charCodeAt(0);                  //  "s" >> num1=83
          if(num1>=77){                                //在M前的字母加13M后的减13
            num1 -= 13;
          }else{num1 +=13;}                           //在M前的字母加13
          arr1[j]=String.fromCharCode(num1);          //arr1[0]="F" 
        }
          arr[i]=arr1.join('');                                        //arr[0]="FREE"
      }
      str = arr.join(' ');                                           //str="FREE CODE CAMP"
  return str;

}

// Change the inputs below to test
rot13("SERR PBQR PNZC");

成功实现字母的转换,但是运行发现还需考虑标点符号,即只对字母生效,A为65,Z为90,修改代码如下:

function rot13(str) { // LBH QVQ VG!
  var arr = str.split(' ');              //arr= ["SERR","PBQR","PNZC"]
  var arr1,arr2;
  var num1,num2;
  var str1;
      for(var i=0;i<arr.length;i++){    
        arr1=arr[i].split('');   //arr1=["S","E","R","R"] 
        for(var j=0;j<arr1.length;j++){                                                    
          num1 = arr1[j].charCodeAt(0);                  //  "s" >> num1=83
          if(num1>77&&num1<=90){                        //在M前的字母加13M后的减13
            num1 -= 13;
          }else if (num1<=77&&num1>=65){num1 +=13;}     //在M前的字母加13
          arr1[j]=String.fromCharCode(num1);           
        }
          arr[i]=arr1.join('');
      }
      str = arr.join(' ');
  return str;

}

// Change the inputs below to test
rot13("GUR DHVPX OEBJA QBT WHZCRQ BIRE GUR YNML SBK.");

通过考验;

反省

* 畏难和浮躁的情绪,戒之戒之,冷静测试!

NBR-hugh commented 8 years ago

实际完成天数:5天 10.28-11.01 实际投入时间:13h10min

反省