JavaScript特別アルゴリズム問題(3):閉パッケージ

19763 ワード

@泡立つ馬の木
ライブラリ元アドレス:http://csbin.io/closures
閉パッケージ、役割ドメイン、および実行コンテキスト
チャレンジ1
質問:
createFunction関数を構築し、関数を作成して返します.作成された関数が呼び出されると、「hello」が印刷されます.
問題:
// CHALLENGE 1
function createFunction() {
    const innerFunction = () => {
    console.log("hello");
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const function1 = createFunction();
function1(); // => should console.log('hello');

チャレンジ2
質問:
パラメータとして入力値を受け入れるcreateFunctionPrinter関数を構築し、特定の関数を作成して返します.特定の関数が呼び出されると、特定の関数が作成されたときにcreateFunctionPrinterの値を入力する必要があります.
問題:
// CHALLENGE 2
function createFunctionPrinter(input) {
    const innerValue = input;
  const innerFunction = () => {
    console.log(innerValue);
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const printSample = createFunctionPrinter('sample');
printSample(); // => should console.log('sample');
const printHello = createFunctionPrinter('hello');
printHello(); // => should console.log('hello');

チャレンジ3
質問:
次のouter関数の実装コードを観察します.関数が返され、その関数はその役割ドメインにない変数を使用していることに注意してください.outer関数を実行して得られた出力値を推定し、addByX関数を構築します.入力値をパラメータとして受け入れ、xに加算する関数を返します.
コード:
// CHALLENGE 3
function outer() {
  let counter = 0; // this variable is outside incrementCounter's scope
  function incrementCounter () {
    counter ++;
    console.log('counter', counter);
  }
  return incrementCounter;
}

const willCounter = outer();
const jasCounter = outer();

// Uncomment each of these lines one by one.
// Before your do, guess what will be logged from each function call.

/*** Uncomment these to check your work! ***/
willCounter();
willCounter();
willCounter();

jasCounter();
willCounter();


function addByX(x) {
    let backpackValue = x ;
  const innerFunction = (el) => {
    return backpackValue + el;
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const addByTwo = addByX(2);
console.log(addByTwo(1)); // => should return 3
console.log(addByTwo(2)); // => should return 4
console.log(addByTwo(3)); // => should return 5

const addByThree = addByX(3);
console.log(addByThree(1)); // => should return 4
console.log(addByThree(2)); // => should return 5

const addByFour = addByX(4);
console.log(addByFour(4)); // => should return 8
console.log(addByFour(5)); // => should return 9

チャレンジ4
質問:
once関数を構築し、パラメータがコールバック関数であることを受け入れ、特定の関数を返します.特定の関数が最初に呼び出されると、コールバック関数が呼び出され、出力値が返されます.1回目の呼び出しでない場合、特定の関数は、1回目の呼び出しで得られたコールバック関数の戻り値のみを返し、コールバック関数を再実行するのではありません.
問題:
// CHALLENGE 4
function once(func) {
    let counter = 0;
  let innerValue = 0; 
  const innerFunction = (el) => {
    counter++;
    if(counter == 1) {
      innerValue = func(el);
      return innerValue;
    } else {
      return innerValue;
    }
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const onceFunc = once(addByTwo);
console.log(onceFunc(4));  // => should log 6
console.log(onceFunc(10));  // => should log 6
console.log(onceFunc(9001));  // => should log 6

チャレンジ5
質問:
after関数を構築し,パラメータとして1つの数値nと1つのコールバック関数を受け入れる.コールバック関数はafterによって構築された関数がn回目に実行される必要があります.
問題:
// CHALLENGE 5
function after(count, func) {
    let counter = count;
  const innerFunction = () => {
    counter--;
    if(counter == 0){
      func();
    }
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const called = function() { console.log('hello') };
const afterCalled = after(3, called);
afterCalled(); // => nothing is printed
afterCalled(); // => nothing is printed
afterCalled(); // => 'hello' is printed

チャレンジ6
質問:
delay関数を構築し、1つのコールバック関数を1番目のパラメータとして受け入れ、1つの数値n(ミリ秒単位)を2番目のパラメータとして受け入れます.delay関数が呼び出されると、nミリ秒後にコールバック関数が実行されます.特定の関数に割り当てられた他のパラメータは、nミリ秒後にコールバック関数によって使用されます.ヒント:settimeout()の検討;
問題:
// CHALLENGE 6
function delay(func, wait, ...args) {
  setTimeout(() => func(...args), wait);
}

delay(called, 2000);  // "hello" after 2 seconds.

チャレンジ7
質問:
rollCall関数を構築し、名前からなる配列を受け入れ、特定の関数を返します.特定の関数を最初に呼び出すと、配列の最初の名前が印刷されます.2回目の呼び出しでは、2番目の名前を印刷し、すべての名前が印刷されるまで続けます.すべての名前が印刷されると、「Everyone accounted for」が印刷されます.
問題:
// CHALLENGE 7
function rollCall(names) {
  const innerArray = new Array;
  for(let i=0; i {
        if(innerArray.length == 0){
      console.log("Everyone accounted for");
    } else {
      console.log(innerArray.shift());
    }
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const rollCaller = rollCall(['Victoria', 'Juan', 'Ruth'])
rollCaller() // => should log 'Victoria'
rollCaller() // => should log 'Juan'
rollCaller() // => should log 'Ruth'
rollCaller() // => should log 'Everyone accounted for'

チャレンジ8
質問:
saveOutput関数を構築し、パラメータとしてコールバック関数とパスワードとして文字列を受け入れます.saveOutputは、コールバック関数と同様に機能する特定の関数を返します.ただし、文字列パラメータがsaveOutput関数の暗号文字列パラメータと同じである場合、特定の関数は、以前に特定の関数を呼び出したすべての入力値をオブジェクトのキーとして使用し、コールバック関数の出力値を値としてオブジェクトを構築し、それを返します.
問題:
// CHALLENGE 8
function saveOutput(func, magicWord) {
    const storedMagicWord = magicWord;
  const storedInputArray = new Array;
  const storedOutputArray = new Array;
  const exitObject = new Object;
  let tempOutput = 0;
  const innerFunction = (el) => {
    if(el !== storedMagicWord) {
      storedInputArray.push(el);
      tempOutput = func(el);
      storedOutputArray.push(tempOutput);
      return tempOutput;
    } else {
      if(storedInputArray.length == storedOutputArray.length) {
        for(let i=0; i should log 4
console.log(multBy2AndLog(9)); // => should log 18
console.log(multBy2AndLog('boo')); // => should log { 2: 4, 9: 18 }

チャレンジ9
質問:
cycleIterator関数を構築し、パラメータを配列として受け入れ、特定の関数を返します.特定の関数はパラメータを受け入れません.最初に呼び出されると、特定の関数は配列の最初の要素を返します.2回目の呼び出しでは、2番目の要素を返して、まっすぐ行きます.特定の関数が配列の最後の要素を返した後、次にこの特定の関数を呼び出すと、配列の最初の要素が返され、2番目の要素がずっと下がります.
問題:
// CHALLENGE 9
function cycleIterator(array) {
    let counter = 0;
  const innerFunction = () => {
        counter++;
    if(counter > array.length){
      counter = 0;
      return array[counter];
    } else{
      return array[counter-1];
    }
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const threeDayWeekend = ['Fri', 'Sat', 'Sun'];
const getDay = cycleIterator(threeDayWeekend);
console.log(getDay()); // => should log 'Fri'
console.log(getDay()); // => should log 'Sat'
console.log(getDay()); // => should log 'Sun'
console.log(getDay()); // => should log 'Fri'

チャレンジ10
質問:
パラメータをコールバック関数と数値として受け入れるdefineFirstArg関数を構築します.コールバック関数は、少なくとも1つのパラメータを受け入れます.defineFirstArgは、特定の関数を返します.この特定の関数は、defineFirstArgの数値パラメータをコールバック関数の最初のパラメータとし、特定の関数のパラメータをコールバック関数の2番目のパラメータとして入力し、コールバック関数を呼び出します.
問題:
// CHALLENGE 10
function defineFirstArg(func, arg) {
    const innerFunction = (el) =>{
    return func(arg, el);
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const subtract = function(big, small) { return big - small; };
const subFrom20 = defineFirstArg(subtract, 20);
console.log(subFrom20(5)); // => should log 15

チャレンジ11
質問:
dateStamp関数を構築し、パラメータをコールバック関数として受け入れ、特定の関数を返します.特定の関数は、コールバック関数に必要なパラメータを受け入れてコールバック関数に渡され、特定の関数が呼び出されたときの日付情報(dateキー)とコールバック関数の出力(outputキー)を記録するオブジェクトを返します.ヒント:Dateオブジェクトの情報を取得する方法を検討する必要があります.
問題:
// CHALLENGE 11
function dateStamp(func) {
    let dateInfo;
  const innerObj = new Object;
  const innerFunction = (el) => {
    dateInfo = new Date();
    innerObj['date'] = dateInfo.toString();
    innerObj['output'] = func(el);
    return innerObj;
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const stampedMultBy2 = dateStamp(n => n * 2);
console.log(stampedMultBy2(4)); // => should log { date: (today's date), output: 8 }
console.log(stampedMultBy2(6)); // => should log { date: (today's date), output: 12 }

チャレンジ12
質問:
パラメータを受け入れずにcensor関数を構築します.censorは、2つの文字列または単一の文字列パラメータを受け入れる特定の関数を返します.2つの文字列パラメータが得られると、特定の関数は、後続の使用に備えて2つの文字列を1対として格納します.文字列パラメータが得られると、特定の関数は同じ文字列を返します.ただし、この文字列の最初の文字列と同じ文字列が、格納文字列ペアの2番目の文字列に置き換えられます.
問題:
// CHALLENGE 12
function censor() {
  let parameterInfoObj = new Object;
  let oneParameterArray = new Array;
  let punctuationArray = new Array;
    const innerFunc = (el1, el2) => {
    if(el1 && el2) {
      oneParameterArray = [];
      punctuationArray = [];
      parameterInfoObj[el1] = el2;
      return parameterInfoObj;
    }
    else if(el1 && !el2){
      oneParameterArray = el1.match(/\b(\w+)\b/g);
      punctuationArray = el1.match(/([,. ]+)/g);
      for(let i = 0; i should log 'The slow, brown fox jumps over the lazy cats.'

チャレンジ13
質問:
JavaScriptオブジェクトにはプライベート属性の定義はありませんが、カスタマイズできますか?createSecretHolder(secret)関数を構築し、任意の値をsecretパラメータとして受け入れ、2つのメソッドのみを返し、secret値のgetSecret()とsecret値を設定するsetSecret()を返します.
問題:
// CHALLENGE 13
function createSecretHolder(secret) {
    let secretInfo = secret;
  const innerObj = new Object;
  innerObj.getSecret = ()=>{
    return secretInfo;
  }
  innerObj.setSecret = (el)=>{
    secretInfo = el;
  }
  return innerObj;
  
}

/*** Uncomment these to check your work! ***/
const obj = createSecretHolder(5)
console.log(obj.getSecret()) // => returns 5
console.log(obj.setSecret(2)) // => undefined
console.log(obj.getSecret()) // => returns 2

チャレンジ14
質問:
callTimes関数を構築し、特定の関数を返します.特定の関数は、呼び出された回数情報を返します.
問題:
// CHALLENGE 14
function callTimes() {
    let counter = 0;
  const innerFunction = () => {
    return ++counter;
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
let myNewFunc1 = callTimes();
let myNewFunc2 = callTimes();
console.log(myNewFunc1()); // => 1
console.log(myNewFunc1()); // => 2
console.log(myNewFunc2()); // => 1
console.log(myNewFunc2()); // => 2

チャレンジ15
質問:
russianRoulette関数を構築し、nと仮定した数値パラメータを受け入れ、特定の関数を返すようにします.この特定の関数は入力パラメータを受け入れず、前のn-1回の呼び出しで文字列「click」を返し、n回目の呼び出しで文字列「bang」を返し、n回以降の呼び出しで文字列「reload to play again」を返します.
問題:
// CHALLENGE 15
function russianRoulette(num) {
  let counter = num;
    const innerFunction = () => {
      counter--;
      if(counter>0) {
        return "click";
      } else if(counter==0){
        return "bang";
      } else{
        return "reload to play again";
      }
    }
    return innerFunction; 
}

/*** Uncomment these to check your work! ***/
const play = russianRoulette(3);
console.log(play()); // => should log 'click'
console.log(play()); // => should log 'click'
console.log(play()); // => should log 'bang'
console.log(play()); // => should log 'reload to play again'
console.log(play()); // => should log 'reload to play again'

チャレンジ16
質問:
パラメータを受け入れずにaverage関数を構築し、特定の関数(パラメータとして数値を受け入れるか、パラメータなし)を返します.averageで作成された特定の関数が数値パラメータを入力するように呼び出されると、戻り値は、特定の関数に入力されたすべての数値パラメータの平均値(重複数値はそれぞれの数値とみなされる)になります.特定の関数がパラメータなしで呼び出されると、現在の平均値が返されます.特定の関数がパラメータなしで呼び出されたときに数値パラメータが入力されていない場合は、0を返します.
問題:
// CHALLENGE 16
function average() {
  let averageValue = 0;
    let argumentCounter = 0;
    let argumentSum = 0;
    const innerFunction = (el) => {
      if(el == undefined) {
        return averageValue;
      } else{
        argumentCounter++;
        argumentSum += el; 
        averageValue = argumentSum / argumentCounter;
        return averageValue;
      }
    }
    return innerFunction;
}

/*** Uncomment these to check your work! ***/
const avgSoFar = average();
console.log(avgSoFar()); // => should log 0
console.log(avgSoFar(4)); // => should log 4
console.log(avgSoFar(8)); // => should log 6
console.log(avgSoFar()); // => should log 6
console.log(avgSoFar(12)); // => should log 8
console.log(avgSoFar()); // => should log 8

チャレンジ17
質問:
makeFuncTester関数を構築し、パラメータが2次元配列(2次元配列が2つの要素のみを含む)であることを受け入れ、パラメータとしてコールバック関数を受信する特定の関数を返します.2 D配列の各サブ配列の最初の要素がコールバック関数に入力されたときに、2番目の要素と同じ戻り値が生成されると、特定の関数はtureを返し、そうでなければ特定の関数はfalseを返します.
問題:
// CHALLENGE 17
function makeFuncTester(arrOfTests) {
  const firstLayerArray = [];
  for(let i = 0; i {
    for(let i=0; i str.toUpperCase();
const capLastAttempt2 = str => str.slice(0, -1) + str.slice(-1).toUpperCase();
console.log(shouldCapitalizeLast(capLastAttempt1)); // => should log false
console.log(shouldCapitalizeLast(capLastAttempt2)); // => should log true

チャレンジ18
質問:
makeHistory関数を構築し、数値パラメータn(制限値として機能する)を受け入れ、特定の関数(パラメータとして文字列を受け入れる)を返します.特定の関数は、この特定の関数に最近入力された文字列パラメータの履歴(呼び出しごとに1回)をnに限定して格納します.特定の関数に文字列が入力されるたびに、特定の関数は、この文字列の後に「done」をつづった新しい文字列(スペースを間隔として)を返します.ただし、文字列が「undo」と入力すると、特定の関数は文字列パラメータ履歴の最近の文字列値を削除し、この最近の文字列の後に「undone」が接続された新しい文字列(スペースを間隔として)を返します.文字列「undo」を入力すると、特定の関数の文字列パラメータ履歴が空になった場合、特定の関数は文字列「nothing to undo」を返します.
問題:
// CHALLENGE 18
function makeHistory(limit) {
    const limitNumber = limit; 
  let parameterStack = [];
  const innerFunction = (stringElement) => {
    if(stringElement === "undo"){
      if(parameterStack.length == 0) {
        return "nothing to undo";
      } else{
        return `${parameterStack.pop()} undone`;
      }
    } else{
      parameterStack.push(stringElement);
      if(parameterStack.length > limit){
        parameterStack = parameterStack.slice(-limit);
      }
      return `${stringElement} done`;
    }
  }
  return innerFunction;
}

/*** Uncomment these to check your work! ***/
const myActions = makeHistory(2);
console.log(myActions('jump')); // => should log 'jump done'
console.log(myActions('undo')); // => should log 'jump undone'
console.log(myActions('walk')); // => should log 'walk done'
console.log(myActions('code')); // => should log 'code done'
console.log(myActions('pose')); // => should log 'pose done'
console.log(myActions('undo')); // => should log 'pose undone'
console.log(myActions('undo')); // => should log 'code undone'
console.log(myActions('undo')); // => should log 'nothing to undo'

チャレンジ19
質問:
テストコードをよく観察して、次のアルゴリズムの説明を理解する必要がある場合は、次のアルゴリズムの説明を理解してください.
blackjack関数を構築し、パラメータを1つの配列(要素はすべて1から11の数値)として受け入れ、DEALER関数を返します.DEALER関数は、2つのパラメータ(いずれも数値)を受け入れ、別のPLAYER関数を返します.
PLAYER関数が最初に呼び出されると、DEALER関数に入力された2つの数値パラメータの合計が返されます.
PLAYER関数を2回目に呼び出すと、次の2つのケースのいずれかが返されます.
  • blackjack関数の数値型配列を入力する最初の数値に入力DEALER関数の2つの数値パラメータの和を加えたもので、和が21以下であれば、この和を返します.
  • と21より大きい場合、文字列「bust」が返されます.

  • PLAYER関数が2回目に呼び出されたときに「bust」が返された場合、次に、PLAYER関数の呼び出しのたびに文字列「you are done!」が返されます.(ただし、「bust」とは異なり、「you are done!」を出力するときに数値型配列の数値は使用されません).2回目のPLAYER関数の呼び出しで「bust」が返されない場合、次にPLAYER関数を呼び出すときに次の2つのいずれかが返されます.
  • 最近の和に数値型配列の次の数値要素を加え、この和が21以下であれば、この和を返します.
  • は、合計結果が21より大きい場合に「bust」を返します.

  • 再度、「bust」を返すと、PLAYER関数の呼び出しのたびに文字列「you are done!」が返されます.そうしないと、PLAYER関数は最近の和値と数値型配列の次の数値要素を合計し続け、ずっと続けます.
    与えられた数値型配列に十分な数値要素があると仮定して、配列要素を使い切る前に「bust」を得ることができます.
    問題:
    
    // CHALLENGE 19
    function blackjack(array) {
        const dealer = (num1, num2) => {
        let first = true; 
        let bust = false; 
        let sum = num1 + num2; 
        const player = () => {
          if(first) {
            first = false; 
            return sum;
          }
          if(bust) {
            return "you are done!";
          }
          if(sum + array[0] <= 21){
            sum += array.shift();
            return sum;
          } else {
            array.shift();
            bust = true;
            return "bust";
          }
        }
        return player;
      }
      return dealer;
    }
    
    /*** Uncomment these to check your work! ***/
    
    /*** DEALER ***/
    const deal = blackjack([2, 6, 1, 7, 11, 4, 6, 3, 9, 8, 9, 3, 10, 4, 5, 3, 7, 4, 9, 6, 10, 11]);
    
    /*** PLAYER 1 ***/
    const i_like_to_live_dangerously = deal(4, 5);
    console.log(i_like_to_live_dangerously()); // => should log 9
    console.log(i_like_to_live_dangerously()); // => should log 11
    console.log(i_like_to_live_dangerously()); // => should log 17
    console.log(i_like_to_live_dangerously()); // => should log 18
    console.log(i_like_to_live_dangerously()); // => should log 'bust'
    console.log(i_like_to_live_dangerously()); // => should log 'you are done!'
    console.log(i_like_to_live_dangerously()); // => should log 'you are done!'
    
    /*** BELOW LINES ARE FOR THE BONUS ***/
    
    /*** PLAYER 2 ***/
    const i_TOO_like_to_live_dangerously = deal(2, 2);
    console.log(i_TOO_like_to_live_dangerously()); // => should log 4
    console.log(i_TOO_like_to_live_dangerously()); // => should log 15
    console.log(i_TOO_like_to_live_dangerously()); // => should log 19
    console.log(i_TOO_like_to_live_dangerously()); // => should log 'bust'
    console.log(i_TOO_like_to_live_dangerously()); // => should log 'you are done!
    console.log(i_TOO_like_to_live_dangerously()); // => should log 'you are done!
    
    /*** PLAYER 3 ***/
    const i_ALSO_like_to_live_dangerously = deal(3, 7);
    console.log(i_ALSO_like_to_live_dangerously()); // => should log 10
    console.log(i_ALSO_like_to_live_dangerously()); // => should log 13
    console.log(i_ALSO_like_to_live_dangerously()); // => should log 'bust'
    console.log(i_ALSO_like_to_live_dangerously()); // => should log 'you are done!
    console.log(i_ALSO_like_to_live_dangerously()); // => should log 'you are done!'
    

    JavaScript专项算法题(3):闭包_第1张图片