문제:

트럭 여러 대가 강을 가로지르는 일 차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 트럭이 1초에 1만큼 움직이며, 다리 길이는 bridge_length이고 다리는 무게 weight까지 견딥니다.
solution 함수의 매개변수로 다리 길이 bridge_length, 다리가 견딜 수 있는 무게 weight, 트럭별 무게 truck_weights가 주어집니다. 이때 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 return 하도록 solution 함수를 완성하세요.

풀이 방법:

트럭이 다리를 지나가는 과정을 그리기 위해서 다리 위에 있는 트럭들을 나타내는 overing_truck, 다리를 건너간 트럭을 나타내는 overed_truck, overing_truck에서 overed_truck으로 넘기기 위한 timer 배열을 만들었다. 그리고 총 시간을 나타내는 answer를 만들었다.
트럭이 다리를 다 지나갈 때까지 반복해야하므로 overed_truck의 배열이 truck_weights와 같아 질 때까지 반복하는 while문을 사용하였다. 그리고 다음과 같은 과정을 반복하도록 하였다.

1. 앞으로 타야할 트럭의 무게와 지금 다리 위에 있는 트럭의 무게의 합이 weight보다 작다면 다리 위에 올리고 timer에 0값을 넣어준다.
2. 1초가 지난 뒤 timer의 값을 lambda 함수를 사용해서 1초 증가시킨다.
3. 만약 timer의 첫 값(0번째 인덱스)가 다리의 길이와 같아졌다면 그 값을 빼내 다리를 지난 배열에 넣어준다.

이 과정을 while문이 깨질 때까지 반복하여 answer를 리턴하도록 하였다. 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def solution(bridge_length,weight,truck_weights):
    answer=0
    a=len(truck_weights)
    timer=[]
    overed_truck=[]
    overing_truck=[]
    while(len(overed_truck)!=a):
        answer+=1
        timer=list(map(lambda x: x+1,timer))
        if len(timer)>0:
            if timer[0]==bridge_length:
                timer.pop(0)
                b=overing_truck.pop(0)
                overed_truck.append(b)
        if len(truck_weights)>0:
            if sum(overing_truck)+truck_weights[0]<=weight:
                b=truck_weights.pop(0)
                overing_truck.append(b)
                timer.append(0)
    return answer
cs


문제:

 문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.

풀이 방법:

 제한 사항의 말이 가장 중요하다. 문자열 전체의 인덱스가 아닌 단어별로 인덱스를 따져 줘야 한다.
따라서 공백을 만날 경우 index를 초기화하는 작업을 하였고, 홀수면 lower를 사용해서 소문자로 만들었고, 짝수면 upper를 사용해서 대문자로 만들었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def solution(s):
    index= 1
    answer = ''
    for i in s:
        if i==" ":
            index=1
            answer+=' '
            continue
        elif index%2==1:
            index+=1
            answer+=i.upper()
        else:
            index+=1
            answer+=i.lower()
    return answer
cs


문제:

프로그래머스 팀에서는 기능 개선 작업을 수행 중입니다. 각 기능은 진도가 100%일 때 서비스에 반영할 수 있습니다.

또, 각 기능의 개발속도는 모두 다르기 때문에 뒤에 있는 기능이 앞에 있는 기능보다 먼저 개발될 수 있고, 이 때 뒤에 있는 기능은 앞에 있는 기능이 배포될 때 함께 배포됩니다.

먼저 배포되어야 하는 순서대로 작업의 진도가 적힌 정수 배열 progresses와 각 작업의 개발 속도가 적힌 정수 배열 speeds가 주어질 각 배포마다 몇 개의 기능이 배포되는지를 return 하도록 solution 함수를 완성하세요.

풀이 방법:

우선 각 기능마다 진도나 속도가 다르기 때문에 기능이 완성되는 날짜가 다르다. 따라서 이를 divmod를 사용해서 각 기능별로 완성이 되는 날짜 배열 complete를 만들었다.
 이후 이중반복문을 이용해서 답을 구하도록 하였다. 앞선 기능이 완성되는 날짜에 따라 배포 되는 작업이 달라진다. 예시처럼 첫 기능이 7일째에 완성이 되므로 다음 기능중 이보다 적게 걸리는 작업들은 7일과 함께 발표된다. 7일 보다 적게 걸리는 작업을 0으로 바꾸며 count를 하나씩 늘렸다. 왜냐하면 만약 적게 걸리는 작업을 제거해버린다면 반복문의 인덱스가 꼬여서 오류가 발생하기 때문이다. 이를 7일보다 많이 걸리는 작업(9일)을 만날 때까지 반복한다. 만나면 두번째 반복문을 break를 해버리고 count를 answer리스트에 추가한다. 이 반복문 작업을 마치고 나서 맨 끝 인덱스가 만약 0이 아니라면 그 작업은 따로 발표를 해야하므로 1을 추가해주도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def solution(progresses, speeds):
    complete = []
    for i in range(len(progresses)):
        a,b=divmod(100-progresses[i],speeds[i])
        if b !=0:
            complete.append(a+1)
        else:
            complete.append(a)
    answer=[]
    for i in range(len(complete)-1):
        count=1
        if complete[i] !=0:
            for j in range(i+1,len(complete)):
                if complete[i] >=  complete[j]:
                    if complete[j]==0:
                        pass
                    else:
                        count+=1
                        complete[j]=0
                else:
                    break
            answer.append(count)
    if complete[-1!=0:
        answer.append(1)
    return answer
cs


문제:

 함수 solution은 정수 n을 매개변수로 입력받습니다. n의 각 자릿수를 큰것부터 작은순으로 정렬한 새로운 정수를 리턴해주세요. 예를 들어 n이 118372면 873211을 리턴하면 됩니다.

풀이 방법:

 입력 받는 것이 정수형이기 때문에 리스트로 변환하기 위해서 string으로 변환시켜야 한다. string으로 변환한 후 리스트 상태에서 뒤집은 후 다시 join을 사용해 묶고 int형으로 변환하여 리턴하면 된다.

1
2
3
4
5
6
def solution(n):
    answer = 0
    n=list(str(n))
    n=sorted(n,reverse=True)
    answer=int("".join(n))
    return answer
cs
 


문제:

124 나라가 있습니다. 124 나라에서는 10진법이 아닌 다음과 같은 자신들만의 규칙으로 수를 표현합니다.

1. 124 나라에는 자연수만 존재합니다.
2. 124 나라에는 모든 수를 표현할 때 1,2,4만 사용합니다.

예를 들어서 124 나라에서 사용하는 숫자는 다음과 같이 변환됩니다.

 10진법

124 나라 

10진법 

124 나라 

14 

21 

22

11 

24 

12 

10 

41 


자연수 n이 매개변수로 주어질 때, n을 124 나라에서 사용하는 숫자로 바꾼 값을 return 하도록 solution 함수를 완성해 주세요.


풀이 방법:

 1~10까지의 예시를 잘 보면 3단위로 맨 오른 쪽 끝의 자리가 1,2,4가 반복 됨을 알 수 있다. 즉 124 나라의 숫자는 3의 나머지와 관련 있다는 것을 알 수 있다. 맨 오른쪽 끝 자리 이외에도 계속 1,2,4가 반복이므로 while문을 사용해서 n이 0이 될 때까지 반복하도록 한다. 이 때 divmod라는 함수를 사용했는데 divmod(a,b)로 사용을 하며 a를 b로 나눈 것의 몫과 나머지를 동시에 반환한다. 나머지가 0일 때, 몫을 1을 줄였는데 그 이유는 10진법의 1,2,3을 보면 십의 자리가 0으로 시작한다고 생각 해야 하기 때문이다. 


1
2
3
4
5
6
7
8
9
10
11
12
def solution(n):
    answer=''
    while n>0:
        n,r=divmod(n,3)
        if r==0:
            answer='4'+answer
            n-=1
        elif r==1:
            answer='1'+answer
        else:
            answer='2'+answer
    return answer
cs


문제:

 임의의 정수 n에 대해, n이 어떤 정수 x의 제곱인지 아닌지 판단하려 합니다. n이 정수 x의 제곱이라면 x+1의 제곱을 리턴하고, n이 정수 x의 제곱이 아니라면 -1을 리턴하는 함수를 완성하세요.

풀이방법:

 만약 n이 정수 x의 제곱이 아니면 n에다가 루트를 씌운 뒤에 1로 나눈다면 나머지가 발생 할 것이다. 조건문에서 0은 거짓 그 외의 수는 참으로 판별하기 때문에 이를 사용해서 문제를 해결하였다.

1
2
3
4
5
6
7
def solution(n):
    answer = n**(1/2)
    if answer%1==0:
        answer=(int(answer)+1)**2
    else:
        answer=-1
    return answer
cs


문제:

선행 스킬이란 어떤 스킬을 배우기 전에 먼저 배워야 하는 스킬을 뜻합니다.

예를 들어 선행 스킬 순서가 스파크 ->라이트닝 볼트 -> 썬더 일때, 썬더를 배우려면 먼저 라이트닝 볼트를 배워야 하고, 라이트닝 볼트를 배우려면 먼저 스파크를 배워야 합니다.

위 순서에 없는 다른 스킬(힐링 등)은 순서에 상관없이 배울 수 있습니다. 따라서 스파크 ->힐링->라이트닝 볼트->썬더 와 같은 스킬트리는 가능하지만, 썬더->스파크 나 라이트닝 볼트 ->스파크 ->힐링 -> 썬더 와 같은 스킬트리는 불가능합니다.

선행 스킬 순서 skill과 유저들이 만든 스킬트리를 담은 배열 skill_trees가 매개변수로 주어질 때, 가능한 스킬트리 개수를 return 하는 solution 함수를 작성해주세요.

풀이 방법:

skill의 인덱스를 비교했을 때 뒤의 스킬이 선행스킬보다 앞서서 있다면 잘못된 스킬트리인것이다. skill에 있는 것들이 항상 스킬트리에 있다는 보장이 없으므로 없는 것을 찾았을 때 -1을 반환하는 find를 사용했다. 따라서 나올 수 있는 경우의 수는 총 5가지이다. 편의상 이전의 스킬을 1번 스킬 이후의 스킬을 2번이라 표현한다. 

1. 1번스킬의 인덱스 < 2번스킬의 인덱스 일 때
 1번스킬이 존재하지 않고 2번스킬이 존재하거나 아니면 정상적으로 이루어져 있을 경우가 존재한다.
전자의 경우에는 잘못된 경우이므로 False로 설정하고 후자는 정상적인 경우이므로 True로 유지한채 진행한다.

2. 1번스킬의 인덱스 ==2번스킬의 인덱스 일 때
이 경우는 둘 다 -1로 같은 것 뿐이다. 예시에서 C만 존재하고 B ,D가 존재 하지 않는다면 이 또한 True이므로 그대로 진행한다.

3. 1번 스킬의 인덱스 > 2번 스킬의 인덱스  일 때
 1번스킬은 존재하지만 2번 스킬이 존재하지 않거나, 잘못 스킬트리가 구성되어 있을 경우이므로 전자는 True로 진행, 후자는 False로 설정후 종료시켰다.

이 과정이 모두 끝나고 난 뒤에도 True이면 정상적인 스킬트리이므로 answer 카운트를 증가시켰다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def solution(skill,skill_trees):
    answer_count=0
    for i in skill_trees:
        correct=True
        for j in range(1,len(skill)):
            if i.find(skill[j-1])<i.find(skill[j]):
                if i.find(skill[j-1])==-1:
                    correct=False
                    break
            elif i.find(skill[j-1])==i.find(skill[j]):
                pass
            else:
                if i.find(skill[j])==-1:
                    continue
                correct=False
                break
        if correct:
            answer_count+=1
    return answer_count
cs


문제:

두 수를 입력받아 두 수의 최대공약수와 최소공배수를 반환하는 함수, solution을 완성해 보세요. 배열의 맨 앞에 최대공약수, 그다음 최소공배수를 넣어 반환하면 됩니다. 예를 들어 두 수 3,12의 최대공약수는 3, 최소공배수는 12이므로 solution(3,12)는 [3,12]를 반환해야 합니다.

풀이 방법:

 최대공약수를 구하는 방법중 가장 좋은 방법은 유클리드 호제법을 사용하는 것이다. 작은 수의 경우에는 상관 없으나 문제와 같이 수가 커질 경우에는 유클리드 호제법이 효율적이기 때문이다. 
 유클리드 호제법이란 '정수 a,b,q,r(b!=0)에 대하여 a=bq+r이면 G(a,b)=G(b,r)가 성립한다.'라는 것이다. 따라서 이를 이용해 b가 0이 될 때가 while문을 반복하도록 해서 최대공약수를 구하도록 하였다.
최소공배수는 두 수의 곱에다가 최대공약수를 나누면 쉽게 구할 수 있다.

1
2
3
4
5
6
7
8
def solution(n, m):
    gcd=n
    multi=n*m
    while m !=0:
        gcd,m=m,gcd%m
    lcm=multi/gcd
    answer = [gcd,int(lcm)]
    return answer
cs


'Algorithm > Python' 카테고리의 다른 글

[Programmers]Lv 1. 정수 제곱근 판별  (0) 2019.01.26
[Programmers]Lv 2. 스킬트리  (0) 2019.01.25
[Programmers]Lv2. 탑  (0) 2019.01.23
[Programmers]Lv 1. 콜라츠 추측  (0) 2019.01.21
[Programmers]Lv 1. 하샤드 수  (0) 2019.01.20

문제:

 수평 직선에 높이가 서로 다른 탑  N대를 세웠습니다. 모든 탑의 꼭대기에는 신호를 송/수신하는 장치를 설치했습니다. 발사한 신호는 신호를 보낸 탑보다 높은 탑에서만 수신합니다. 또한, 한 번 수신된 신호는 다른 탑으로 송신되지 않습니다.

예를 들어 높이가 6,9,5,7,4인 다섯 탑이 왼쪽으로 동시에 레이저 신호를 발사합니다. 그러면, 탑은 다음과 같이 신호를 주고 받습니다. 높이가 4인 다섯 번째 탑에서 발사한 신호는 높이가 7인 네 번째 탑이 수신하고, 높이가 7인 네 번째 탑의 신호는 높이가 9인 두 번째 탑이, 높이가 5인 세 번째 탑의 신호도 높이가 9인 두 번째 탑이 수신합니다. 높이가 9인 두 번째 탑의 높이가 6인 첫 번째 탑인 보낸 레이저 신호는 어떤 탑에서도 수신할 수 없습니다.

맨 왼쪽에서 순서대로 탑의 높이를 담은 배열 heights가 매개변수로 주어질 때 각 탑이 쏜 신호를 어느 탑에서 받았는지 기록한 배열을 return 하도록 solution 함수를 작성해주세요.

풀이 방법:

 스택이란 모든 원소들의 삽입과 삭제가 리스트의 한쪽 끝에서만 수행되는 자료 구조로 LIFO(Last In First Out) 이라는 특징을 가지고 있다. 스택은 리스트의 끝을 Top이라고 하는데 삽입과 삭제의 연산이 top에서만 이루어져 있으므로 top 포인터는 1씩 증가 혹은 감소시킴으로써 수행한다.
 큐는 스택과 반대 구조로 리스트의 한 쪽 끝에서는 자료가 삽입되고 다른 한 쪽에서 자료가 삭제되는 자료 구조를 뜻한다. 즉 FIFO(First In First Out) 구조를 가지고 있다.
 파이썬의 리스트는 기본적으로 스택 구조를 유지한다. 따라서 append를 사용하면 리스트의 끝에 추가를 하고 pop을 하면 리스트의 끝 값이 빠져나가는 것이 그 이유이다. 우선 신호의 진행 방향이 오른쪽에서 왼쪽으로 이동을 하므로 조금 더 편하게 보기 위해서 reverse 함수를 사용해서 방향을 바꾸어 확인하였다. 송신하는 탑의 인덱스를 i 의 값으로 수신하는 탑의 인덱스를 j 로 하여 송신 탑보다 높은 수신 탑을 찾도록 하였다. 만약 찾았다면 reverse 함수를 사용해서 인덱스를 뒤집었으므로 길이에서 수신 탑의 인덱스를 빼서 원래 수신 탑의 인덱스를 집어 넣도록 하였다. 또한 count 값을 설정해서 끝까지 갈 동안 수신 탑을 못 찾을 경우에 0을 넣도록 하였다. 항상 모든 경우에 가장 왼쪽의 탑은 수신을 받을 탑이 없기에 반복문이 끝난 뒤 0을 넣고 난 뒤 다시 원래의 값을 얻기 위해 reverse 함수를 사용해서 원래대로 돌렸다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def solution(height):
    answer = []
    height.reverse() #오른쪽에서 왼쪽으로 송신하므로
    for i in range(len(height)):
        count=0 #송신하는 탑과 수신하는 탑의 차이
        for j in range(i+1,len(height)):
            count+=1
            if height[i] < height[j]:
                answer.append(len(height)-j)
                break
            else:
                if count==len(list(range(i+1,len(height)))): #수신하는 탑이 없이 끝까지 도달 했을 경우
                    answer.append(0)
                    break
    answer.append(0#맨 왼쪽에 있던 탑은 항상 수신하는 탑이 없다.
    answer.reverse()
    return answer
cs
  


문제:

1937년 Collatz란 사람에 의해 제기된 이 추측은, 주어진 수가 1이 될 때까지 다음 작업을 반복하면, 모든 수를 1로 만들 수 있다는 추측입니다. 작업능 다음과 같습니다.

1-1. 입력된 수가 짝수라면 2로 나눕니다.
1-2. 입력된 수가 홀수라면 3을 곱하고 1을 더합니다.
2. 결과로 나온 수에 같은 작업을 1이 될 때까지 반복합니다.

위 작업을 몇 번이나 반복해야하는지 반환하는 함수, solution을 완성해 주세요. 단 작업을 500번을 반복해도 1이 되지 않는다면 -1을 반환해 주세요.

풀이 방법:


 500번은 시도를 해봐야 하므로 이를 for 반복문이나 while 반복문을 사용해야 하는데 for 반복문을 사용했다. 우선 숫자가 1인지 확인을 하고 난 뒤에 아니라면 작업을 수행하도록 하였다. 만약 반복문 내에서 1이 되지 않았다면 -1을 반환토록 하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
def solution(num):
    answer = 0
    for i in range(500):
        if num == 1:
            return answer
        else:
            if num%2==0:
                num=num//2
                answer+=1
            else:
                num=num*3+1
                answer+=1
    return -1
cs

문제 링크:

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



+ Recent posts