728x90


뭐지.. 왜 문제 복사가 안되는거지!!!??

 

암튼.. 이제부터 블로그 제대로 작성할려고 노력..!


문제 정리

 

일단 이 문제는 제한사항을 봐야한다. (코딩테스트의 핵심은 제한사항을 잘 봐야한다!)

 

  1. 중복이 없다. 
    - 이말은 lost와 reverse 내의 원소 값이 유일해야한다는 점!
    => lost = [1,1,2,3] reserve = [2,2,3,4] 가 될 수 없다.

  2. 여벌의 체육복이 있는 학생(reserve) 도 도난 당했을 수 있다.
    - lost 값에 reserve 값이 공통적으로 존재할 수 있다는 의미!
    => lost = [1,2,3] reserve = [3,4,5] 처럼..
    그래서 문제를 보면 여벌의 체육복은 1벌 밖에 없으니 3번 학생은 체육복을 빌려줄수가 없다

>> 즉, lost와 reserve에 같은 값이 있다면 그 값은 reserve에서 제외시켜줘야한다.

 

 

step1. reserve의 요소들 중 lost에 동일하게 존재하는 값들은 모두 제거해줘야 한다. 

reserve_set = set(reserve) - set(lost)
lost_set = set(lost) - set(reserve)

//set 차집합 계산법
a = [1,3,5,6]
b = [2,4,6,8]
c = set(a) - set(b) //6이 공통

print(c) 
[1,3,5]

그걸 set 자료형으로 구현했다. set은 집합 자료형이므로객체끼리 집합 연산이 가능하다. 그래서 - 연산자를 사용하여 각 집합별로 차집합을 수행할 수 있다. 

 

step2. 예시를 보자

n lost reserve return
5 [2,4] [3,5] 5

 

 

학생 1 학생 2 학생 3 학생 4 학생 5
  x o x o

 

3, 5 번 학생은 여벌의 체육복을 갖고 있다. 4번 학생은 3번, 5번 학생으로부터 체육복을 받을 수 있다.

 

           - 4번 학생이 3번 학생의 체육복을 받았다고 가정. => 체육 시간 참가 가능

           - 2번 학생은 3번 학생의 체육복을 받을 수 있음에도 3번이 4번한테 줬기에 못 받음. => 체육 시간 참가 불가능

           - 4번 학생은 굳이 3번 학생이 빌려주지 않아도 5번 학생의 체육복을 받을 수 있음.

 

결론 : 체육복은 양 옆 학생에게 빌려줄 수 있으므로 왼쪽 요소부터 탐색 해야 함.

 

step3. 문제 풀이

def solution(n, lost, reserve):
    reserve_set = set(reserve) - set(lost)
    lost_set = set(lost) - set(reserve)
    
    for student in reserve_set:
        if student - 1 in lost_set:
            lost_set.remove(student - 1)
        elif student + 1 in lost_set:
            lost_set.remove(student + 1)
            
    answer = n - len(lost_set)
    return answer

reserve의 student -1 요소는 reserve 학생의 왼쪽 학생부터 빌려주고

만약에 없다면 오른쪽 학생을 주는 식으로 작성하면 끝

728x90
728x90

문제 설명

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할 수 있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.

아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

명함 번호가로 길이세로 길이
1 60 50
2 30 70
3 60 30
4 80 40

가장 긴 가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할 수 있습니다. 하지만 2번 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할 수 있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.

모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes가 매개변수로 주어집니다. 모든 명함을 수납할 수 있는 가장 작은 지갑을 만들 때, 지갑의 크기를 return 하도록 solution 함수를 완성해주세요.


제한사항
  • sizes의 길이는 1 이상 10,000 이하입니다.
    • sizes의 원소는 [w, h] 형식입니다.
    • w는 명함의 가로 길이를 나타냅니다.
    • h는 명함의 세로 길이를 나타냅니다.
    • w와 h는 1 이상 1,000 이하인 자연수입니다.

입출력 예sizesresult
[[60, 50], [30, 70], [60, 30], [80, 40]] 4000
[[10, 7], [12, 3], [8, 15], [14, 7], [5, 15]] 120
[[14, 4], [19, 6], [6, 16], [18, 7], [7, 11]] 133

입출력 예 설명

입출력 예 #1
문제 예시와 같습니다.

입출력 예 #2
명함들을 적절히 회전시켜 겹쳤을 때, 3번째 명함(가로: 8, 세로: 15)이 다른 모든 명함보다 크기가 큽니다. 따라서 지갑의 크기는 3번째 명함의 크기와 같으며, 120(=8 x 15)을 return 합니다.

입출력 예 #3
명함들을 적절히 회전시켜 겹쳤을 때, 모든 명함을 포함하는 가장 작은 지갑의 크기는 133(=19 x 7)입니다.

 


풀이

def solution(sizes):
    w = [] # 가로 값을 담을 빈 리스트 생성
    h = [] # 세로 값
    for i in range(len(sizes)): # sizes는 2차원 리스트
        if sizes[i][0] >= sizes[i][1]: # 조건 : 가로>=세로
            w.append(sizes[i][0]) 
            h.append(sizes[i][1]) 
        else: # 명함번호2 해당
            h.append(sizes[i][0]) 
            w.append(sizes[i][1]) 
    return max(w) * max(h)

위와 같이 풀었는데 아래와 같이 푸는 방법도 있더라..

def solution(sizes):
    w = []
    h = []
    for i in range(len(sizes)):
    	sizes[i].sort()
        w = max(w, sizes[i][0])
	h = max(h, sizes[i][1])

    return w * h

각 w, h를 비교해서 둘 중 큰 값을 한 리스트에 넣고 나머지를 리스트로 만든다. 두 개의 리스트 중 가장 큰 값을 뽑아서 곱하면 된다.

  1. w, h 리스트를 만든다.
  2. for문을 돌면서 가로와 세로 2개의 모서리 w, h 중 큰 값은 가로 w리스트에, 작은 값은 세로 h리스트에 담는다.
  3. 가로/세로 중 가장 큰 값으로 만든 사각형의 넓이인 두 개의 리스트에서 가장 큰 값이 곱한 값이 답이다.
  4. w, h중 큰 값을 모아서 그 중 큰 값과, w, h중 작은 값을 모아서 그 중 큰 값을 곱하면 간단하게 끝난다.
728x90
728x90

1. 문제

2. 풀이과정

해당 문제는 단어가 1자리부터 최대 5자리까지만 존재하므로 모든 경우를 구한 뒤에 찾는 것으로 해결하였다.

모든 경우를 찾을 때는 중복순열을 활용하여 찾아주었다.

 

  1. 중복순열을 구해주는 product 함수를 사용하기 위해 product 모듈을 불러온다. from itertools import product
  2. 중복순열을 저장해 줄 리스트를 생성한다. result = list()
  3. 최소 1자리 단어부터 최대 5자리 단어까지 존재하므로 각 자리 개수만큼 반복하며 for i in range(1, 6)
  4. 모음 리스트에서 중복을 허용하여 해당 자리 단어를 리스트로 생성한다. li = list(product(["A", "E", "I", "O", "U"], repeat=i))
  5. 중복순열을 구한 뒤 해당 순열을 하나씩 불러오며 for j in li
  6. 각 순열을 하나의 단어로 만들어 결과에 한 단어로 저장한다. result.append(''.join(k for k in j))
  7. 전부 구한 중복순열의 결과를 사전순으로 정렬한다. result.sort()
  8. 정렬한 중복순열 리스트에서 해당 단어의 인덱스를 찾아 1을 더해준 값이 정답이다. 인덱스 값으로 찾았기 때문에 번호를 붙일 때는 1을 더해줘야 한다. answer = result.index(word) + 1
 

3. 소스코드

from itertools import product

def solution(word):
    answer = 0
    
    result = list()
    for i in range(1, 6):
        li = list(product(["A", "E", "I", "O", "U"], repeat=i))
        for j in li:
            result.append(''.join(k for k in j))
        
    result.sort()
    answer = result.index(word) + 1

    return answer
728x90
728x90

문제

우리는 사람의 덩치를 키와 몸무게, 이 두 개의 값으로 표현하여 그 등수를 매겨보려고 한다. 어떤 사람의 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x, y)로 표시된다. 두 사람 A 와 B의 덩치가 각각 (x, y), (p, q)라고 할 때 x > p 그리고 y > q 이라면 우리는 A의 덩치가 B의 덩치보다 "더 크다"고 말한다. 예를 들어 어떤 A, B 두 사람의 덩치가 각각 (56, 177), (45, 165) 라고 한다면 A의 덩치가 B보다 큰 셈이 된다. 그런데 서로 다른 덩치끼리 크기를 정할 수 없는 경우도 있다. 예를 들어 두 사람 C와 D의 덩치가 각각 (45, 181), (55, 173)이라면 몸무게는 D가 C보다 더 무겁고, 키는 C가 더 크므로, "덩치"로만 볼 때 C와 D는 누구도 상대방보다 더 크다고 말할 수 없다.

N명의 집단에서 각 사람의 덩치 등수는 자신보다 더 "큰 덩치"의 사람의 수로 정해진다. 만일 자신보다 더 큰 덩치의 사람이 k명이라면 그 사람의 덩치 등수는 k+1이 된다. 이렇게 등수를 결정하면 같은 덩치 등수를 가진 사람은 여러 명도 가능하다. 아래는 5명으로 이루어진 집단에서 각 사람의 덩치와 그 등수가 표시된 표이다.

이름(몸무게, 키)덩치 등수
A (55, 185) 2
B (58, 183) 2
C (88, 186) 1
D (60, 175) 2
E (46, 155) 5

위 표에서 C보다 더 큰 덩치의 사람이 없으므로 C는 1등이 된다. 그리고 A, B, D 각각의 덩치보다 큰 사람은 C뿐이므로 이들은 모두 2등이 된다. 그리고 E보다 큰 덩치는 A, B, C, D 이렇게 4명이므로 E의 덩치는 5등이 된다. 위 경우에 3등과 4등은 존재하지 않는다. 여러분은 학생 N명의 몸무게와 키가 담긴 입력을 읽어서 각 사람의 덩치 등수를 계산하여 출력해야 한다.

입력

첫 줄에는 전체 사람의 수 N이 주어진다. 그리고 이어지는 N개의 줄에는 각 사람의 몸무게와 키를 나타내는 양의 정수 x와 y가 하나의 공백을 두고 각각 나타난다.

출력

여러분은 입력에 나열된 사람의 덩치 등수를 구해서 그 순서대로 첫 줄에 출력해야 한다. 단, 각 덩치 등수는 공백문자로 분리되어야 한다.

제한

  • 2 ≤ N ≤ 50
  • 10 ≤ x, y ≤ 200

예제 입력 1 복사

5
55 185
58 183
88 186
60 175
46 155

예제 출력 1 복사

2 2 1 2 5

풀이

 

N = int(input()) # 전체 사람 수
people = [] # 사람 정보를 받을 빈 list 생성

for _ in range(N): 
    x, y = map(int, input().split()) # 키와 몸무게 입력
    people.append((x,y)) # 그 값을 people 리스트에 추가

for i in people:
    rank = 1 # 초기값은 전부 1
    for j in people:
        if i[0] < j[0] and i[1] < j[1]: # 키와 몸무게 둘 다 커야한다는 and 조건 
            rank += 1 # 위 조건 만족 시 count + 1
    print(rank, end = " ")

문제 속에 답이 다 나와있는 문제였다.

일단, 자신보다 몸무게와 키 모두 큰 사람의 수 + 1이 자신의 덩치 등수가 되는 것을 알 수 있다.

 

=> ( 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x, y)로 표시된다. 두 사람 A 와 B의 덩치가 각각 (x, y), (p, q)라고 할 때 x > p 그리고 y > q 이라면 우리는 A의 덩치가 B의 덩치보다 "더 크다"고 말한다.

 

따라서 입력받은 몸무계와 키를 각각의 사람마다 묶어서 people 리스트에 저장해준 후,

자신보다 몸무게 그리고 키가 모두 큰 사람의 수를 세는 것으로 쉽게 해결할 수 있다. 

728x90
728x90

문제

셀프 넘버는 1949년 인도 수학자 D.R. Kaprekar가 이름 붙였다. 양의 정수 n에 대해서 d(n)을 n과 n의 각 자리수를 더하는 함수라고 정의하자. 예를 들어, d(75) = 75+7+5 = 87이다.

양의 정수 n이 주어졌을 때, 이 수를 시작해서 n, d(n), d(d(n)), d(d(d(n))), ...과 같은 무한 수열을 만들 수 있다. 

예를 들어, 33으로 시작한다면 다음 수는 33 + 3 + 3 = 39이고, 그 다음 수는 39 + 3 + 9 = 51, 다음 수는 51 + 5 + 1 = 57이다. 이런식으로 다음과 같은 수열을 만들 수 있다.

33, 39, 51, 57, 69, 84, 96, 111, 114, 120, 123, 129, 141, ...

n을 d(n)의 생성자라고 한다. 위의 수열에서 33은 39의 생성자이고, 39는 51의 생성자, 51은 57의 생성자이다. 생성자가 한 개보다 많은 경우도 있다. 예를 들어, 101은 생성자가 2개(91과 100) 있다. 

생성자가 없는 숫자를 셀프 넘버라고 한다. 100보다 작은 셀프 넘버는 총 13개가 있다. 1, 3, 5, 7, 9, 20, 31, 42, 53, 64, 75, 86, 97

10000보다 작거나 같은 셀프 넘버를 한 줄에 하나씩 출력하는 프로그램을 작성하시오.

입력

입력은 없다.

출력

10,000보다 작거나 같은 셀프 넘버를 한 줄에 하나씩 증가하는 순서로 출력한다.

예제 입력 1 복사

예제 출력 1 복사

1
3
5
7
9
20
31
42
53
64
 |
 |       <-- a lot more numbers
 |
9903
9914
9925
9927
9938
9949
9960
9971
9982
9993

 

 


흠... 일단 문제가 너무 이해가 안갔다... 그래서 끄적끄적 코드를 쳐보니 

natural = set(range(1, 10001)) 
generated = set() 

for n in range(1, 10001):
    for j in str(n):
        n += int(j) 
        
    generated.add(n) 
self_num = sorted(natural - generated) 
for i in self_num:
    print(i)

 

1. 자연수 1~ 10000을 natural set에 넣어준다. 이 친구는 생성자가 없는 숫자를 골라내기 위한 용도로 쓰인다.

2. generated set는 d(n)들을 넣어줄 set이다. 빈방 상태로 시작한다.

3. 첫 번째 for문을 돌린다. 1부터 10000까지 돌리는 이유는, 1부터 10000 사이에서 나올 수 있는 생성자를 빠짐없이 찾기 위해서다. 문제에 있는 것처럼 d(d(d(... n)))수열식으로 꼬리 물면서 찾으면, 시작점에 따라 수열이 달라지는 셀프 넘버의 특성상 코드가 복잡해진다.

 

어.. 그래... 1부터 10000까지 계산한다고 하자.... generated set에 들어가는 숫자가 중복될 수 있으면,,, 101 같은 경우는 생성자가 2갠데 어떡해? -> 이는 중복을 허용하지 않는 set으로 해결

 

4.  그럼 이제 두 번째 for문을 보자. n를 str(n)으로 바꿨다!! -> indexing 해서 자릿수 씹고 뜯고 맛보려고...!

그리고 indexing 되어 한 글자씩 뽑힌 j를 int(j)로 형 변환해준다. -> 사칙연산하려고..!... n += int(j) 하려고...!

이렇게 각 자릿수를 원래 자기 수 n에 더해주면서 d(n)이 생성!

5. 이 d(n)은 set에 인자를 넣어주는 add()를 사용해서 generated에 집어넣어 준다.

6. 그럼 이제 1부터 10000까지의 수가 들어있는 natural에서 생성자가 있는 d(n)들을 모조리 빼준다.

출력할 때 순서대로 나와야 하니까 sorted로 정렬도 해준다.

그럼.. 생성자 없는 self_num set이 완성....

for문으로 self_num 하나씩.. 하나씩 출력하면 끝

 

728x90
728x90

문제

알파벳 대소문자로 된 단어가 주어지면, 이 단어에서 가장 많이 사용된 알파벳이 무엇인지 알아내는 프로그램을 작성하시오. 단, 대문자와 소문자를 구분하지 않는다.

입력

첫째 줄에 알파벳 대소문자로 이루어진 단어가 주어진다. 주어지는 단어의 길이는 1,000,000을 넘지 않는다.

출력

첫째 줄에 이 단어에서 가장 많이 사용된 알파벳을 대문자로 출력한다. 단, 가장 많이 사용된 알파벳이 여러 개 존재하는 경우에는 ?를 출력한다.

예제 입력 1 복사

Mississipi

예제 출력 1 복사

?

예제 입력 2 복사

zZa

예제 출력 2 복사

Z

예제 입력 3 복사

z

예제 출력 3 복사

Z

예제 입력 4 복사

baaa

예제 출력 4 복사

A

words = input().upper()
unique_words = list(set(words)) 

cnt_list = []
for x in unique_words :
    cnt = words.count(x)
    cnt_list.append(cnt)  

if cnt_list.count(max(cnt_list)) > 1 :  
    print('?')
else :
    max_index = cnt_list.index(max(cnt_list)) 
    print(unique_words[max_index])

문제를 풀 때 입력받은 문자 중 중복되는 값을 제거한 리스트를 변수에 저장하고서 입력받은 문자열의 알파벳 개수를 세는데 이용했다. 빈 리스트를 생성하고서 개수를 센 수를 리스트에 추가하였고 최종적으로 수로 이루어진 리스트에서 가장 큰 값을 출력하였다. 이때, if-else 조건식을 이용해서 가장 큰 값의 개수가 여러 개인 경우 물음표를 출력하도록 했다. 

728x90
728x90

문제

알파벳 소문자로만 이루어진 단어가 주어진다. 이때, 이 단어가 팰린드롬인지 아닌지 확인하는 프로그램을 작성하시오.

팰린드롬이란 앞으로 읽을 때와 거꾸로 읽을 때 똑같은 단어를 말한다. 

level, noon은 팰린드롬이고, baekjoon, online, judge는 팰린드롬이 아니다.

입력

첫째 줄에 단어가 주어진다. 단어의 길이는 1보다 크거나 같고, 100보다 작거나 같으며, 알파벳 소문자로만 이루어져 있다.

출력

첫째 줄에 팰린드롬이면 1, 아니면 0을 출력한다.

예제 입력 1 복사

level

예제 출력 1 복사

1

예제 입력 2 복사

baekjoon

예제 출력 2 복사

0

n = list(str(input()))
if list(reversed(n)) == n:
    print(1)
else:
    print(0)
728x90
728x90

문제

도현이는 바구니를 총 N개 가지고 있고, 각각의 바구니에는 1번부터 N번까지 번호가 순서대로 적혀져 있다. 바구니는 일렬로 놓여져 있고, 가장 왼쪽 바구니를 1번째 바구니, 그 다음 바구니를 2번째 바구니, ..., 가장 오른쪽 바구니를 N번째 바구니라고 부른다. 

도현이는 앞으로 M번 바구니의 순서를 회전시키려고 만들려고 한다. 도현이는 바구니의 순서를 회전시킬 때, 순서를 회전시킬 범위를 정하고, 그 범위 안에서 기준이 될 바구니를 선택한다. 도현이가 선택한 바구니의 범위가 begin, end이고, 기준이 되는 바구니를 mid라고 했을 때, begin, begin+1, ..., mid-1, mid, mid+1, ..., end-1, end 순서로 되어있는 바구니의 순서를 mid, mid+1, ..., end-1, end, begin, begin+1, ..., mid-1로 바꾸게 된다.

바구니의 순서를 어떻게 회전시킬지 주어졌을 때, M번 바구니의 순서를 회전시킨 다음, 바구니에 적혀있는 번호를 가장 왼쪽 바구니부터 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 N (1 ≤ N ≤ 100)과 M (1 ≤ M ≤ 100)이 주어진다.

둘째 줄부터 M개의 줄에는 바구니의 순서를 바꾸는 만드는 방법이 주어진다. 방법은 i, j, k로 나타내고, 왼쪽으로부터 i번째 바구니부터 j번째 바구니의 순서를 회전시키는데, 그 때 기준 바구니는 k번째 바구니라는 뜻이다. (1 ≤ i ≤ k ≤ j ≤ N)

도현이는 입력으로 주어진 순서대로 바구니의 순서를 회전시킨다.

출력

모든 순서를 회전시킨 다음에, 가장 왼쪽에 있는 바구니부터 바구니에 적혀있는 순서를 공백으로 구분해 출력한다.

예제 입력 1 복사

10 5
1 6 4
3 9 8
2 10 5
1 3 3
2 6 2

예제 출력 1 복사

1 4 6 2 3 7 10 5 8 9

n, m = map(int, input().split())
box = [i for i in range(1, n+1)]

for i in range(m):
    i, j, k = map(int, input().split())
    box = box[:i-1]+box[k-1:j]+box[i-1:k-1]+box[j:]
print(*box)
728x90

+ Recent posts