항해 99

항해 99 5기 TIL_11

Dream Herb 2022. 1. 21. 01:04

▶ Today I Learned

 

<CS 스터디>

 

[2진수 쉽게 표현하기]

 

BCD: 10진수를 2진화 한 것 Binary Coded Decimal

ex)

2진수: 1101 

BCD: 0001 0011 좌측 4자리: 십의 자리 우측 4자리: 일의 자리

 

But 비트를 너무 많이 낭비한다는 단점이 있음

 

[8진법]

 

비트 3개를 사용하여 2진수를 8진수로 나타내기

 

ex) 2진수 101 8진수 5

8진수 015 -> 8**2*0 + 8**1*1 + 8*0*5 = 8 + 5 = 13

 

그러나 컴퓨터는 만들 때 8의 배수를 이용해 만드는 경우가 많음

4비트 2비트... 그러나 8진수는 한자리당 3개의 비트가 쓰여 갯수가 맞아 떨어지지 않음

요즘 많이 쓰이진 않음

 

[16진법]

 

비트 4개를 사용하여 2진수를 16진수로 나타내기

ex) 2진수 1001 = 16진수 9

 

그러나 16진수의 경우 수를 표현할 때 10이상 부터는 10진수 2개이상을 써야한다는 단점이 있음

-> 그래서 10 ~ 15는 기호로 표현

 

[비트 그룹의 이름]

 

비트 그룹 이름에는 여러가지가 있는데 그중 워드라는 말은 컴퓨터가 빠르게 처리하기 좋은 단위를 말함

ex) 워드 = 32비트

 

큰 수를 가리키는 표준용어도 있음

KB MB GB TB

1024  = 2**10

1024*1024 = 2**20 와 같은 방식으로 단위가 늘어남

그러나 이 이름들은 미터법 kilo mega 등에서 따온 것으로 10진법을 기반으로 하고 나타내는 수는 2진법 기반임

=> 헷갈림을 방지하기위해 IEC라는 국제기구에서는 kibi 와 같은 이름을 쓰고 단위를 10진법 단위로 하기로 명명

하지만 그 이후에도 헷갈려 하는 사람들이 많은 것으로 보임

(아직까지 실제로 kibi라는 것을 쓰는 걸 본적은 없다..)

실제로 stackoverflow에서도 실제로 사용하냐는 물음들이 꽤 있었고

인터넷의 다른글을 보아도 실제로 쓰는 것이 별로 없어보인다..

 

 

<알고리즘 기초>

 

[제일 작은 수 제거하기]

 

https://programmers.co.kr/learn/courses/30/lessons/12935

소요시간: 3시간

 

어제에 이어 고민하다가 짰던 코드

function solution(arr) {
    
   let answer = []
    let i = 0

if (arr.length == 1) {
  return [-1]
} else {

while(0 < arr.length-1) {

if (arr[i] < arr[i+1]) {
  answer = arr.push(arr[i+1])
  arr.splice(i+1, i+2)
} else {
  answer = arr.push(arr[i])
  arr.splice(i, i+1)
  }
i++
  
  }
  return answer
}

}

 

식은 맞게 짠것 같다. 테스트 실행을 돌려보니 -1을 반환하는 건 잘 작동하는데

배열의 길이가 2이상일 경우 연산이 느린 듯 하다.

실행시간이 10초를 넘어간다며 다음과 같은 문구가 뜬다.

와우..이런건 처음보는데

진짜 코드가 잘 안돌아가나..?

기능을 쓰지 않고 구현해보고 싶었는데 성능이 좋지 못한 코드라 그런 것 같다.

여튼 제출이 안되니 새로운 방법을 찾자!

 

그렇게 제출한 코드

function solution(arr) {

   return arr.length == 1 ? [-1] : arr.filter(m => Math.min(...arr) < m)
}

 

cf) Math.min() 쓸 때 ()안에 배열이 들어간다면 저렇게 ...을 해주어야한다.

깔끔하긴 한데 기능을 많이 썼다.

다른 방식으로 해보고 싶어 모범답안을 찾아보았는데

상위권 대부분은 위와 같이 Math.min 이나 filter, apply 등을 썼다.

 

그러던 중 발견한

프로그래머스 모범답안

 

function solution(arr) {
    var answer = [];
    var smallest = arr[0]; 
    if (arr.length > 1) {
        for (var i = 1; i < arr.length; i++) { // i를 1부터 준 게 인상적이었다.
        // 단순하게 i는 0 부터 찾기 시작해서 앞뒤 관계 비교후 위치를 바꿔주게되면
        // 전체의 크기에 따라 나열하지 못한다. 이분처럼 최소값을 따로 빼두고 밑에서 하나하나 비교하는게
        //훨씬 효율적인 방법 :)
            if (arr[i] < smallest) {
                smallest = arr[i]; // 가장 작은 값을 찾아서 따로 빼주는 방식
            }
        }
        for (var j = 0; j < arr.length; j++) {
            if (arr[j] > smallest) { // 최솟값과 비교해서 최솟값보다 크면 배열에 집어넣고 그것을 출력
                answer.push(arr[j])
            }
        }
    } else {
        answer.push(-1)
    }
    return answer;
}

 

 

참고해서 다음에 비슷하게 풀어보아야지 :)

 

 

[콜라츠 추측]

 

https://programmers.co.kr/learn/courses/30/lessons/12943

소요시간: 15분

 

처음 제출한 코드

function solution(num) {

    let count = 0

    while(1 < num) {

	if (num%2 == 0) {
  num = num/2
	} else {
  num = num*3 + 1
	}
  count++
	}
    return 500 <= count || num !== 1? -1 : count
}

여기서 주의할 것은 count || num에 count && num을 하면 안 된다는 것이다. 위 while문은 무조건 n이 1이 될 때 까지 돌아가게 되는데

우리는 횟수가 500이 넘어가기만 해도 -1을 출력해야하기 때문이다.

위 코드는 count가 500을 넘어가도 연산을 하는 것이 문제이다.

따라서 연산을 중간에도 멈춰줄 수 있게 다음과 같이 바꿔보자

let count = 0

while(1 < num || count < 500) {

if (num%2 == 0) {
  num = num/2
} else {
  num = num*3 + 1
}
  count++
}

return 500 <= count || num !== 1? -1 : count

이러면 count가 500이 되기만 해도 빠져나올 것이다!

대신 조건이 추가되었으니 컴퓨터 쪽에선 고려할 조건이 늘어서 위와 아래 중 어느쪽이 더 효율적일지는 성능을 따져보아야겠다..

 

더 효율적이거나 기발한 방법은 없을까?

 

프로그래머스 모범답안

function collatz(num,count = 0) {
    return num == 1 ? (count >= 500 ? -1 : count) : collatz(num % 2 == 0 ? num / 2 : num * 3 + 1,++count);
}

음 사실 내가 쓴 반복문과 조건문을 삼항 연산자로 나타낸 것 외에는 똑같다. 다른 답안들도 구조 자체는 똑같다.

애초에 문제에서 콜라츠 수를 구하는 식을 알려줬기에 다들 같은 방법을 생각하는 듯 하다.

문득 드는 생각이지만 만약 콜라츠 수를 구하는 법을 알려주지 않았다면

시간은 훨씬 오래 걸렸겠지만 다들 기발한 방법을 생각해보지 않았을까 라는 생각이 든다.

생각의 틀이 제한되지 않을테니까 :3

 

[전화번호 양식 갖추기]

 

소요시간: 20분

 

제한조건

‘1012345678’로 저장된 전화번호를 다시 ‘010-1234-5678’ 형식으로 바꾸려고 한다.

phone은 length는 10으로 고정
function solution(phone){
  
  let firstPart = "0" + phone.substring(0,2) + "-"
  
  let secondPart = phone.substring(2,6) + "-"
  let thirdPart =  phone.substring(6,10)

	let result= firstPart + secondPart + thirdPart
	return result;
}
console.log(solution("1062509911"))

splice를 활용해 간단히 만들어볼 수 도 있다.

 

like this

phone = "1012345678"

let num = phone.split('')

let first = "0" + num.splice(0,2,"-").join('')
let second = num.splice(0,5,"-").join('')
let third = num.join('')

console.log(first + second + third)

splice(시작인덱스, 종료인덱스[이것 전까지 반환], 잘라낸 부분에 추가하고 싶은 것)

 

 

 

 

[공부시간 구하기]

 

소요시간: 2시간

 

제한 조건

체크아웃을 할 때 익일 시간은 24+a 로 계산한다. 즉 새벽 2시는 24+2 인 26으로 표기한다.
체크인 페이지는 새벽 5시까지 체크아웃이 되어 있지 않으면 체크아웃을 깜빡한 것으로 간주한다.
따라서 체크인 시스템은 새벽 5시 정각이나, 새벽 5시를 넘겨서 체크아웃을 하게 되면 자동으로 체크아웃을 오후 9시(21:00)로 한 것으로 처리한다.
function solution(arr1, arr2){

let i = 0

for (i ; i < arr2.length ; i++) {
29 <= arr2[i].split(":")[0] ? arr2[i] = "21:00": arr2[i]

} // 체크아웃 시간 5시 정각이거나 넘을 경우 21:00로 초기화

let checkInHours = arr1.map(v => v.split(":")[0])
let checkInMins = arr1.map(v => v.split(":")[1])

let checkOutHours = arr2.map(v => v.split(":")[0])
let checkOutMins = arr2.map(v => v.split(":")[1])

//체크인과 체크아웃을 시간과 분으로 쪼개어 배열 생성

let studyHours = checkOutHours.map((v, i) => checkOutHours[i] - checkInHours[i])

let studyMins = []

let j = 0 // 분의 인덱스로 활용할 변수

for (j ; j < arr2.length ; j++) {

  if (checkOutMins[j] - checkInMins[j] < 0) {
    studyMins[j] = (checkOutMins[j] - checkInMins[j] + 60)
    /*이 부분에서 사실 크게 간과했다. 한시간이 100분이 아니라 60분 이라는 점이다.
    그래서 시간에서 1시간 제하는 대신 얻어야 하는 건
    마이너스값의 절대값도 아니고 100분에서 마이너스 값을 제하는 것도 아닌 60분에서
    마이너스 값을 제하는 것이다..!*/ 

    studyHours[j] = studyHours[j] - 1
    // 마이너스 분단위 계산 대신 1시간 빼버리기
    
  } else {
    studyMins[j] = checkOutMins[j] - checkInMins[j]
  }
}

let totalHours = studyHours.reduce((acc, cur) => acc + cur )
let totalMins = studyMins.reduce((acc, cur) => acc + cur )
// 총 공부 시간과 분 배열로 구한 것 시간은 시간대로, 분은 분대로 합치기

if (60 <= totalMins) {
  totalHours = totalHours + Math.floor(totalMins/60)
  totalMins = totalMins%60
  // 60분 초과하면 60분 단위로 시간에 넘기기, 다빼고 분은 60 미만으로 남는 분 적용하기
}

  let answer = `${totalHours}시간 ${totalMins}분`
	return answer;
}

let arr1=["8:42", "9:00", "8:50", "8:47", "9:01", "8:51", "8:59"];
let arr2=["21:42", "23:10", "25:30", "29:10", "23:11", "26:44", "29:26"];
console.log(solution(arr1, arr2))

 

 

 

▶ 느낀 점

 

어제는 전체 발표도 있었고 오늘 아침에 바로 CS스터디 발표를 하다보니 부랴부랴 준비해서 깊이 있게 다루진 못했다. 우선은 가볍게 이런게 있구나 정도를 이해하고 추후에 필요한 지식을 좀 더 파보면 좋을 것 같다..! (실제로 적용도 해보아야 내것이 될 테니)

그리고 5일간의 알고리즘 스터디가 드디어 끝이났다..!

약 30문제 정도를 풀었고 빨리 푸는 대신 관련 개념과 사용법을 이해하는 것, 그리고 문제를 다각도로 접근하는 것에 좀 더 치중했다. 속도는 많이 느렸지만 좋은 기반이 되어 나중에는 날개를 달아주리라 :)

 

그동안 함께 해주신 팀원 분들덕에 또 즐거운 한주가 되었다! 매주 좋은 분들만 만나 기분이 좋다 ㅎㅎ

다들 고생많으셨습니다..! :3

 

다음 주차도 화이팅팅!

 

 

▶ 공부 시 참고 링크들

 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/min

 

Math.min() - JavaScript | MDN

The static function Math.min() returns the lowest-valued number passed into it, or NaN if any parameter isn't a number and can't be converted into one.

developer.mozilla.org

 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

 

Array.prototype.filter() - JavaScript | MDN

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

developer.mozilla.org

 

https://velog.io/@kimhscom/JavaScript-%EC%9E%90%EC%A3%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-ES6-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC

 

[JavaScript] 자주 사용하는 ES6 문법 정리

들어가기 전에 Node.js와 React관련 프로젝트를 진행하면서 기존에 배워왔던 jQuery를 활용한 ES5 문법으로 JavaScript 코드를 작성하였지만 이제는 최신 트렌드에 맞게 ES6 문법으로 JavaScript 코드를 작성

velog.io

 

https://hianna.tistory.com/404

 

[Javascript] 배열 특정 값 위치(index) 찾기 - indexOf(), lastIndexOf()

배열에서 특정 값의 위치 index를 찾는 방법을 소개합니다. Javascript에서 배열에서 특정 값의 위치를 찾는 방법은 다양합니다. 이번에는 먼저, indexOf() 함수와 lastIndexOf() 함수를 사용하여 배열에서

hianna.tistory.com