문제

문제

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

 

코딩테스트 연습 - 문자열 압축

데이터 처리 전문가가 되고 싶은 어피치는 문자열을 압축하는 방법에 대해 공부를 하고 있습니다. 최근에 대량의 데이터 처리를 위한 간단한 비손실 압축 방법에 대해 공부를 하고 있는데, 문자

programmers.co.kr

 

처음 작성한 코드

def solution(s):
    mini = len(s)
    s = [''.join(list(i)) for i in s]
    for i in range(1,len(s)+1):
        ans = ''
        cnt = 1
        for idx in range(0,len(s),i):
            now = ''.join(s[idx:idx+i])
            if s[idx:idx+i]==s[idx+i:idx+i+i]:
                cnt += 1
                continue
            else:
                if cnt > 1:
                    ans += str(cnt)
                    cnt = 1
                ans += now
        mini = min(mini,len(ans))
    return mini
  1. 문자열을 1개 단위로 자르는 거 부터해서 len(s)개 단위까지 자르는 포문을 돌면서 진행했다.
  2. 현재 문자열과 다음 문자열이 같으면 cnt를 증가시키고
  3. 다를 시, cnt+반복된문자열 이렇게 새로운 문자열에 저장시켜놓고 그 길이를 지금까지 구해둔 mini와 비교후 더 작은 값을 mini에 넣었다.

 

깨달은 점

  • 문제를 풀 때, 처음부터 모든 경우를 풀 수 있는 로직을 짜지말고 최소한 단위를 작게하여 로직을 짜고 그걸 확장해나가는 방식으로 짜면 훨씬 수월하게 풀릴 때가 있는 것 같다.
  • level 2 치고 쉬웠던 것 같다!

'Programmers' 카테고리의 다른 글

[프로그래머스] 오픈채팅방  (0) 2021.01.19
[프로그래머스] 괄호 변환  (0) 2021.01.19
[프로그래머스] 프렌즈4블록  (0) 2021.01.17
[프로그래머스] 캐시  (0) 2021.01.15
[프로그래머스] 키패드 누르기  (0) 2021.01.14

문제

문제

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

 

코딩테스트 연습 - [1차] 프렌즈4블록

프렌즈4블록 블라인드 공채를 통과한 신입 사원 라이언은 신규 게임 개발 업무를 맡게 되었다. 이번에 출시할 게임 제목은 프렌즈4블록. 같은 모양의 카카오프렌즈 블록이 2×2 형태로 4개가 붙

programmers.co.kr

 

처음 작성한 코드

def solution(m, n, board):
    from collections import deque
    answer = 0
    board = [list(i) for i in board]
    
    while True:
        flag = 0
        for i in range(m-1):
            for j in range(n-1):
                if board[i][j]!='_' and board[i][j].upper() == board[i][j+1].upper() == board[i+1][j].upper() == board[i+1][j+1].upper():
                    board[i][j] = board[i][j].lower()
                    board[i][j+1] = board[i][j+1].lower()
                    board[i+1][j] = board[i+1][j].lower()
                    board[i+1][j+1] = board[i+1][j+1].lower()
                    flag = 1
        
        if flag == 0: return answer
        
        for j in range(n):
            cnt = 0
            lower = deque()
            upper = deque()
            for i in range(m):
                if board[i][j].islower():
                    board[i][j] = '_'
                    lower.append(board[i][j])
                    cnt+=1
                else:
                    upper.append(board[i][j])
            
            index = 0
            while lower:
                board[index][j] = lower.popleft()
                index+=1
            while upper:
                board[index][j] = upper.popleft()
                index+=1
            
            answer += cnt
  1. 4개가 모여 지워진 블록은 '_'로 변경했다.
  2. 처음에 board를 돌면서 4개가 같으면 그 값들을 모두 소문자로 변경시켰다. -> 비교할 땐 대문자로 바꿔서..
  3. flag 변수를 통해 더이상 같은 4개가 없으면 answer를 return하며 함수를 종료시켰다.
  4. 세로를 돌면서 소문자라면 lower에 넣고('_'로 변환시킨 후) 아니면 upper에 넣었다. -> upper는 아직 안 지워진 블록이기 때문에 다음 턴에서 바닥에 깔리고 그 위에가 '_'로 깔려야한다.
  5. while로 lower를 먼저 도는 이유는 인덱스가 0부터기 때문에 위에는 _로 깔리고 밑에가 영어로 깔리는게 당연하기 때문에 lower를 먼저 채웠다.
  6. 4번에서 소문자라면 cnt를 1씩 증가하고 소문자의 갯수(==지워진 블록)를 cnt로 증가시켰기 때문에 answer에 cnt를 더했다.

 

깨달은 점

  • string.islower()하면 소문자인지 대문자인지 체크해준다.
  • c언어와는 다르게 a == b == c == d 이런식으로 2개 이상 비교가 가능하다.
  • 간단한 문제였지만 접근하는 데 오래 걸린 것 같다. 푸헹

'Programmers' 카테고리의 다른 글

[프로그래머스] 괄호 변환  (0) 2021.01.19
[프로그래머스] 문자열 압축  (0) 2021.01.18
[프로그래머스] 캐시  (0) 2021.01.15
[프로그래머스] 키패드 누르기  (0) 2021.01.14
[프로그래머스] 다트 게임  (0) 2021.01.14

지금까지 사용했던 annotation을 정리해보겠다.

 

@Autowired

스프링 컨테이너에 빈으로 등록되어있는 객체를 자동으로 주입해준다.

 

@PersistenceContext

스프링에서 영속성 관리를 위해 Entity Manager가 존재한다.

그래서 스프링이 처음 시작할 때, entity manager를 만들어서 빈으로 등록을 해둔다.

entity manager는 @Autowired가 아니고 특별하게 @PersistenceContext라는 어노테이션으로 주입을 해줄 수 있다.

근데 최신 스프링부트에서는 @Autowired로도 할 수 있다고 한다.

 

@RequiredArgsConstructor

private final Member member;

라고 final로 선언한 필드가 있다고 했을 때

위 어노테이션을 사용하면 클래스에서 final 붙은 필드만 가지고 생성자를 만들어서 알아서 주입해준다.

예를 들어 아래의 코드처럼 작성하였다면

@RequiredArgsConstructor
public class MemberRepository{
	private final EntityManager em;
}

@RequiredArgsConstructor 어노테이션을 사용했기 때문에 final 붙은 필드인 em에 entity manager를 주입해준다.

무슨얘기냐 하면

public class MemberRepository{
	
    private final EntityManager em;
    
    @Autowired
    public MemberRepository(EntityManager em){
    	this.em = em;
    }

}

이렇게 긴 코드를 @RequiredArgsConstructor로 쉽게 구현할 수 있다는 것이다.

그리고 클래스에 생성자가 하나만 있으면 @Autowired를 삭제해도 알아서 빈으로 등록된 em을 주입시켜준다! 꿀팁!

 

@Transactional

db에 접근하는 모든 객체 또는 메소드 위에 @Transactional을 사용해야한다.

성공하면 commit이 되어 db에 저장되고 실패하면 rollback이 된다.

test에서는 default가 rollback이라 테스트가 진행되고 끝나면 rollback이 되어 db에 저장이 되지 않는다.

test에서도 commit 되는 것을 눈으로 확인하고 싶으면 @Rollback(false)를 써주면 된다.

 

@Test

테스트를 위한 메소드 위에 써준다.

예외를 일으키기위해 테스트코드를 짤 때 @Test(expected = IllegalStateException.class) 처럼 예상되는 예외를 써주면 예외가 났을 때 통과를 하게된다.

@Test(expected = IllegalStateException.class)
    public void 중복_회원_예외() throws Exception{
        //given
        Member member1 = new Member();
        member1.setName("kim");

        Member member2 = new Member();
        member2.setName("kim");

        //when
        memberService.join(member1);
        memberService.join(member2); 
        
        //then
        fail("예외가 발생해야 한다.");
    }

 

@SpringBootTest

통합테스트를 할 때 사용하는 어노테이션이다.

이 어노테이션을 써야지만 빈으로 등록되어있는 객체들을 다 로드해서 사용할 수 있다.

 

@Entity

도메인 객체 위에 쓴다.

도메인은 실제 db와 매칭될 클래스이다.

 

@Id @GeneratedValue

@Id - primary key와 매칭될 필드위에 쓴다.

@GeneratedValue - auto_increment와 같은 기능을 담당해준다.

 

@Column(name=" ")

테이블에서의 컬럼명을 지정해줄 수 있다.

 

@OneToMany, @OneToOne, @ManyToOne, @ManyToMany

@OneToMany - 1대다 관계에 일 때 사용한다.

@OneToOne - 1대1 관계일 때 사용, fetch 타입을 LAZY로 적용. ~ToOne 은 defaul fetch type이 EAGER이다. EAGER는 즉시로딩이라 연관된 테이블을 다 불러와서 LAZY로 쓰는 걸 권장한다.

@ManyToOne - 다대1 관계, 이 역시 fetch type을 LAZY로 사용하는 걸 권장

@ManyToMany - 대다다 관계..

 

 

 

 

 

문제

문제

 

처음 작성한 코드

def solution(cacheSize, cities):
    from collections import deque
    answer = 0
    used = deque([])
    if cacheSize==0:
        return len(cities)*5
    cities = [value.lower() for _,value in enumerate(cities)]
    for i in cities:
        if i not in used:
            if len(used) < cacheSize:
                used.append(i)
            else:
                used.popleft()
                used.append(i)
            answer+=5
        else:
            used.remove(i)
            used.append(i)
            answer+=1
    return answer
  1. cacheSize 0이면 계속 cache miss니까 예외처리 하고 시작했다.
  2. 대소문자 구별하지 않으니까 다 소문자로 바꿨다.
  3. i가 cache에 있으면 cache에 계속 존재하지만 가장 최근에 접근되었기 때문에 remove 후 append를 하여 최근 접근된 것을 표현했다.
  4. i가 cache에 없으면 제일 오래된 [0]번째에 있는 원소를 빼고 제일 마지막에 append로 현재 i를 저장한다.

 

깨달은 점

  • 잠시 잊었던 LRU 알고리즘을 다시 생각해냈다. LRU: 제일 안쓰이는 거 교체 -> 큐 사용(FIFO)
  • 2단계지만 어렵지않았다. 파이썬이랑 친해지고 있는 것 같다.

문제

문제

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

 

코딩테스트 연습 - 키패드 누르기

[1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5] "right" "LRLLLRLLRRL" [7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2] "left" "LRLLRRLLLRR" [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] "right" "LLRLLRLLRL"

programmers.co.kr

 

처음 작성한 코드

def solution(numbers, hand):
    answer = ''
    Left = [10]
    Right = [12]
    for i in numbers:
        if i == 0 : i=11
        if i in [1,4,7]:
            Left.append(i)
            answer+='L'
        elif i in [3,6,9]:
            Right.append(i)
            answer+='R'
        else:
            l1,l2 = divmod(abs(Left[-1] - i), 3)
            r1,r2 = divmod(abs(Right[-1] - i), 3)
            if l1+l2 < r1+r2:
                Left.append(i)
                answer+='L'
            elif l1+l2 == r1+r2:
                if hand=='right':
                    Right.append(i)
                    answer+='R'
                else:
                    Left.append(i)
                    answer+='L'
            else:
                Right.append(i)
                answer+='R'
    return answer
  1. '*'을 10으로, '#'을 12로 놓고 풀었다.

 

깨달은 점

  • 카카오 코테는 깔끔하다. 시키는 대로만 하면 통과다..
  • 1단계는 역시 쉬워서 내 기분을 좋게 해준다!

'Programmers' 카테고리의 다른 글

[프로그래머스] 프렌즈4블록  (0) 2021.01.17
[프로그래머스] 캐시  (0) 2021.01.15
[프로그래머스] 다트 게임  (0) 2021.01.14
[프로그래머스] 비밀지도  (0) 2021.01.13
[프로그래머스] 실패율  (0) 2021.01.13

Live Templates

인텔리제이에서 개발을 할 때, sout을 치고 tab을 누르면

이렇게 자동으로 print해주는 코드를 만들어주는 것처럼

자주 사용하는 코드를 일종의 단축어로 만들어놓으면 참으로 편리하다.

 

그래서 나는 테스트 코드를 짤 때 유용하게 사용하고 있는 라이브 템플릿 만드는 방법을 공유하고자 한다. 윈도우를 기준으로 작성할거다!

 

Live Templates 생성하기

 

1. File -> Setting에 들어간다.

 

2. Live Templates를 검색한다.

 

3. 우측에 + 버튼을 누르고 Template Group을 클릭한다.

 

4. 내가 만들 템플릿이라 custom이라고 그룹명을 지었는데 그냥 마음에 드는 이름으로 짓는다.

 

5. 지금 만든 그룹을 선택하고 이번엔 Live Template를 클릭한다.

 

6. 템플릿 이름을 정하고 설명도 써주고 코드도 써주고 Applicable도 설정해주고 OK를 누른다.

 

7. tdd(자기가 만든 템플릿 이름)을 치고 tab을 누르면 아주 잘 나오는 것을 확인할 수 있다.

 

 

 

Template text

@Test
public void $NAME$() throws Exception{
    //given
    $END$
    //when
    
    //then
}

이번에 생성한 라이브 템플릿의 코드이다.

라이브 템플릿을 통해 좀 더 간편하게 개발하자!!

:)

문제

문제

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

 

코딩테스트 연습 - [1차] 다트 게임

 

programmers.co.kr

 

처음 작성한 코드

def solution(dartResult):
    import re
    from collections import deque
    score = []
    su = deque(re.findall("(\d+)",dartResult))
    while True:
        if not dartResult: return sum(score)
        s = su.popleft()
        dartResult = dartResult[len(s):]
        s = int(s)
        b = dartResult[0]
        dartResult = dartResult[1:]
        if b == 'S': score.append(s)
        elif b == 'D': score.append(s**2)
        elif b == 'T': score.append(s**3)
        if not dartResult: return sum(score)
        if dartResult[0]=='*' or dartResult[0]=='#':
            o = dartResult[0]
            dartResult = dartResult[1:]
            if o == '*':
                if len(score)<2:
                    score[-1]*=2
                else:
                    score[-1]*=2
                    score[-2]*=2                    
            else:
                score[-1]*=(-1)
    return sum(score) 

 

코드 리뷰 후

def solution(dartResult):
    import re
    bonus = {'S':1, 'D':2, 'T':3}
    option = {'':1, '*':2, '#':-1}
    dart = re.findall('(\d+)([SDT])([*#]?)',dartResult)
    for i in range(len(dart)):
        if dart[i][2]=='*' and i>0:
            dart[i-1]*=2
        dart[i] = int(dart[i][0]) ** bonus[dart[i][1]] * option[dart[i][2]]
    return sum(dart)
  1. findall()을 하면 dart라는 리스트에 ('숫자', 'S', '*') 이런식으로 또는 옵션이 없으면 ('숫자', 'S'. '') 이렇게 빈칸을 반환해준다.
  2. bonus는 제곱수니까 점수에 ** 하고 옵션은 2배거나 -1배니까 곱하기로 나타내서 dart를 재활용한다. 그리고 *가 나올 시 그 전 점수 2배 해주는 코드도 if문으로 해결했다.

깨달은 점

  • 정규표현식은 정말 .. 이 문제에서 내가 뽑아야할 문자들이 (숫자)(S,D,T)(옵션으로 *,#) 였다. 즉 여기서 관건은 *나 #는 있으면 뽑고 없으면 안뽑는 그걸 어떻게 표현하는 지를 몰라서 한참 고민하다가 그냥 숫자만 뽑았다... 숫자는 자리수 관계없이 \d+ 이렇게 하면 되고 [SDT]는 뭐 당연한거고 [*#]? 이렇게 하면 있으면 뽑고 없으면 빈칸을 뽑아준다.. 대박!! '[]?' 이 표현식을 잘 기억해둬야겠다!
  • 내가 처음 짠 코드는 모든 조건을 if 문으로 해결했는데 다른 사람이 짠 코드를 보니 dict()을 이용하여 아주 깔끔히 잘 풀었다... 대박~ 

'Programmers' 카테고리의 다른 글

[프로그래머스] 캐시  (0) 2021.01.15
[프로그래머스] 키패드 누르기  (0) 2021.01.14
[프로그래머스] 비밀지도  (0) 2021.01.13
[프로그래머스] 실패율  (0) 2021.01.13
[프로그래머스] 튜플  (0) 2021.01.11

문제

문제

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

 

코딩테스트 연습 - [1차] 비밀지도

비밀지도 네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다

programmers.co.kr

 

처음 작성한 코드

def solution(n, arr1, arr2):
    return [j.replace('1','#').replace('0',' ') for j in [bin(arr1[i]|arr2[i])[2:].zfill(n) for i in range(n)]]
  1. arr1과 arr2을 돌면서 or 연산해서 2진수로 바꾸고 1을 #으로 바꾸고 0을 빈칸으로 바꾸고 return 했다.

 

깨달은 점

  • zfill(n) 하면 n자리수만큼 0으로 채워준다. '1'인데 n=5면 '00001'로 만들어준다~ 개쩐당!
  • bin(1) 하면 1을 2진수로 변환해주는데 이때 문자열로 반환해준다. '0b1' 이런식으로..
  • format(0b1111,'b') 하면 1111 반환해주는데 이진수 문자열은 안되고 이진수만 되서 [2:]이렇게 해서 0b를 없애버렸다.

'Programmers' 카테고리의 다른 글

[프로그래머스] 키패드 누르기  (0) 2021.01.14
[프로그래머스] 다트 게임  (0) 2021.01.14
[프로그래머스] 실패율  (0) 2021.01.13
[프로그래머스] 튜플  (0) 2021.01.11
[프로그래머스] 뉴스 클러스터링  (0) 2021.01.10

문제

문제

 

처음 작성한 코드

def solution(N, stages):
    answer = []
    stages.sort()
    for i in range(1,N+1):
        c = stages.count(i)
        if len(stages): answer.append((i,c/len(stages)))
        else: answer.append((i,0))
        stages = stages[c:]
    return [i[0] for i in sorted(answer,key=lambda x: x[1], reverse=True)]
  1. for문을 1부터 N까지 돌면서 각 단계에 도전중인 사람을 count로 찾는다.
  2. (i단계, i단계의 실패율)을 answer에 저장한다.
  3. stages를 count한 만큼 땡겨서 다음번에 length를 구할 때 count된 것을 뺼 수 있게 한다.
  4. answer에서 실패율을 key로 잡고 sort한다음 0번째 index 즉, 단계를 return 한다!

깨달은 점

  • 1단계라 그런지 쉬웠다..

'Programmers' 카테고리의 다른 글

[프로그래머스] 다트 게임  (0) 2021.01.14
[프로그래머스] 비밀지도  (0) 2021.01.13
[프로그래머스] 튜플  (0) 2021.01.11
[프로그래머스] 뉴스 클러스터링  (0) 2021.01.10
[프로그래머스] H-Index  (0) 2021.01.09