카테고리 없음

숫자카드 나누기

수타. 2023. 6. 22. 12:01

https://school.programmers.co.kr/learn/courses/30/lessons/135807

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제설명 :

두 리스트가 주어지는데 한리스트에선 모든 숫자를 나눌수 있고, 다른 리스트에선 모든숫자에 나누어 지지 않는 숫자중 가장 큰수를 구하여라.

 

소요시간:

30분 

난이도2

 

1차시도:

import math
import heapq as hp

	
def solution(arrayA, arrayB):
	A = arrayA[0]
	B = arrayB[0]
	
	for a in arrayA[1:]:
		A = math.gcd(A,a)
	for b in arrayB[1:]:
		B = math.gcd(B,b)
	if A*B == 1: #만약 둘다 최대공약수가 1이라면 0을 리턴
		return 0
	q = []
	#리스트에 후보군을 넣기
	for i in range(2,max(A+1,B+1)):
		if A%i == 0: #1이상의 i는 A의 공약수
			hp.heappush(q,(-i,'A'))
		if B%i == 0:
			hp.heappush(q,(-i,'B'))
	piv = 1
	while q:
		num , ch = hp.heappop(q) #제일큰것부터 꺼내기
		num = -num
		if ch =='A':
			for b in arrayB:
				if b%num==0:
					piv = 0
					break
		if ch =='B':
			for a in arrayA:
				if a%num==0:
					piv = 0
					break	
		if piv : #만약에 나머지 가 나누어 떨어지는게 하나도 없다면 			
			return num
	return 0 #while문다돌았는데도 없다면

먼저 두 리스트를 앞에서 부터 두개씩 비교해서 전체의 최소 공배수를 구한후,

(세 숫자이상의 최소공배수는 두 숫자씩 최소공배수를 구하고 그 숫자와 다른숫자들의 최소공배수를 구하면됨)

 

A,B상관없이 조건에 만족하는 가장 큰수를 찾아야 하기 때문에, heap을 사용해 A,B의 최소공배수의 공약수들을 구분하여 넣어주고(heapq은 작은수 부터 반환하기 때문에, -를 붙여 넣어주었는데 생각해보니 순환하며 리스트의 내부에 숫자를 push할 일이 없으니 그냥 리스트에 넣어놓고 한번에 sort()를 하는 편이 더 나았겠다는 생각이 든다.

 

그후, 큰수부터 꺼내며, A의 최소공배수의 약수일 때는 B를 순환하며 나누어떨어지는것을 확인하고, 반대에 경우도 확인하며, 가장 큰 수가 나온다면, 바로 끝내고 반환합니다. 

 

다른 사람의 풀이:

다른사람 풀이를 보기전 짧게 reduce함수와 all함수에 대해 예시를 통해 알아보면, 

 

from functools import reduce

result = reduce(lambda x, y: x+y, [1, 2, 3, 4, 5], 100)
print(result) #115

다음과 같은데 functools에 있는 함수이며, 첫번째엔 함수, 두번째엔 iterable, 세번째엔 initializer가들어가고 안들어간다면 기본값은 None입니다. 위 예시에선 100이라는 초기값을 주었기 때문에 100부터 1을 더하고 그 값에 2를...해서 마지막 5까지더해 115를 출력하게 됩니다. 만약 마지막 100을 없앴다면 초기값을 안주었기 때문에 15를 출력할것 입니다.

 

print(all([True, False, True, True, True])) # False
print(any([True, False, False, False, False])) # True

all함수 그리고 비슷한 성격의 any 함수도 살펴보면, all함수는 말그대로 모든 것이 True일때만 True를 반환 하는 함수 인데, 위 예시에선 False가 하나 껴있기 때문에, False가 출력되고, any함수역시 말 그대로 하나라도 True인 값이 존재한다면, True를 반환하는 함수 입니다. 

 

이제 풀이를 살펴보면

from functools import reduce
from math import gcd


def solution(nums1, nums2):
    gcd1, gcd2 = reduce(gcd, nums1), reduce(gcd, nums2)
    answer = []
    if all(each % gcd2 for each in nums1):
        answer.append(gcd2)
    if all(each % gcd1 for each in nums2):
        answer.append(gcd1)
    return max(answer) if answer else 0

gcd1,gcd2에 reducd함수와 gcd함수를 이용해 한번에nums1과 nums2의 최소 공배수를 찾고,

만약 gcd2에 대해  모든 nums1이 나누어지지 않는다면 (나누었을떄 0이아니라면)  gcd2를 넣고

반대로도 한후 두값중 큰값을 반환했습니다. 

 

피드백:

위 코딩을 보고나니 제코딩에서 GCD_A값이 array_B에대해 나누어 떨어지는게있다면 그 공약수를 넣어 확인했는데, 특정값이 만약 나누어 떨어진다면 그 공약수 역시 당연히나누어 떨어지기 때문에 제 코드중 공약수에 관한부분은 삭제해도 무방합니다.