오늘 한일

  • 우아한형제들 코딩테스트를 볼 예정이였으나, 서버상의 문제로 다음 주로 연기 됐다.

  • 친구들을 만났다.

  • 백준의 백설공주 알고리즘 문제를 자바의 Stream을 이용해서 풀었다.

오늘 느낀점

  • 우아한형제들 코딩테스트를 볼 예정이였는데 codility 서버에 문제가 생겨서 시험을 못보게 됐다. 4시간짜리 시험이라 오늘 가장 큰 일정은 이거였는데 갑자기 취소되서 오늘 공부 의욕이 급 사라졌다. 주말이고 하니 오랜만에 친구들을 만나서 놀았다.

  • 백설공주 문제를 Stream만을 이용해서 만들어 본 코드다.

    public static void main(String[] args) {
      String peoples = "20\n7\n23\n19\n15\n10\n25\n8\n13";
      List<Integer> numbers = Arrays.asList(peoples.split("\n")).stream().map(Integer::parseInt).sorted().collect(Collectors.toList());
      solution(numbers);
    }
    public static void solution(List<Integer> numbers) {
      int fakerHeight = numbers.stream().mapToInt(Integer::intValue).sum() - 100;
      numbers.stream().filter(firstPeople -> !numbers.stream().filter(secondPeople -> firstPeople!= secondPeople).anyMatch(secondPeople -> firstPeople + secondPeople == fakerHeight)).forEach(System.out::println);
    }
    

    좀 익숙해졌다 싶었는데 생각보다 쉽지 않았다. 그래도 오늘 공부한 덕에 중간처리, 최종처리 개념과 filter(), forEach()는 좀 더 익숙해 진거 같다. 더 개선할 수도 있을거 같은데 현재로서는 이게 최종본이다.

  • 친구들을 보러가다 생각난건데, 왜 굳이 이렇게 복잡하게 하나 싶었는데, 그렇게 구현했을때의 몇가지 이점이 생각났다.

    public interface State
    public abstract class EndState implements State
    class Spare extends EndState  
    

    왜 굳이 이렇게 하나 싶었는데, 그렇게 구현했을때의 몇가지 이점이 생각났다.

    1. endState를 상속 받는 자식들한테 필요한 메소드를 미리 구현 해둘수 있다.

    2. 자식들한테 필요한 메소드를 새로 만들고 (예를 들면 getScore()같은)

      endState

      내가 이전에 여러 조건들로 점수를 획득 하던 부분을 이런식으로 구현 가능할 듯 싶다.

    남의 코드를 볼때 좋은점은(특히나 좋은 코드라면) 어떤 의도로 짰는지 생각해보는게 즐겁고, 생각의 폭까지 넓어진다.

내일 할일

  • 콘솔 볼링 게임 리팩토링

  • 프로그래머스 알고리즘 문제 풀기

오늘 한일

  • 볼링 진행 사항

    • 포비의 볼링 코드 일부를 봤다. 확실히 깔끔 했다. 상속과 인터페이스를 이용 하는 법에서 배웠다.

    • 도메인 주도 설계시 가장 중요한, 핵심이 되는 도메인을 먼저 만들어 나가자(당연히 도메인끼리도 중요도가 다르다.)

  • 호눅스 깃 LEVEL2 수업 참석(commit, branch..)

  • 라즈베리파이 + 슬랙 봇을 이용한 출입문 제어 장치를 만들어 봤다.

오늘 느낀점

  • 포비의 코드들이 확실히 깔끔하고 의미도 명확했다. 클래스를 쪼갠다하면 지금까지의 접근법은 쪼갤 필요성이 있는 클래스에서 지나치게 많은 기능을 위해 코드량이 길어지는 부분이 있으면 해당 기능을 담당하는 클래스를 만들어가는 식 위주로 생가했다. 이번 볼링에서의 경우라면 Frame 클래스에 점수 계산을 대신 해줄 유틸클래스를 만들까 생각했었다. 다시 작업하는 볼링에서 점수 구현 부분까지 가면 어떻게 될지 모르겠지만, 지금 봐서는 확실히 더 깔끔해질거 같다. 조건문으로 분기하는 부분들이 상속과 인터페이스 덕에 많은 간소화가 이루어 질거 같다. 인터페이스 상속에 익숙해 지자.

  • 포비의 코드를 자꾸 보면 너무 따라 할까봐 가능하면 안 볼려고하는데 계속 보게 된다. 다시 생각해보니 아직 상속과 인터페이스는 익숙하지 않으니 일단은 해당 부분을 구현하는 곳만은 따라 사용해보면서 익숙 해지는게 나을 것 같다.

  • 코드를 보다가
    public class Frame {
      private Frame next;
      public Frame bowl(int countOfPin) {
    		state = state.bowl(countOfPin);
    		if (state.isEnd()) {
    			next = new Frame(no + 1);
    			return next;
    		}
    		return this;
    	}
    }
    

    Frame이 다음 Frame이 갖는데 왜 next를 반환 할까 의문이 들었다. 심지어 isEnd()로 이 Frame이 입력이 끝난 Frame인지 확인도 안하고 점수를 넣고 본다. 처음엔 뭔가 잘못 짰나 싶었다.(한 3분간은 포비가 실수 했다는 확신을 가지고 해당 코드에 기여를 해봐야지! 하면서 어떻게 잘못 짰나 분석하고 있었다…) 그러다 다시 생각해보니 값을 입력하고 새로 생성된 state를 통해서 입력이 끝난 Frame인지 확인하고 다음 Frame을 생성하고 반환해주는 코드인거 같다. 즉, Player가 시작 Frame과 자신이 값을 입력받아야 할 Frame을 가지고 있는 구조로 설계한거 같다. 이전에 내 코드는 Frame을 순회하면 isEnd()를 확인하며 값을 입력받을 Frame을 찾아 다녔는데 이게 더 좋을 거 같다. 이건 적용해야겠다.

  • Stream을 사용하다보니 이전보다 확실히 익숙해진거 같다. 거기다 Stream을 적용 할만한 곳에 잘 사용하면 코드 작성이 더 쉬워질거 같다. 그래서 지금 진행 중인 과제에서도 적용할까 싶지만, 그러다 꼬일까봐 일단은 그러지 말고 간단한 알고리즘을 풀때는 반복적으로 Stream을 이용해보면서 Stream 사용자체에 더 익숙해지고 사용 가능한 곳을 발견 하는 눈을 기르자.

  • 호눅스의 깃 수업이 단순히 사용법에 그친것이 아니라 대략적으로 내부가 어떻게 동작하는지 알려줘서 최근 branch를 생성하며 코드를 작성하는 경우가 많았던지라 많은 도움되었다. 생각 난 김에 시간날때 생활코딩의 지옥에서 온 깃도 마저 다 봐야겠다.

  • 라즈베리파이가 참 가지고 놀기 좋은거 같다. 오늘도 덕분에 기분 전환도 된거 같다. 덤으로 자바 + 백엔드에만 집중하고 거기에 크게 관련되지 않는 분야는 관심을 안가지고 있었는데 이번에 슬랙봇을 만들면서 재밌게 놀았다. 근데 재미용에다 짧은 시간에 만든거라 동작원리의 고려 없이 라이브러리만 찾아 필요한 부분만 수정해서 만들었는데 작동원리들을 물어 볼 줄이야..

내일 할일

  • 콘솔 볼링 게임 리팩토링

  • 우아한형제들 코딩 테스트

오늘 한일

  • 볼링 진행 사항

    • Frame 추상클래스를 상속받는 NormalFrame, LastFrame로 변경 작업 진행중

    • b4와 짝 프로그래밍 진행

오늘 느낀점

  • 볼링 작업이 일부 멈췄다. 엊그제까지는 빨리 레벨2를 끝내고 레벨4 작업을 하고 싶은 마음때문에 빨리 안돼서 스스로한테 스트레스 받고 자신감도 떨어졌는데, 생각을 달리해서 현재 진행 속도가 내 성장 속도라고 인정하기로 했다. 게다가 느리게 갈때도 있고 빠르게 갈때도 있는 법이다. 다음번엔 빨리 갈수도 있을거다. 그러니 마음이 조금 편해 졌다. 거기다 바뀐 코드스쿼드 과정은 개개인의 속도에 맞추는 과정이라고 하지 않았던가? 여튼 빠르게라면 더 좋겠지만 가장 중요한건 꾸준하게란걸 잊지말자!

  • b4가 짝 프로그래밍을 하자 해서 진행 했는데 test코드를 작성하는 부분부터 많은 부분이 달라서 진행이 많이 더뎠다. 조금 의구심이 드는 방식으로 작성을 하던데 그게 ‘다른’ 방식일지 ‘틀린’ 방식인지 알 수가 없었다. 그건 그렇고 b4가 혼자 하다 많이 막혀서 다시 처음부터 같이하면서 자신감을 찾을라 했던거 같은데, 오늘은 나도 막혀서 진행을 잘 못해서 괜히 미안하다. 코드의 진행도 못하는 상태서 자잘한 테클을 많이 건거 같아 더욱 그렇다… 짝 프로그래밍도 잘하고 싶은데 아직은 어려운거 같다.

  • 사실 나 같은 경우엔 콘솔상의 볼링 게임을 이전에 구현 완료했었다. 심지어 이전이 보여지는 것 자체는 더 낫다. 단지 코드가… 그래서 잘 만들고 싶어서 다시하는 거라 성공했던 경험때문인지 스스로 케어가 되는거 같은데 b4는 그게 안돼서 더 좌절을 하고 있는거 같다. 도와주고 싶긴해도 이번 과제에서는 내 여력도(시간이 아닌 능력) 부족해서 제대로 도와주질 못하고 있다. 같은 과제를 하고 있는 사람은 단 둘 두명뿐인데 같이 잘해냈으면 좋겠다.

  • 호눅스가 말한 출입문을 라즈베리파이 + 서보모터를 열게하는 작업을 서보모터가 작동하는 수준만 잠깐 하고 자야겠다.(일단 볼링이 중요하니 길어봤자 30분만 잠깐 볼 생각이다. 볼링 작업하다 관심 안가면 안할 수도 )

내일 할일

  • 콘솔 볼링 게임 리팩토링

  • 호눅스 git 강의 참석

  • 브라이언이 가능하다면 + 내가 시간적 여유가 있다면 슬랙봇에 대해서 배워야겠다.

오늘 한일

  • 오늘자 데일리 미팅 내용 중 체크 사항

    • 월,수,금에 알고리즘 문제 같이 풀기(문제 찾는건 트램이 고생해주기 했다)

    • 단, 지각자가 있으면 지각자가 알고리즘 문제 하나 찾기.

  • 오늘자 볼링 진행 사항
    • 구현은 완료

    • 파악된 버그(첫번째 Frame에 스트라이크, 스페어가 입력되면 초기 출력에 잘못된 값 출력)

    • Frame 클래스에 집중적인 리팩토링 작업이 남았다(특히나 스트라이크, 스페어 점수 구현부)

    • 풀리를 보내봤다.

  • 알고리즘 강의의 레드블랙트리 트리에 대해 공부했다.(포스팅)

  • 소수 구하기 알고리즘 및 codility의 레벨1 문제를 풀었다.

  • stream에 대해서 좀더 보고 싶었는데 기본적인 형태만 간략히 보고 제대로 보질 못했다.

  • 이클립스에서 작업 후 습관적으로 gui환경에서 git commit을 하는 경우가 있었다. 조심하자!

오늘 느낀점

  • Frame 클래스가 그렇게 복잡하지 않았는데 스트라이크/스페어 점수 계산 처리가 들어가면서 지나치게 복잡해 졌다. 오늘은 풀리를 보내자는 목표를 위해 구현만 되는 코드를 만들어 나가다 보니 새로운 기능이 들어가면 버그가 발생하고, 해당 버그를 해결하면 다른 곳에서 발생…하는 불상사가 일어나서 버그 수정만 3시간 넘게 하고서는 겨우 풀리를 보냈다.

  • 지금 TIL을 작성하면서 생각해보니 구현만 하기 위해 문제가 생기면 임시방편으로 막아가면서 진행 했던게 기술부채가 아니였나 싶다. 그덕에 부채가 조금 쌓였을때는 큰 문제가 안됐지만 뒤로 갈수록 감당이 안됐던거 같다. 이런 작은 규모의 프로젝트에서도 이런데 큰 프로젝트에서는 더 큰 문제가 될거 같다. 규모에 상관없이 기술부채를 쌓지 않도록 조심해야겠다. (이번 사항이 기술부채에 해당하는게 맞는건지 확실치는 않지만…)

  • 소수 구하기 알고리즘을 풀면서 이중 for문이 나왔는데 알고리즘 강의를 공부하면서 반복문은 recursion(순환, 재귀)으로 변경이 가능하다 했던 말이 기억나 그렇게 변경을 해봤다. 습관적으로 반복문을 이용하는 경우가 많은데 알고리즘 문제를 풀때는 가능하면 recursion으로 풀도록 버릇을 들여봐야겠다.

  • 새벽에 레드블랙트리 강의를 봤는데 이전에도 자료구조를 공부할때 봤을때도 AVL트리와 레드블랙 트리는 균형을 맞추기 위해 막 스스로 움직이는게 신기하고 뭔가 정교한 기계 혹은 살아있는 유기체 같은 느낌이라 예쁜거(?)같다.(해당 트리를 제대로 이해 했냐 묻는다면 당연히 아니다. 바라보는 것만 좋다)

  • 알고리즘 강의는 우선순위가 높은 편이 아니니 매일 하진 말고 여유 있을때마다 해야겠다.(단, 다른 분들의 진도가 내 진도와 같아지면 그땐 다른 사람들과 진도를 맞춰봐야겠다)

내일 할일

  • 콘솔 볼링 게임 리팩토링

  • 지각 벌칙으로 금요일 알고리즘 문제 찾기

인프런의 영리한 프로그래밍을 위한 알고리즘 강좌를 보고 작성한 문서입니다.

레드블랙트리(Red-Black Tree)

BST의 경우 최악의 경우 극단적으로 밸런스가 무너진다.(계속 오른쪽 혹은 왼쪽의 자식만 있는 경우)

레드블랙 트리란?

  • 이진탐색트리의 일종

  • 균형잡힌 트리: 높이가 O(logn)

  • SEARCH, INSERT, DELETE 연산을 최악의 경우에도 O(logn) 시간에 지원


red_black_tree

  • 각 노드는 하나의 키(key), 왼쪽자식(left), 오른쪽 자식(right), 그리고 부모노드(p)의 주소를 저장

  • 자식노드가 존재하지 않을 경우 NIL 노드라고 부르는 특수한 노드가 있다고 가정

  • 따라서 모든 리프노드는 NIL노드

  • 노드들은 내부노드와 NIL노드로 분류

  • 실제 레드블랙 트리에서 NIL노드를 구현하진 않는다. 설명을 쉽게 하기 위한 용도

red_black_tree2

  • 15, 20의 밑에 NIL노드가 있다고 가정

  • 루트노드 위에도 NIL노드가 있다고 가정

  • 그림 (b)의 가장 밑의 black 노드가 NIL노드


레드블랙 트리의 정의

  1. 각 노드는 red 혹은 black이다.

  2. 루트노드는 black이다.

  3. 모든 리프노드(즉, NIL노드)는 black이다.

  4. red노드의 자식노드들은 전부 black이다.(즉, red노드는 연속되어 등장하지 않는다.)

  5. 모든 노드에 대해서 그 노드로부터 자손인 리프노드에 이르는 모든 경로에는 동일한 개수의 black노드가 존재한다.

#### 레드블랙 트리의 예)

red_black_tree_example

레드블랙 트리의 높이

  • 노드 x의 높이 h(x)는 자신으로부터 리프노드까지의 가장 긴 경로에 포함된 에지의 개수이다.(현재 노드에서 NIL노드까지 가는데 필요한 가장 많은 선의 갯수)

  • 노드 x의 블랙-높이 bh(x)는 x로부터 리프노드까지의 경로상의 블랙노드의 개수이다.(노드 x 자신은 불포함)

    red_black_tree_height


Left and Right Rotation

rb_tree_rotation

  • 탐색은 기본적으로 BST의 알고리즘에서와 같으므로 삽입, 삭제만 공부 한다.

  • Left and Right Rotation은 삽입, 삭제시 필요로 하는 기본적인 동작이다.

Left Rotation 수도코드

rb_tree_left_code

  • y = right[x] != NIL이라고 가정

  • 루트노드의 부모도 NIL이라고 가정

Left Rotation 수행시

rb_tree_left_example