Coding (164)

07
20

1. 문제의 발단

  • 지금도 계속 헷갈리고 있는 재귀함수를 사용하기 위해 일반적으로 사용되는 탬플릿을 외운다
  • 아직 문제를 계속 풀고 있어서 다른 블로깅은 하지 못 할것 같다.
function 재귀함수(처음 입력받거나, 아까 받은 값) {

let [head, ...tail] = arr; // 배열의 가장 앞의 arr[0]를 head, 나머지 요소를 배열안에 tail로 담는다.

	if('탈출 조건') {
		return '마지막에 리턴하게 될 답'
	} else {
		return 재귀함수(다시 매게변수로 넘겨줄 값)
	}
 }
COMMENT
 
07
19

1. class

  • 구성이 비슷한 여러 개의 객체를 만들려고 할 때 사용하는 ''blueprint"가 된다.
  • 예를 들어, 게임 캐릭터의 스킬을 정리해 놓은 리스트를 만들려고 한다.
const Garrosh = {
	passiveSkill : 'Armor Up',
    q : 'Groundbreaker',
    w : 'Bloodthirst',
    e : 'Wrecking Ball',
}

const Artanis = {
	passiveSkill : 'Shiield Overload',
    q : 'Blade Dash',
    w : 'Twin Blades',
    e : 'Phase Prism',
}

const ...
  • 이런 식으로 만들다가는 끝이 없을 것이다.
  • 그렇기 때문에 class를 이용한 객체를 만들 수 있는 생성자를 만들 것이다.
class Hero {
	constructor(passiveSkill, q, w, e) { //constructor를 하나 만들어서 매개변수들을 정해준다.
		this.passiveSkill = passiveSkill;
        	this.q = q;
        	this.w = w;
        	this.e = e;
	}
}

const Nova = new Hero('Permanent Cloak', 'Snipe', 'Pinning Shot', 'Holo Decoy');

// Nova === Hero {
//	  passiveSkill : 'Permanent Cloak',
//    q : 'Snipe',
//    w : 'Pinning Shot',
//    e : 'Holo Decoy',
// }
  • 이는 ES6 문법에서부터 적용된다. 과거의 방법인 함수를 만드는 방법도 있다.
function Hero(passiveSkill, q, w, e) { // 첫번째 글자는 대문자로 쓴다.
	this.passiveSkill = passiveSkill;
    this.q = q;
    this.w = w;
    this.e = e;
}

const Diablo = new Hero('Black Soulstone', 'Shadow Charge', 'Fire Stomp', 'Overpower');

// Diablo === Hero {
//	  passiveSkill : 'Black Soulstone',
//    q : 'Shadow Charge',
//    w : 'Fire Stomp',
//    e : 'Overpower',
// }
  • 위의 class와 똑같이 작동하게 된다. 이렇게 간단하게 계속 캐릭터 정보를 입력할 수 있다.
  • 즉, 엄청난 재사용성을 가지게 된다.
  • 함수와 같은 모든 타입의 데이터도 넣을 수 있다.
  • 이렇게 생성된 객체들을 'instances'라고 한다.

2. prototype

  • 이때, 생성자를 만들면 생성된 자식 object에는 'prototype'이 생성된다. 만들지 않아도 자동으로 생긴다.
  • 간단하게 '유전자'라고 생각하면 된다. 부모가 자식에게 물려주는 것이기 때문이다. 그래서 위의 예시에 Hero에 prototype에 키와 값을 주면 모든 자식에게 영향을 주게 된다.
Hero.prototype.gameTitle = 'Heroes of the Storm'

// Nova.gameTiltle === 'Heroes of the Storm'
// Diablo.gameTitle === 'Heroes of the Storm'
  • 이렇게 숨겨진 prototype에는 우리가 매번 사용하던 기본 함수들이(ex: length, sort 등등) 이미 저장되어 있다.
  • 우리가 평상시에 한 자료를 만들 때 그 타입에 따라 const arr = [1, 2, 3, 4,]로 만들지만, const arr = new Array(1, 2, 3, 4,)로도 만들 수 있다. 똑같은 방식이다. 말하자면, 위에서 보았던 Hero와 Array는 똑같은 역할을 하게 되는 것이다!
  • 그러므로, Array에 prorotype에 있던 각각의 기본 함수들을 그대로 새로 만든 arr에서도 사용할 수 있게 된다.
  • 이를 그대로 응용하면, 우리는 새로운 기본 함수를 Array.prototype.funcA = function() {...}과 같은 식으로 만들어 줄 수 도 있다!

3. OOP

 객체지향 프로그래밍의 주요 콘셉트이다.

  1. 캡슐화(Encapsulation)
    • 데이터를 어떠한 기능이 동작하면 조작할 수 있도록 연결하는 것.
    • 데이터를 일부러 은닉시키기도 한다.
  2. 추상화(Abstraction)
    • 내부 기능은 복잡하게 되어 있을지 몰라도, 우리가 보는 환경에는 단순하게 하여 사용자로 하여금 이용을 편하게 할 수 있게 한다.
    • 옛날에 만들었던 계산기를 생각해 보자. 겉으로 보기에는 사칙연산의 혼합이 가능하거나 소수점 계산이 가능하더라도 생긴 건 불가능한 계산기와 똑같고, 단순하게 숫자와 연산자로 이루어진 모습이다.
  3. 상속(Inheritance)
    • 말 그대로 상속. 부모의 속성과 특징을 자식에게 물려주는 것이다. 위의 예시로 보았듯이, 부모가 가지고 있던 속성을 자식에게 줄 수 있다. 공통되는 부분을 가직 자식 객체들의 똑같은 부분을 계속 적어줄 필요가 없다.
  4. 다양성(Polymorphism)
    • 상속받은 자식들 중에 하나에만 다른 속성을 추가하거나 수정하고 싶을 때는 필요한 함수만, 혹은 속성만 뽑아서 수정하면 된다. 각각 하나하나 따로 수정을 해 줄 필요가 없다.
COMMENT
 
07
16

1. 사건의 발단

  • 코드를 짜기 전에 수도 코드를 쓰게 된다. 이것처럼 모든 일에는 계획이 중요하다. 그래서 노션을 사용해 짜는 습관을 들이려고 한다.

2. 슬레시의 사용

  • 노션에서 슬레쉬는 명령어 키이다.
  • 블로그 글 쓸 때처럼 리스트를 작성하거나, 체크박스를 만들거나, 스타일도 바로 넣을 수 있다.
  • 이미지, 동영상, 깃 헙도 바로 연결할 수 있다.
  • 토글을 활용해서 글을 줄여보자. 매우 깔끔하겠지?
  • 주 용한 내용은 콜 아웃으로 강조한다.

3. 트렐로

  • 프로젝트의 형태로 진행과정을 공유하게 된다.
  • 이걸로 프로젝트 진행상황을 공유하는 기업들이 많다고 한다. 사용하면서 익숙해지면 될 것 같다.

4. 템플릿

  • 디자인적인 요소 모든 것을 저장해 두고 언제든지 꺼내 쓸 수 있다.
  • 템플릿을 이용해 아주 다양한 폼들을 받아와서 아예 기업 홈페이지를 없애고 노션을 사용해 대체하기도 한다. 엡에서 공유를 설정해 놓으면 팀이 아닌 인원도 볼 수 있는 홈페이지가 되기 때문이다. 심지어 구글에 검색도 된다!
  • 템플릿은 자신이 직접 만들어 쓸 수 도 있다.

 

간단하게 노션에 대해 정리해 보았다. 일단 사용하면서 여기저기에 사용해 봐야 익숙해질 것 같다.

 

COMMENT
 
07
13

1. Math.sqrt를 사용하지 않은 수숫점 구하기.

  • 입력받은 수를 제곱근 값을 소숫점 두 자리까지만 리턴한다.
  • 셋째 자리에서 반올림한다.
function computeSquareRoot(num) {
  // 기준을 잡아줄 소숫점 자리들의 가장 작은 수를 배열에 만든다.
  const decimal = [1, 0.1, 0.01, 0.001];
  //기준이 될 result를 1로 둔다.
  let result = 1;
  // 반복문으로 기준이 된 result를 제곱해서 num보다 작은 경우
  for (let i = 0; i < decimal.length; i++) {
    while (result * result < num) {
  //result에 소숫점 자리를 더한다. num가 더해진 기준의 제곱보다 커질때 까지 반복.
      result = result + decimal[i];
    }
  // 만약 result의 제곱이 num와 같을때 바로 리턴.
    if (result * result === num) {
      return result;
  // 아니면 소숫점 빼주고
    } else {
      result = result - decimal[i];
    }
  }
  //소숫점 3번째에서 반올림
  return Number(result.toFixed(2));
}
  • 다른 방법으로는 '바빌로니아 법의 점화식'이 있다고 한다. 나는 이해할 수 없다...

2. 카이사르 암호

  • 문자열과 숫자를 입력받아 입력받은 숫자만큼 평행 이동시킨 문자열을 리턴한다.
  • 공백은 무시한다.

[시도 1]

function decryptCaesarCipher(str, secret) {
  // 일단 스트링을 다 split으로 다 땐다.
  let newStr = str.split('');
  // 때어낸 문자를 아스키코드로 변환하여 넣는다.
  let arr = []
  for(let i = 0; i < newStr.length; i++) {
    arr.push(newStr[i].charCodeAt())
  }
  // 지금 이 배열이 아스키 코드로 바꾼 스트링이 들어있는 배열
  let ascii = arr.map(arr => arr - secret)
  let result = '';
  // 배열들을 돌면서 빈칸을 빈칸을 걸러내고
  for(let i = 0; i < ascii.length; i++) {
    if(ascii[i] === 29) {
      result = result + ' '
    } else {
    //남은건 다시 문자로 바꿔서 반환
      result = result + String.fromCharCode(ascii[i])
    }
  }
  return String(arr);
}
  • 실패
  • 아스키코드의 표에서 보면 secret으로 큰 수를 받을 경우, 소문자를 넘어 대문자까지 넘어간다.
  • 소문자 만을 범위로 secret을 정해주어서 97번부터 122번 사이에서만 secret이 변환되도록 만들어야 한다.

[시도 2]

function decryptCaesarCipher(str, secret) {
  let strArr = [abcdefghijklmnopqrstuvwxyz]
  let newStr = str.split('')
  let indexArr = [];
  for(let i = 0; i < newStr.length; i++) {
    indexArr.push(strArr.indexOf(newStr[i]))
    }
  return indexArr
  }
  • 완전히 틀린 코드이다.
  • 아예 나올 수 있는 알파벳을 모두 넣어서 그 배열 속에서 반복문으로 index를 매칭 시키려고 했지만 실패
  • 다시 아스키코드의 범위를 지정하는 방법으로 돌아가기로 하였다.

[시도 3]

function decryptCaesarCipher(str, secret) {
    let newStr = '';
    // str을 split으로 다 자른다.
    let splitStr = str.split('')
    // 자른 newStr에 for...of로 모든 배열들을 다 찾아서
    for(let i of splitStr) {
      // 만약 빈칸이면
        if(i === ' ') {
          // 빈칸을 넣고
          newStr = newStr + ' '
          } else {
            // 만약 아스키 코드 표에서 소문자가 되는 97을 넘으면 맞으면, secret이동 후에 - 122(최대 숫자) 총 알파벳 갯수가 26개 니까 나머지에 122 더한다.
            // 97보다 작으면, secret이동 후에 - 122 그리고 26 나눠서 나머지에 마찬가지 122 더한다.
            newStr = newStr + String.fromCharCode((i.charCodeAt(0) > 97) 
            	? (i.charCodeAt(0) - secret - 122) % 26 + 122 
                : (i.charCodeAt(0) - secret - 122) % 26 + 122)
            };
    }
    return newStr;
}
  • 문제 해결!
  • 조건을 걸 때, 총 알파벳 개수(26)와 최소 97, 최대 122가 나온다는 것을 바탕으로 범위를 정했다.
  • for... of와 삼항 연산자로 코드를 조금 더 간결하게도 바꿨다.
COMMENT