180928 TIL Lec2 학점계산기 step2 & 알고리즘 스터디

» 1막, TIL (Today I Learned)

알고리즘 수업

  • 재귀에 대해서 배웠다. 재귀 개념은 이해가 가는데, 실제로 짜보는 게 너무 어렵다.
  • 재귀로 피보나치 수열 구현부터 이해가 되지 않았다… 복습하기!

알고리즘 스터디

  • 오늘은 인원이 늘어 총 5명이서 진행했다.
  • 지난 번에 풀었던 문제중에 어려웠던 문제에 대해 피드백을 나눴다.
  • ‘시저암호’의 경우 나는 그냥 배열에 다 때려넣었는데, 달리와 헤드는 아스키문자를 이용해서 풀었다.

step2 수정

  • step2 피드백 내용을 반영했다… (여기서 오늘 좀 위기였다. 하루에 한 번씩 울고싶네ㅠ)

  • Crong: 여기서 사용한 data를 removeLecture 함수에서 직접 호출하지않고, 파라미터로 받으면 더 좋을 듯.

//수정 전
function removeLecture(lecture, time) {
    setTimeout(function () {
        const newData = [];
        for (i = 0; i < data.length; i++) { ......

//수정 후
function removeLecture(dataArr, lecture, time) {
    setTimeout(function () {
  • Crong: 여기 for문을 filter와 map으로 수정해보세요.
//수정 전
            if (data[i].name !== lecture) {
                newData.push(data[i]);

//수정 후 - 처음으로 filter를 사용해보았다! 
        const newData = dataArr.filter(function (value) {
            return value.name !== lecture;
        })
  • Crong: getValues 함수에서는 values라는 객체에 무언가 담아두고, 그 결과를 다시 gpaCalculator 에서 활용해서 출력하는건데요.
    gpaCalculator에서 필요한 건 getValues 객체가 아니고, 각각의 정보가 필요한 것이죠.
    따라서 getValues를 통해서 values객체를 만들지 않고, 평점을계산하는 함수, 전공평점을계산하는함수, 이수학점을 계산하는 함수,..
    이렇게 각각 에 요구사항에 맞는 함수들을 만들고 그 함수들을 호출하면 되죠. 이런방식으로 한번 구현해보세요~

    elements …변수가 너무 기네요~
//수정 전
function getValues(dataArr) {
    const values = {};
    const elements = [calculateCredits(dataArr)[0], calculateCredits(dataArr)[1], calculatePoints(dataArr)[0], calculatePoints(dataArr)[1], parseFloat((calculatePoints(dataArr)[0] / calculateCredits(dataArr)[0]).toFixed(2)), parseFloat((calculatePoints(dataArr)[1] / calculateCredits(dataArr)[1]).toFixed(2))];
    [values.grossCredits, values.grossMajorCredits, values.grossPoints, values.grossMajorPoints, values.gpa, values.mgpa] = elements;
    return values;
}

//수정 후 - getValues() 를 아예 없애고, gpaCalculator()에서 선언해주었다. 이렇게 해야 나중에 알아보기도 쉽고 디버깅에도 적절하다고..  확실히 변수명으로 무슨 값인지 알 수 있으니 좋다. 

function gpaCalculator(dataArr, scale) {
    const [grossCredits, majorCredits] = calculateCredits(dataArr);
    const [grossPoints, majorPoints] = calculatePoints(dataArr);
    const gpa = ((grossPoints / grossCredits) * (scale / 4.5)).toFixed(2);
    const mgpa = ((majorPoints / majorCredits) * (scale / 4.5)).toFixed(2);
}
  • Crong: 정렬을 위해서 gradePoint 속성을 추가한건가요? 객체를이용하면 이를 해결할수 있을거 같아요. grademap={‘a’:4.5 ,’a+’:4.0…} 이런걸 사용하면 gardePoint를 제거할 수 있을거에요.
// 수정 전
function sortGrade(dataArr) {
    for (i = 0; i < dataArr.length; i++) {
        dataArr[i].gradePoint = fourPointFiveTable[dataArr[i]['grade']];
    }

// 수정 후 - 원래는 기존 데이터에 fourPointFiveTable에 대응하는 값이 있으면 그 값을 gradePoint에 넣도록 했는데, 아래처럼 바로 값을 가져와서 크기 비교를 하도록 수정하였다. 

function sortGrade(dataArr) {
    dataArr.sort(function (a, b) {
        return fourPointFiveTable[b.grade] - fourPointFiveTable[a.grade];
    });
  • Crong: for문을 다른 for-of 나 forEach로 수정해볼 수 있는지 검토 해주실래요?
//수정 전
    for (i = 0; i < dataArr.length; i++) {
        for (j = 0; j < dataArr.length; j++) {
            if (dataArr[i]['grade'] === dataArr[j]['grade'] && dataArr[i]['credit'] > dataArr[j]['credit']) {
                let temp = dataArr[i];
                dataArr[i] = dataArr[j];
                dataArr[j] = temp;
            }
        }
    }

//수정 후 - 이 부분은 헤드한테 forEach() 쓰는 법 도움을 받아서..ㅎ.. 풀었는데, 사실 이 전이랑 복잡도가 똑같은데 굳이 이렇게 해야되나 싶었지만 해봄... 
    dataArr.forEach((v1, i1) => {
        dataArr.forEach((v2, i2) => {
            if (dataArr[i1]['grade'] === dataArr[i2]['grade'] && dataArr[i1]['credit'] > dataArr[i2]['credit']) {
                let temp = dataArr[i1];
                dataArr[i1] = dataArr[i2];
                dataArr[i2] = temp;
            }
        })
    })

그리고 2차 피드백이 너무나 금방 왔다. 성실한 크롱크롱…


  • 위의 마지막 내용에 대한 피드백이 역시나 왔다…

    crong: 아 이부분이 틀린건 아닌데요. 배열*배열을 탐색해서 복잡도가 높은 코드에요.
    좀 간단한 방법을 고민해야 할 거 같네요.
    이미 한번 grade별로 정렬된 상태이면, 이를 활용해서 같은grade별로, sort를 사용해서 또 정렬해보세요.

  • 이 피드백을 받은 게 어제 저녁 8시 30분… 한 시간정도 고민하다가 안되서 아래같이 써놓고 집에 옴

image

  • 11시반쯤 집에 왔는데 너무나 끝내고 싶었다. 두 가지 고민이었는데
    1) grade 값이 같은 것끼리 묶은 상태에서
    2) credit 순으로 정렬을 어~~게 하느냐는 것이다.
    처음엔 아래처럼 하면 될 것 같았다.
function sortGrade(dataArr) {
    dataArr.sort(function (a, b) {
        return fourPointFiveTable[b.grade] - fourPointFiveTable[a.grade];
    });

function groupBy(dataArr, property) {
  return dataArr.reduce(function (acc, obj) {
    var key = obj[property];
    if (!acc[key]) {
      acc[key] = [];
    }
    acc[key].push(obj);
    return acc;
  }, {});
}

let groupedData = groupBy(dataArr, 'grade');
...
  • 이렇게 하면 객체 안에 학점을 key로 가진 객체들이 배열 안에 들어가게 된다.(이게 뭐야 무슨 액자식 구성도 아니고.. 구운몽…)
    { A+ : [ (과목1), (과목2) ] }
  • 근데… 저 (과목) 에 있는 credit에 어떻게 접근할 것인가… 가 문제였다. 막 짜다가 정신차려보면 또 for-in-for를 쓰고 있었다….. 우엥
  • 새벽 1시쯤에 Crong이 “이미 한번 grade별로 정렬된 상태이면, 이를 활용해서 같은grade별로, sort를 사용해서 또 정렬해보세요.”라고 말한 부분을 여러번 읽었는데, 아 그럼 grade sort한 걸로 또 할 수 있나?? 해서 아래처럼 짰더니 되는 것이다!
function sortGrade(dataArr) {
    dataArr.sort(function (a, b) {
        return fourPointFiveTable[b.grade] - fourPointFiveTable[a.grade];
    });

    dataArr.sort(function (a, b) {
        if (a.grade === b.grade) {
            return b.credit - a.credit;
        }
    });

    return dataArr;
}
  • 왜 이렇게 간단하게 되는거지… 허무하게…
    어쨌든 새벽에 PR을 날리고 잠들었다.




주말 To-Do

  1. 알고리즘 문제 풀기
  2. NextStep 객체 강의 듣고 실습해보기
  3. 알고리즘 공부: 재귀 - 피보나치
  4. CS50 week 3