문제설명 (링크 참조)

문자열 압축

문자열의 반복되는 부분을 겹쳐서 제일 짧은 문자열을 만들어 리턴하라!

풀이

입력받은 문자열을 1~제일 크게 나눌 수 있을 때까지 나눠서 겹치는지 확인하는 문제

결국 최대 두개가 겹치는 건 길이의 1/2일때니깐 1~len(s//2) 까지 확인하면 된다.

1~len(s//2)까지 매 시행횟수에 초기값 설정.


초기값

  • arr=””
  • count=1
  • cur=s[0:i]

  • cur은 매 시행의 크기만큼 첫번째 문자열.
  • count는 현재 몇번 반복되었는지 확인

반복문을 돌면서 다음 조건을 통해 arr에 차례차례 담는다.

  1. cur과 같은 크기만큼 다음 문자열을 비교
  2. 같으면 count+=1 해주고 넘어감
  3. 다르면 count가 1이면 겹치는게 하나도 없는것이므로로 그냥 cur만 arr에 더해줌
    다르고 count가 1이 아니면 여러번 겹친것이므로 count+cur로 문자열에 더해줌

코드

def solution(s):
    answer=len(s)
    for i in range(1,len(s)//2+1):
        arr = ''
        count=1
        cur=s[0:i]
        for j in range(i,len(s),i):
            if(cur==s[j:j+i]):
                count+=1
            else:
                if(count==1):
                    arr+=cur
                else:
                    arr+=str(count)+cur
                    count=1
                cur=s[j:j+i]
        if(count==1):
            arr+=cur
        else:
            arr+=str(count)+cur

        if(answer>len(arr)):
            answer=len(arr)
    return answer

특이사항

  • 처음에 무조건 같은 크기로 나누는지 몰라서 엄청 어렵게 생각함.
    (1 + 3 + 3)이런식으로 나눠도 되는줄 알고 원래 난이도보다 훨씬 올려서 생각했다.
  • 문제를 잘 읽자...

문제설명 (링크 참조)

프로그래머스 튜플

입력받은 문자열을 확인하여 제대로 된 순서의 리스트로 변환 후 리턴

풀이

문제에서 입력받은 문자열 s에서 값들을 추출하는게 관건이었던 문제.

처음에는 리스트 형식으로 요소를 주는 줄 알았지만 하다보니 문자열로 준다는 것을 깨닫고 어떻게 문자열에서 각 요소들을 정리해서 추출할 수 있을까 고민을 많이 함.

  1. 우선 입력받은 s의 튜플 하나하나를 리스트로 바꿔준다.
  1. 리스트의 요소들을 str에서 int로 바꿔준다.
  • s[2:-2:].split('},{')를 해주면 { }전부 제외하고 각 튜플을 하나의 요소로 만들어 줄 수있다.
  • 그리고 for문을 돌며 각 요소를 다시 split(',')해주고 값들을 str에서 int로 바꿔주면 각각의 요소들을 얻을 수 있다.
  1. res 딕셔너리에 길이를 key로 저장해준다.

{{2},{2,1},{2,1,3},{2,1,3,4}} 이 문자열을
{1: [2], 2: [2, 1], 3: [2, 1, 3], 4: [2, 1, 3, 4]} 이런식으로 길이를 key값으로 얻을 수 있음.

  1. res를 반복문으로 돌면서 모든 배열의 요소를 확인하며 answer에 값을 넣어준다.

 

{{a1}, {a1, a2}, {a1, a2, a3}, {a1, a2, a3, a4}, ... {a1, a2, a3, a4, ..., an}} 의 형식이므로
res에서 길이가 1인(key값이 1인) value 부터 확인하면서 answer에 없을경우 요소 추가.

코드

def solution(s):
    res={}
    answer = []
    #입력받은 문자열은 인덱싱해서 리스트로 만들어줌
    arr=s[2:-2:].split('},{')
    for i in arr:
        a=i.split(',')
        #str을 int로 바꿔줌
        for j in range(len(a)):
            a[j]=int(a[j])
        res[len(a)]=a
    #크기가 1인 것 부터 확인하면서 answer배열에 안들어가 있으면 넣고 다음으로 넘어감.
    for i in range(1,len(res)+1):
        for j in range(len(res[i])):
            if(res[i][j] not in answer):
                answer.append(res[i][j])
                break
    return answer

특이사항

  • 다른사람풀이 보니까 여러 방법이 있는 것 같다. 정규표현식으로 한줄로 푼 괴수분을 보았다...
  • 또 정규표현식이 아니더라도 나처럼 굳이 딕셔너리를 쓰지않고 리스트를 sort해서 작성하신 분들도 보았다.

문제설명 (링크 참조)

프로그래머스 양궁 대회 문제

라이언이 어피치를 이기는 경우 중 낮은 점수를 더 많이 맞힌 경우를 리턴, 리턴 값은 10점 화살의 개수 부터 0점까지 리스트 형식으로 반환 한다.
ex [1,2,3,0,0,0,0,0,0,0,1]
단 어떠한 경우에도 못이기면 -1 리턴.

풀이

결국은 라이언이 어피치를 이기는 경우를 체크해주면 된다.

코드는 이런방법으로 작성했다.

  1. 우선 0~10의 화살을 쏠 수 있는 경우의 수를 조합을 이용해 뽑았다. (여기서 같은 점수를 여러번 맞힐 수 있으므로 중복이 가능하게 뽑아야 했다. 그래서 그냥 combinations가 아닌 combinations_with_replacement 사용.)
  2. 나온 경우의 수와 어피치의 과녁을 비교해서 라이언이 더 많이 맞힌 수는 라이언의 점수로, 어피치가 더많이 맞혔거나 같으면 어피치 점수로, 둘다 0이면 점수를 세지 않았다.

-> 여기서 여러발을 맞혀도 누적 점수가 아닌 과녁의 점수만 +해줘야한다.

  1. 점수를 체크한 뒤 라이언이 어피치보다 더 많은 점수를 획득했을 때, 가장 큰 차이로 이기는 경우를 찾아야 한다. 그래서 count 변수로 점수의 차이를 저장해놓고 현재 결과 점수가 count보다 클경우 c배열과 count 업데이트.
  2. 그렇게 찾은 조합을 점수로 변환한 후 answer에 넣어서 return

코드

from itertools import combinations_with_replacement
def solution(n, info):
    arr=[0,1,2,3,4,5,6,7,8,9,10]
    b=list(combinations_with_replacement(arr,n))
    # 가능한 모든 경우의 수를 중복 조합으로 구함.
    c=[] #결과 저장할 배열 선언
    count=0
    for i in range(len(b)):
        l=0
        a=0
        for j in range(11):
            if(info[j]<b[i].count(10-j)):
                l+=10-j
            elif(info[j]>=b[i].count(10-j) and info[j]!=0):
                a+=10-j
                #둘다 0이면 그냥 넘어간다.
        if(l<a):
            continue
        elif(l>a):
            #라이언이 이기는 경우 중에서도 최대 점수차이가 나올때만 업데이트.
            if(count<l-a):
                count=l-a
                c=b[i]

        else:
            continue
    answer=[0,0,0,0,0,0,0,0,0,0,0]
    #결과 배열이 비어있으면 -1 리턴.
    if(len(c)==0):
        return [-1]
    #결과 배열의 값을 answer배열의 인덱스로 사용해서 답 작성.
    for i in range(len(c)):
        answer[10-c[i]]+=1
    return answer

특이사항

  • 둘다 0이면 점수를 세지 않는 조건을 생각하지 않아서 몇번 틀림
  • 그리고 조건중에 “같은 점수일경우 적은 수의 과녁을 더 많이 맞힌 경우를 우선한다”라는 조건이 있었는데 딱히 신경안써도 통과해서 왜 그럴지 고민함
    → 고민한 결과 조합을 함수로 구했을 경우 배열의 앞쪽부분을 순서대로 먼저 조합으로 구함. 즉 arr이 0,1,2..순서대로 시작했기 때문에 0,1,2..순서대로 많은 조합부터 구한 것!
    그렇기 때문에 코드에서는 점수가 똑같을 경우를 생각 안하고 클때만 바꿨지만, 결국 점수가 같을 경우를 체크해도 앞에 나온게 무조건 우선일 수 밖에 없다. (상대적으로 낮은 번호의 수가 더 많기 때문에)

+ Recent posts