import sys
N, M = map(int, sys.stdin.readline().split())
not_heard = set() #듣지 못한 사람
not_saw = set() # 보지 못한 사람
for _ in range(N):
not_heard.add(sys.stdin.readline().rstrip())
for _ in range(M):
not_saw.add(sys.stdin.readline().rstrip())
일단 집합(set)을 두 개 만들건데, 첫번째는 듣지 못한 사람이고 두번째는 보지 못한 사람이다. 아니 입력 순서가 듣-보임. 아무튼, 빈 집합을 만들고 입력 받자마자 추가하게 해 준다. 혹시나 중복되더라도 set 자료형은 알아서 중복 걸러주니까 걱정 ㄴㄴ.
not_heard_saw = not_heard & not_saw
not_heard_saw = list(not_heard_saw)
not_heard_saw.sort()
print(len(not_heard_saw))
for i in not_heard_saw:
print(i)
다음은 출력인데... 일단 아래 세 줄은 길이와 요소를 출력하는거니까 설명은 생략한다. 솔직히 이거 풀 짬이면 다들 알잖아요 뭔지...
위의 세 줄은 순서대로 1) 교집합을 구하고 2) 그걸 리스트로 바꿔서 3) 정렬하는 코드이다. 출력 사전순이니까 정렬해야지.
import sys
N, M = map(int, sys.stdin.readline().split())
not_heard = set() #듣지 못한 사람
not_saw = set() # 보지 못한 사람
for _ in range(N):
not_heard.add(sys.stdin.readline().rstrip())
for _ in range(M):
not_saw.add(sys.stdin.readline().rstrip())
not_heard_saw = not_heard & not_saw
not_heard_saw = list(not_heard_saw)
not_heard_saw.sort()
print(len(not_heard_saw))
for i in not_heard_saw:
print(i)
이거 참고로 노션에는 기록을 못한다... 차마 기록할 페이지를 어디다 만들어야 할 지 모르겠음... ㅋㅋㅋㅋㅋ
문방구 오락기에서 게임하다가 엄마한테 등짝맞던 시절... 아니 그니까 초딩때를 이야기하는거다. 아무튼, 우리가 나눗셈을 처음 배웠을 때 6 나누기 4는 몫이 1이고 나머지가 2라 1 ... 2 이런 식으로 표현했다. 근데 콤퓨타는 기본적으로 몫과 나머지따원 모르겠고 난 소수점으로 쫑낼것이다! 모드란 말이죠.
그니까 응애 애기피츄 책사죠 하던 시절의 그 나눗셈을 해보자 이겁니다. 뭘로? 파이썬으로. 왜 피츄인지는 내 닉네임을 보면 납득할 수 있을것이다. 본인이 라이츄기 때문에 유년기가 피츄인거다.
일단 나눗셈의 용어에 대해 알고 가도록 하자. 나눗셈 하면 피제수와 제수라는 두 개의 용어가 있는데(몫과 나머지도 있지만), 피제수는 나눠지는 수, 제수는 나누는 수이다. 6 나누기 3에서 6은 피제수, 3은 제수다.
전에 백준 풀이에서 부정과 불능에 대해 얘기하면서 0 나누기 0을 하게 되면 0을 빼고빼고빼고빼고빼고빼고...빼고 해야돼서 안 끝난다고 했는데, 그렇다. 피제수에서 제수를 겁나 빼는게 나눗셈이다. 30 나누기 5 하면 30에서 5를 여섯 번 빼면 된다. 언제까지? 0 될때까지. 나머지가 있다면 언제까지? 0보다 크고 제수보다 작을때까지.
import sys
X = int(sys.stdin.readline()) # 피제수
Y = int(sys.stdin.readline()) # 제수
cnt = 0
while X >= Y:
X -= Y
cnt += 1
print(cnt, X)
여기서 cnt는 몫이고, X는 피제수(였던것)가 된다. 왜 였던것이냐면 피제수가 제수보다 클때까지 빼고빼고빼고빼고...빼서 제수보다 작아지면 while문을 빠져나오기 때문.
import sys
X = int(sys.stdin.readline()) # 피제수
Y = int(sys.stdin.readline()) # 제수
cnt = 0
while X >= Y:
X -= Y
cnt += 1
print('{} ... {}'.format(cnt,X))
이렇게 하면 몫 ... 나머지로 출력되는데 아직 한가지 더 남았다. 나머지가 0이면?
import sys
X = int(sys.stdin.readline()) # 피제수
Y = int(sys.stdin.readline()) # 제수
cnt = 0
while X >= Y:
X -= Y
cnt += 1
if X == 0:
print('{}'.format(cnt))
else:
print('{} ... {}'.format(cnt,X))
아니 이게 클때로 조건을 걸어두니까 피제수에서 제수 뺄 수 있는데 걍 나머지로 짬때리더라고... 그래서 등호 추가했다. 이러면 피제수와 제수가 같아질때 한번 더 빼고 나머지가 0이 된다. 아무튼... 이렇게 if문을 추가하면 나머지가 없을때는 몫만, 나머지가 있을때는 몫 ... 나머지로 출력해준다.
import sys
X = int(sys.stdin.readline()) # 피제수
Y = int(sys.stdin.readline()) # 제수
cnt = 0
while True:
if X < Y:
break
X -= Y
cnt += 1
if X == 0:
print('{}'.format(cnt))
else:
print('{} ... {}'.format(cnt,X))
이건 While True 버전. While True는 위의 while문에 있던 조건문이 if+break 2+1 패키지로 들어간다.
일단 for문은 여기서부터 여기까지 해라지 조건부 반복문이 아니기때문에 while만 해봤는데, 이거 굳이 반복문 써야 하나요? 아뇨, 더 간소화 할 수 있는 방법이 있습니다.
import sys
X = int(sys.stdin.readline()) # 피제수
Y = int(sys.stdin.readline()) # 제수
if X % Y != 0:
print('{} ... {}'.format(X // Y, X % Y))
else:
print(X // Y)
X // Y는 몫(int(X/Y)와 같음), X % Y는 나머지다. 그러니까 X를 Y로 나눈 나머지가 0이 아니면 몫 ... 나머지로, X를 Y로 나눈 나머지가 0이면 몫만 출력하면 된다. ㅇㅋ?
자 일단 최소공배수가 뭐냐... 두 수 x, y가 있을 때 x의 배수이면서 y의 배수인 수 중 제일 작은 수가 최소공배수다. 이거 초등학생때 다 배운겁니다 여러분. 자매품으로는 최대공약수가 있는데 이건 x를 나눴을때도 나누어 떨어지고 y를 나누었을때도 나누어 떨어지는 제일 큰 수. 반대되는 개념은 왜 없냐면 최소공약수는 무조건 1이고 최대공배수는 수가 끝이 없어서 없다.
그리고 최대공약수/최소공배수 구할 때 어떻게 하냐...
저기서 왼쪽에 있는 2, 3만 곱하면 최대공약수(6)가 되고, 밑에 있는것(최종적으로 나온 몫)까지 다 곱하면 최소공배수다. 그래서 12와 18의 최대공약수는 6, 최소공배수는 36. 두 수가 서로소(공약수따원 없다네)일 경우 최대공약수가 1이기때문에 걍 깡으로 곱하면 그만이지만, 진짜 깡으로 곱해서 출력한다?
예~ 틀려요~
유클리드 호제법
그럼 여기서 저 유클리드 머시기가 왜 나왔는지를 알려주도록 하겠다. 유클리드 호제법은 자연수나 다항식의 최대공약수를 구하는 방법으로... 다항식에 그걸 써도 되는지는 모르겠으나 아무튼. 두 수가 서로(互) 상대방 수를 나누어(除)서 결국 원하는 수를 얻는 방식이라고 할 수 있다. 그래서 호제법이지 뭐 호형호제 이딴거 아님.
2개의 자연수(또는 정식) a, b에 대해서 a를 b로 나눈 나머지를 r이라 하면(단, a>b), a와 b의 최대공약수는 b와 r의 최대공약수와 같다. 이 성질에 따라, b를 r로 나눈 나머지 r'를 구하고, 다시 r을 r'로 나눈 나머지를 구하는 과정을 반복하여 나머지가 0이 되었을 때 나누는 수가 a와 b의 최대공약수이다. 아, 글로 보면 모르겠죠?
출처: 나무위키-유클리드 호제법
미안... 이걸 손으로 쓰기엔... 이거 리눅스 놋북인걸... 프레스코따원 안된다규... 아무튼 이런 느낌이다. 그럼 예시를 몇 개 할짝여보고 가도록 하자. 참고로 나무위키에는 서로소의 예시가, 위키피디아에는 최대공약수가 존재하는 예시가 있다.
위키피디아에 있는 예시는 18696과 19332의 최대공약수를 찾는 것이다. 예시에 나온 두 수의 최대공약수는 36이다. 왜? 72를 36으로 나눠서 나머지가 0이 됐으니까. 그럼 두 수가 서로소면 어떻게 해요? 서로소인 13과 6의 예시를 들어보자면 13 = 6 * 2 + 1 -> 6 = 1 * 6 + 0 이기 때문에 둘은 서로소이고, 최대공약수가 1이 된다.
그럼 다시 풀이로 돌아가보자.
다시 풀이로
그러니까 유클리드 호제법으로 두 수의 최대공약수를 구한다는것까지는 알겠는데, 이걸로 뭘 할거냐고? 위 그림을 다시 보자. 18과 12의 최대공약수는 얼마? 6이다. 유클리드 호제법으로 18 12 하면 18 = 12 * 1 + 6, 12 = 6 * 2 + 0 해서 6 나온다. 그리고 어떻게 했어요? 18을 6으로 나눠서 나온 몫 3과 12를 6으로 나눠서 나온 몫 2를 곱했다 그죠?
import sys
def Euclidean(a, b):
while b != 0:
[a, b] = [b, a%b]
return a
T = int(sys.stdin.readline())
for i in range(T):
A, B = map(int, sys.stdin.readline().split())
위에 있는 함수는 위키피디아에 파이썬 예시로 있었던 코드다. 재귀형도 있긴 한데 그거는 공약수 있으면 뺑뺑이 도느라 시간초과 날 수 있으니 걍 함수형을 쓰자. 아무튼, 이 코드는 유클리드 호제법을 이용해 세 가지 단계를 거칠거다. 첫번째, 유클리드 호제법으로 최대공약수를 구한다. 두번째, 그 최대공약수로 A와 B를 각각 나눈다. 세번째, 몫 두 개랑 최대공약수를 곱한다.
import sys
def Euclidean(a, b):
while b != 0:
[a, b] = [b, a%b]
return a
T = int(sys.stdin.readline())
for i in range(T):
A, B = map(int, sys.stdin.readline().split())
C = Euclidean(A,B) # 유클리드 호제법으로 최대공약수를 도출
LCM = C * (A // C) * (B // C) # LCM이 최소공배수였다니
print(LCM)
그래서 A, B 입력받는 밑에 두 줄이 그거다. C는 유클리드 호제법으로 구한 최대공약수, 그리고 LCM은 최소공배수. 변수 할당하고 줄 늘리기 귀찮아서 걍 한큐에 곱해버였는데 //가 안 들어가면 뭐 된다? 소수점 됩니다. 그니까 // 쓰십셔. 아니면 int 드가야되는데 귀찮기도 하고, 어차피 우리는 몫만 필요하니께(나머지가 없기도 함). 그래서 A // C는 A를 C로 나눈 몫, B // C는 B를 C로 나눈 몫이다. 그리고 C와 몫 두 개를 곱하면 LCM, 최소공배수가 된다.
밑에 있는 print문은 말 그대로 최소공배수 출력하라는 얘기. 변수 할당할 필요 없이 print문에 저 식 때려박아도 되긴 되는데 그렇게 하면 틀렸을때 수정하다가 머리터짐.... 한큐에 맞춰서 망정이지.
여기다. 여기 좋은거 많데? 근데 구슬이 서 말이라도 꿰어야 보배라는데... 뭐함? IDE 켜야죠.
class node:
def __init__(self, data):
self.data = data # 노드에 들어갈 데이터
self.next = None # 다음 노드를 가리킬 포인터
연결 리스트는 노드로 이루어져 있고, 그 노드는 데이터와 포인터로 구성되어있다. 그니까 모든 노드들이 다 이래요. 헤드(시작) 테일(끝) 뭐 다를거 없이 걍 다 노드는 똑같다. 단지 테일 노드는 포인터가 다음을 가리키지 않을 뿐. 그러면 이거 찍어내야 할 거 아뉴? 그죠 노드 찍어낼라면 틀 짜야지.
head = node(1) # 헤드(첫 노드)
head.next = node(2) # 다음 노드
head.next.next = node(3) # 다음다음 노드
다른거 없고 이렇게만 해도 노드가 세 개인 연결 리스트가 생긴다. 노드는 데이터와 포인터로 이루어져 있다고 했는데, 여기서 데이터는 각각 1, 2, 3이다. 그리고 next로 노드 1의 포인터가 2를, 2의 포인터가 3을 가리키게 했다.
node = head
while node:
print(node.data)
node = node.next
요 네 줄 추가하면 출력도 된다. while문은 대충 뭘 가리키는 애가 없는 노드(테일)까지 갈 때까지 데이터를 출력하고 다음 노드로 가시오 뭐 이런 얘기.
근데 생각해보자. 저 넥스트를 꼭 연결 리스트 만들때마다 줄줄이 소시지마냥 추가해야됨? 저거 백준 문제에서 본 적 있다고요? 네, 그 롱롱롱ㄹ오롱ㄹ오롱롱롱롱 그 문제임... 아무튼 일할때도 잔머리를 굴리는 본인 성미상 이런건 씁 에반데 소리가 절로 나온다. 다들 그렇잖음?
head = node("Pikachu")
여기 연결 리스트가 있다. 그래서 이 뒤에 피카츄의 진화체인 라이츄를 추가해볼건데... 사실 간단하게 head.next = node("raichu") 해도 되긴 된다. 근데 저게 막 25번째 노드고 그러면 넥스트 24번 정직하게 치실거임? 아니잖음...
node = head
while node:
print(node.data)
if node.next == None:
node.next = Node("Raichu")
break
node = node.next
출력이 피카츄만 나와서 글치 추가된 거 맞다. 위에 있는 while문을 조금 응용한건데, 테일 노드(하나밖에 없음...)에 도달하면 뒤에 라이츄 노드를 붙이게 된다. 그럼 헤드에 뭐 추가할때는 어떻게 하나요?
node = Node("Pichu")
node.next = head
head = node
이건 세 단계로 헤드를 바꾼(...)건데, 먼저 피츄 노드를 추가하고 피츄 노드의 포인터를 피카츄(지금 헤드)를 가리키게 한 다음 피츄 노드를 헤드로 임명했다. 라이츄는 밑에 따로 추가한거라 출력 안되는데 추가된거 맞음. 근데 왜 출력이 안될까...
빌형! VScode 이상해!
아, 사실 참고문헌에는 추가만 있어서 삭제도 따로 찾아봤다.
head = Node("Pidgey")
head.next = Node("Cyndaquil")
head.next.next = Node("Totodile")
2세대 스타팅들이 있는 노드인데 자세히 보니까... 구구가 아니라 치코리타가 와야 하는 거 아녀? 반대 아닌가
node = head
while node:
if node.data == "Pidgey":
head = head.next
node = node.next
break
node = node.next
데이터가 구구면 다음 노드가 머리가 된다 뭐 이런 얘기인데, 이거는 구구 노드가 헤드라 가능한 코드다. 원래는
node = head
while node:
if node.next.data == 5:
node.next = node.next.next
break
node = node.next
아무튼 일단 풀어야 하니 풀어봅시다. 아, 이 문제는 입력 받는 거 배열로 받고 풀 때 딕셔너리가 들어간다. 예시를 보면 아시겠지만 입력에 중복외는 숫자가 있는데 set() 쓰면 이걸 다 쳐버리거든. 입력이 딕셔너리면요? 딕셔너리도 키값 중복되면 다 쳐버린다.
X = int(sys.stdin.readline())
card_list = list(map(int, sys.stdin.readline().split()))
# 카드 입력
Y = int(sys.stdin.readline())
find_list = list(map(int, sys.stdin.readline().split()))
# 찾을거 입력
그러니까 여러분도 얌전히 입력은 리스트로 받으시는 게 정신건강에 이롭습니다.
태그 보니까 이진 탐색이 있다. 그리고 풀이법에서도 이진 탐색 알고리즘을 쓰는데... 그럼 리스트 정렬 안 해요? 뒤에 하심? 아니 그거 안씁니다. collections의 카운터를 갖다 쓸 건데 이거는 걍 counter 만들어놓고 출력만 잘 하면 된다.
import sys
from collections import Counter
X = int(sys.stdin.readline())
card_list = list(map(int, sys.stdin.readline().split()))
# 카드 입력
Y = int(sys.stdin.readline())
find_list = list(map(int, sys.stdin.readline().split()))
# 찾을거 입력
Z = Counter(card_list)
for i in find_list:
if i in card_list:
print(Z[i], end=" ")
else:
print(0, end=" ")
근데 시간초과... ㅋㅋㅋㅋㅋㅋ 아니 왜때문에?
import sys
from collections import Counter
X = int(sys.stdin.readline())
card_list = list(map(int, sys.stdin.readline().split()))
# 카드 입력
Y = int(sys.stdin.readline())
find_list = list(map(int, sys.stdin.readline().split()))
# 찾을거 입력
Z = Counter(card_list)
print(' '.join(f'{Z[m]}' if m in Z else '0' for m in find_list))
enumerate는 해시 테이블을 만들어보는 과정에서 나왔던건데, 반복문 뺑뺑이 도는 역할을 한다. 근데 이제 for문 하면 빠질 수 없는 for i in 아무개 없이 할 수 있다.
import sys
text = sys.stdin.readline().rstrip()
for i in text:
print(i)
텍스트를 입력받아서 한글자씩 출력하는 코드. for문은 이렇게 쓴다. 이건 직접 글자에 접근해서 print(i)로 출력했지만 보통은 for i in range(len(text))로 주고 print문을 작성하게 된다. 그거 말고도 가끔 그럴때 있잖음. 인덱스랑 같이 뽑고 싶잖아요? 그러면 어떻게 하냐...
import sys
text = sys.stdin.readline().rstrip()
j = 0
for i in text:
print(j, i)
j += 1
뭐 이렇게 하든가 range를 len(text)로 하고 뽑든가 함.
import sys
text = sys.stdin.readline().rstrip()
for i in enumerate(text):
print(i)
enumerate는 이렇게 쓰면 된다. 그냥 이렇게만 하면 인덱스와 요소를 튜플로 반환한다. 위 예시에서는 글자를 입력받아서 출력하는거니까 인덱스-알파벳이 쌍으로 출력되는 것이다.
이렇게 튜플로 묶어서 출력되는데... 아 이거 안이뻐... 그러면
import sys
text = sys.stdin.readline().rstrip()
for i, j in enumerate(text):
print(i,j)
for문에 변수 두 개 주면 된다. 그러면 튜플이 깔끔하게 언패킹 돼서 출력된다.
import sys
text = sys.stdin.readline().rstrip()
for i, j in enumerate(text, start=1):
print(i,j)
start= 옵션으로 시작 번호를 지정할 수도 있다. 위 코드의 경우 언패킹과 시작 번호 지정이 둘 다 된 상태.
로그 데이터는 이름이랑 상태가 있는데 상태가 enter면 출근한거고 leave면 퇴근한거다. 그니까 이걸 토대로 현재 회사에 있는 사람을 찾으면 되는데... 아 이거 머리 터진다 그죠? 근데 머리 터질 일이 1도 없음. 일단 이 문제의 카테고리가 집합인 것을 잊지 말자.
import sys
K = int(sys.stdin.readline())
person = set()
K는 로그가 몇 줄이냐는 얘기고 person은 현재 회사에 있는 사람들을 표시하기 위한 집합. set이면 중괄호 안에 들어가는 건 맞는데, 그렇다고 걍 중괄호 치면 딕셔너리 되니까 주의하자.
import sys
K = int(sys.stdin.readline())
person = set()
for _ in range(K):
who, where = sys.stdin.readline().split()
print(who, where)
그 다음은 간단하다. 입력을 받을건데, 받아서 enter면 set에 넣고, leave면 set에서 뺀다. 끝이다. 솔직히 분리돼서 들어오는거 어떻게 할 지 막막하셨쥬? 근데 입력받을 때 변수 하나만 쓰라고는 안 했다.
import sys
K = int(sys.stdin.readline())
person = set()
for _ in range(K):
who, where = sys.stdin.readline().split()
if where == 'enter':
person.add(who)
elif where == 'leave':
person.discard(who)
print(person)
이게 끝이다. set에서 뺄 때 뭐라고 하는지 까먹어서 자동완성으로 나온 discard() 썼음... discard도 버리다 뭐 이런 뜻이잖아요? 근데 이따 최종 코드를 보면 아시겠지만 discard 아니고 remove가 맞습니다. 아무튼 그럼. 그럼 우리에게 남은 건 뭐냐... 이걸 '사전 역순'으로 정렬하는건데, set은 정렬따원 되지 않는다. 그럼 어떻게 하냐고?
person = sorted(list(person))
person = reversed(person)
for i in person:
print(i)
테마가 set인거지 리스트를 쓰지 말라고는 안 했음. 리스트로 바꾸면서 sorted()로 정렬하고 그걸 reversed()로 뒤집어서 출력하면 된다.
import sys
K = int(sys.stdin.readline())
person = set()
for _ in range(K):
who, where = sys.stdin.readline().split()
if where == 'enter':
person.add(who)
elif where == 'leave':
person.remove(who)
person = sorted(list(person))
person = reversed(person)
for i in person:
print(i)
솔직히 여기서 궁금했던 사람 있을텐데, 그럼 배열 두 개가 길이가 다르면 어떻게 될까? 앞에서부터 짝이 맞는 애들끼리 묶기때문에 뒤에 있는 포름알데히드가 빠져있는 것을 알 수 있다. zip()으로 리스트를 묶을 때는 두 리스트의 0번-0번, 1번-1번 이런 식으로 순차적으로 묶기 때문에 중간에 데이터가 빠져버리면 아 망했어요가 된다.
뭔 코딩하다말고 쿠키 타령이여? 아, 먹는 쿠키 말고... 클래스를 만들건데, 이 클래스를 보통 쿠키 틀에 비유한다. 쿠키 틀로 쿠키 찍는거랑 클래스가 비슷한가봄. 그거랑 별개로 치즈쿠키 먹고싶다...
class Hash_table:
def __init__(self, length = 5):
self.max_len = length
self.table = [[] for _ in range(self.max_len)]
def hash(self, key): # 해시 테이블에 key와 value를 넣는다.
res = sum([ord(s) for s in key])
return res % self.max_len
def set(self, key, value):
index = self.hash(key)
self.table[index].append((key, value))
def get(self, key): # 해시 테이블에서 key의 value를 찾는다.
index = self.hash(key)
value = self.table[index]
if not value: # 찾는 키가 없으면 None을 반환
return None
for v in value: # 리스트에서 값을 찾아 반환
if v[0] == key:
return v[1]
return None
이게 해시 테이블을 찍어내기 위한 쿠키 틀이다. 위쪽은 해시 테이블의 길이를 정하는 것 같고... hash는 키랑 밸류를 넣는 거고, 밑에 있는 게 해시 함수다. 여기서는 아스키 코드의 총 합을 테이블의 길이로 나눠서 해시를 만드는데(해시 함수가 만드는 게 해시), 이거 입력이 한글이면 다른 방법을 써야 한다. 밑에 있는 set은 아마 키값을 넣고 변환된 해시가 나오면 그 해시에 인덱싱하는 것 같고... 그 밑에 있는 건 해시 테이블에서 키를 이용해 값을 찾는 거다.
아, 밑에 if문이요? 해시 테이블에서 값 찾았는데 없을 때 None이라고 뜨게 하라는 얘기.
if __name__ == "__main__":
capital = Hash_table()
country = ["Korea", "America", "China", "England", "Türkiye"]
city = ["Seoul", "Washington", "Beijing", "London", "Ankara"]
for co, ci in zip(country, city):
capital.set(co, ci)
print("해시 테이블의 상태")
print("===============")
for i, v in enumerate(capital.table):
print(i, v)
print()
print("해시 테이블의 검색 결과")
print("====================")
print(f"Captial of America = {capital.get('America')}")
print(f"Captial of Korea = {capital.get('Korea')}")
print(f"Captial of England = {capital.get('England')}")
print(f"Captial of China = {capital.get('China')}")
print(f"Captial of Japan = {capital.get('Japan')}")
print(f"Captial of Türkiye = {capital.get('Türkiye')}")
그래서 이 과정을 거치면 해시 테이블이 완겅된다. 검색 결과에 있는 건 말 그대로 .get을 이용해 해시 테이블에서 검색한 결과.
if __name__ == "__main__":
pokemon = Hash_table()
name = ["Metagross", "Gengar", "Raichu", "Yveltal", "Glimmora"]
nickname = ["김메탕", "최팬텀", "왕뚠뚠돈까스", "냉동차돌박이", "라피스라줄리"]
for name, nickname in zip(name, nickname):
pokemon.set(name, nickname)
print("해시 테이블의 상태")
print("===============")
for i, v in enumerate(pokemon.table):
print(i, v)
print()
print("해시 테이블의 검색 결과")
print("====================")
print(f"Metagross = {pokemon.get('Metagross')}")
print(f"Gengar = {pokemon.get('Gengar')}")
print(f"Raichu = {pokemon.get('Raichu')}")
print(f"Yveltal = {pokemon.get('Yveltal')}")
print(f"Glimmora = {pokemon.get('Glimmora')}")
print(f"Beldum = {pokemon.get('Beldum')}")
해시 메소드 건들기 싫어서 포켓몬은 영칭으로 넣었음... 아무튼. 리스트가 클래스 안에 있는 게 아니기때문에 리스트 안에 있는 건 얼마든지 바꿀 수 있다. 키값은 포켓몬의 영어 이름(그니까 이름), 밸류는 내가 실제로 지어준 닉네임이다.
아니 아스키코드 합을 5로 나눈건데 충돌만 세개 실화냐...
pokemon = Hash_table()
name = ["Swadloon", "Ferroseed", "Tinkaton", "Yveltal", "Raichu", "Nihilego", "Metagross", "Gengar", "Goodra", "Primarina", "Glimmora", "Brute Bonnet", "Iron bundle", "Heatran", "Zygarde", "Goomy", "Flutter Mane"]
nickname = ["망개떡", "김철시드", "웨폰브레이커", "냉동차돌박이", "왕뚠뚠돈까스", "김부추곱창씨", "김메탕", "김팬텀", "타로블루베리", "세탁기고장남", "라피스라줄리", "고혈압버섯", "메탈딸배몬", "모쏠드런선생", "우로보로스", "딸기바닐라", "퀘찰코아틀"]
for name, nickname in zip(name, nickname):
pokemon.set(name, nickname)
for i, v in enumerate(pokemon.table):
print(i, v)
해시 테이블을 만들 리스트 자체의 길이는 상관 없다. 길이 넘는다고 오류뜨는 거 아님.
아, 그래서 zip이랑 enu머시기는 뭐냐고? zip은 저기 리스트 두 개를 튜플로 묶어서 반환하는건데 리스트의 0번 0번끼리 묶는다. enu머시기는 반복문 도는거라는데 나중에 자세히 다뤄보겠음.
import sys
M, N = map(int,sys.stdin.readline().split())
word_list = set()
cnt = 0
for i in range(M):
a = sys.stdin.readline().rstrip()
word_list.add(a)
for i in range(N):
check = sys.stdin.readline().rstrip()
if check in word_list:
cnt += 1
print(cnt)
일단 이게 정답 맞다. 체크할 단어가 들어있는 set을 만든 다음, 체크할 단어를 입력받아서 세트에 있으면 하나씩 추가해서 세는 뭐 그런 식인데... 근데 처음에 리스트 써서 한 게 틀렸음... 근데 왜 틀린지 모르겠음... 리스트는 체크할 단어 리스트/찾을 리스트 나눠서 입력받고 다 했는데 틀려써...
그래서 질문 게시판을 찾다가 알게 된 건데, 아래 세트에는 중복되는 단어가 없다. 근데 위쪽 세트에는 중복되는 단어가 있을 수도 있다. 리스트는 중복 처리를 안하지만 세트는 중복 처리를 하기 때문에 만약 체크할 단어를 5개 받는데 그 중 하나가 중복이면 4개로 쳐버릴 수 있거든. 그것때문에 리스트는 틀렸나... 아무튼 그래요.
연립일차방정식의 해를 찾는 문제. 문제에서는 해가 존재하는 연립일차방정식을 가정한다. (그래서 이 풀이대로 짜면 답이 없을 때 출력이 없음)
풀이
이 문제를 읽은 본인의 심정:
너는 고등학교 이과 선택하지 마라... 연립일차방정식 그거 푸는거 귀찮아서 코딩할 정도면 나중에 삼각함수 미적분 극한은 어쩌려고... 공대가면 미적분방정식도 있고 그 뭐지? 적분기호인데 가운데 동그라미 꼬지해둔 것도 있음. 우리과요? 미적은 안 쓰는데 통계 합니다.
보통은 소거법 가감법 이런걸 쓰는데, 이거 브루트 포스잖아요? 그래서 일일이 넣어보는 개쌉노가다를 해야 합니다... 애초에 백준에서 mpmath를 쓰게 둘 리 없잖아요? solve 던지면 다 끝날것을...
import sys
a, b, c, d, e, f = map(int,sys.stdin.readline().split())
일단 양해를 좀 구하고 싶은 게, 백준 문제를 푸는 파이썬 파일은 하나다. 하나 풀고 새로 파일을 만드는 게 아니라(애초에 백준 풀이는 깃헙에 올리지도 않음) 그 파일 안에서 계속 푸는데, 여기에 올리면서는 지웠지만 백준 풀이에는 이전에 점근 표기법 문제 풀 때 달았던 주석이 아직도 남아있다. 주석이니까 문제 푼 건 맞았지.
for x in range(-999, 1000):
for y in range(-999, 1000):
pass
주제가 브루트포스다. 그리고 범위를 줬으면 무식하게 때려박아보는 게 순리 아니겠음?
import sys
a, b, c, d, e, f = map(int,sys.stdin.readline().split()) # 순서대로 a1 a0
for x in range(-999, 1000):
for y in range(-999, 1000):
if (a * x + b * y == c) and (d * x + e * y == f):
print(x, y)
break
연립방정식을 풀 때 소거법 가감법 이런걸 왜 하느냐... 변수가 두개라서? 놉. 해가 두 식을 다 만족해야 하기 때문이다. 그니까 ax+by=c와 dx+ey=f를 둘 다 만족하는 해를 찾는게 연립방정식을 푸는거다. 저기 미적분 붙으면 공포겠구만 아주...
아, 깜빡한 게 있다. 위에 너는 이과 오지 말아라... 근데 문과도 수학 쓰는 전공이 있습니다. 경제학과라던가... 그러니까 문제에 있는 수현이는 연립일차방정식도 귀찮아서 코딩하는 정도고 본인이 앞으로도 수학을 공부할 의지가 없다면 경제학과 가도 피똥싼다. 농담 아니고 저동네 미적 쓴다니까?
김구라짤 아니냐고요? 아니 이해도 못했다니까? 김구라짤은 그래도 뭔 문제인지 이해는 했다는 얘기예요. 근데 이건 아녀.
일단 일차식이 하나 주어진다. 그리고 c랑 n0은 뭐냐... 이 문제에서 최종적으로 확인해야 하는 건 일차식 일차항 계수와 y절편이 주어지면 일차함수 나와요 안나와요? 나옵니다. 그 일차식 일차항 n에 n0부터 100까지의 값을 넣어서 f(n) < g(n)인지를 보면 되는 문제다. 그리고 g(n) = n이므로 c * n이 된다.
예시를 보면 똑같은 일차식인데 1부터 할때는 조건을 만족하지 못하고 10부터 조건을 만족한다고 하는데... 이게 왜 이러냐... f(1) = 14, f(2) = 21 이런 식으로(f(0)이 7이다) 1부터 9까지는 f(n)이 8n보다 크다. 그러다가 10이 되면 f(10) = 77이고 8n은 80이 되기 때문에 f(n)이 8n보다 작아지게 된다.
import sys
a, b = map(int,sys.stdin.readline().split()) # 순서대로 a1 a0
c = int(sys.stdin.readline())
n = int(sys.stdin.readline()) # n0
flag = 1
for i in range(n,101):
if a * i + b > c * i:
flag = 0
break
print(flag)
flag가 왜 있냐면 조건을 만족하지 못할 때는 print(0) break를 쓰면 0 하나만 나오고 끝난다. 근데 조건을 만족하면 1이 줄창 나온 다음에 끝나그덩. 그러니까 flag를 1(True)로 설정해놓고 조건에 부합하지 않으면 flag를 0(False)으로 바꾸고 빠져나오면 되고(하나라도 안 맞으면 그냥 0), 조건에 부합하면 다 돌고 나와서 flag를 그대로 출력하는 구조.
근데 이런게 더 있을까봐 두렵다... 진짜... 이차원 배열때는 뭔지 알겠는데 어떻게 함? 이었는데 이거는 보자마자 이게 뭔 소린가 싶더라..
그럼 분모에 왜 6이 오는지는 아실텐데 왜 n * n-1 * n-2가 오는지는 이해가 안가시죠들? 위에 팩토리얼 푼 걸 보면 아시겠지만 nC3이기때문에 공식이 n!/3!(n-3)!이 되는데, 이렇게 되면 n!에서 n * n-1 * n-2만 남고 나머지는 나눠버릴 수 있다. 사실 저기서 삼중반복문? 이거 조합이네요? 하실 수도 있겠지만 아무튼.