Spells and Charms

プログラミング(呪文学)の学習記録。

eloquent javascript 2nd edition chapter 3 Function

Excercise

Minimum

The previous chapter introduced the standard function Math.min that returns its smallest argument. We can do that ourselves now. Write a function min that takes two arguments and returns their minimum.

これは結構すぐできた。
変に勘ぐってifの条件をa-b>0にしたけれど、a>bでよかったと思う。
そのほうが計算がいっこ少ないし。

function min(a,b){
if(a-b>0){
return b
}else{
  return a
}
}

 

Recursion

これはそもそもなにをreturnしたらいいのかあんまりわからなかった。。

returnがBoolean になるやつ、思いつかない傾向。
true falseを返すんだけど、条件の書き方がパッと思いつかない。

 

この問題は、何をreturnしたらいいのかわからずしばらく立ち往生。

We’ve seen that % (the remainder operator) can be used to test whether a number is even or odd by using % 2 to check whether it’s divisible by two. Here’s another way to define whether a positive whole number is even or odd:

  •   Zero is even.

  •   One is odd.

  •   For any other number N, its evenness is the same as N - 2.

 Define a recursive function isEven corresponding to this description. The function should accept a number parameter and return a Boolean.

 Test it on 50 and 75. See how it behaves on -1. Why? Can you think of a way to fix this?

問題よくよくよんでいたら、コンソールにかいてるじゃないですか。。。

console.log(isEven(50));
// → true
console.log(isEven(75));
// → false
console.log(isEven(-1));
// → ??

しかもよく考えたら関数名もisEven。
ということで、偶数ならtrue奇数ならfalseだったみたいでした。

途中経過のこんなかんじ。

function isEven(n){
if(n===0){
return true
}else if(n===1){
return false
}else return isEven(n-2)
}

n=-1のとき、無限になっちゃってます。

RangeError: Maximum call stack size exceeded (line 1 in function isEven) 

 

ネタバレですがヒントにもそうかかれていました。

When given a negative number, the function will recurse again and again, passing itself an ever more negative number, thus getting further and further away from returning a result. It will eventually run out of stack space and abort.

0より小さい値が与えられた時の条件を足せばいいのかということで、こういうコードに。

 

function isEven(n){
  if(n>=0){
	if(n===0){
      return true;
	}else if(n===1){
      return false;
	}else 
      return isEven(n-2);
	}
  else{
      return isEven(-n);
	}
  }

 

コンソールの回答はあってたけども、
回答の方がスコープがひとつ少なかった。

function isEven(n) {
  if (n == 0)
    return true;
  else if (n == 1)
    return false;
  else if (n < 0)
    return isEven(-n);
  else
    return isEven(n - 2);
}

 

 

補足)recursionでわかりやすかった動画。

 

 

 

Bean Counting

You can get the Nth character, or letter, from a string by writing"string".charAt(N), similar to how you get its length with "s".length. The returned value will be a string containing only one character (for example, "b"). The first character has position zero, which causes the last one to be found at position string.length - 1. In other words, a two-character string has length 2, and its characters have positions 0 and 1.

 Write a function countBs that takes a string as its only argument and returns a number that indicates how many uppercase “B” characters are in the string.

 Next, write a function called countChar that behaves like countBs, except it takes a second argument that indicates the character that is to be counted (rather than counting only uppercase “B” characters). Rewrite countBs to make use of this new function.

 

パッと思いついたコードはこれ。paizaとかkataとかでも似たようなものをみた記憶。

function countBs(str){
  var count = 0;
 for(var i = 0; i<str.length; i++){
   var b = str.charAt(i);
   if(b="B"){
     count +=1;
   }
   return count;
 } 
}

これだと数字はでてくるものの、forループがちゃんとまわっていない模様。
デバックをくりかえす。

 

変数いらないとおもって削除、などちょこちょこいじってなんかできた。

function countBs(str){
  var count = 0;
 for(var i = 0; i<str.length; i++){
   if(str.charAt(i) === "B"){
     count ++;
   }
 } 
   return count;
}

 

問題は2つの関数をかけということだったので次のcountChar

まずは前出のcountBs をほぼほぼぱくってこちらのコード。

function countChar(s,x){
var count = 0 ;
  for(var j = 0; j < s.length-1; j++){
    if(s.charAt(j)===x){
    count++
    }
  }
  return count;
}

 

しかし数字があまりただしくでない。デバックをくりかえす。
jの範囲設定まちがってました。

< つかってるので、s.length-1 ではなく、s.length でよかった。

function countChar(s,x){
var c = 0 ;
  for(var j = 0; j < s.length; j++){
    if(s.charAt(j) === x){
    c++;
    }
  }
  return c;
}

 

 

個人的にはRecursionが一番とっつきにくかった。

 

追記、最後の問題ちゃんと問題最後まで読んでなかった。
countBsつくりなおせってかいてあった。あはは!

 

function countChar(s,x){
var c = 0 ;
  for(var j = 0; j < s.length; j++){
    if(s.charAt(j) === x){
    c++;
    }
  }
  return c;
}

function countBs(s,c){
  return countChar(s,'B')
};

 

回答はこんなかんじ。自分のとほぼ一緒だけど{ }が端折られてるぶん短くすっきり。

このほうがいいのかな?

function countChar(string, ch) {
  var counted = 0;
  for (var i = 0; i < string.length; i++)
    if (string.charAt(i) == ch)
      counted += 1;
  return counted;
}

function countBs(string) {
  return countChar(string, "B");
}