강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

Jespy님의 프로필 이미지
Jespy

작성한 질문수

세계 대회 진출자가 알려주는 코딩테스트 A to Z (with Python)

브루트 포스 알고리즘 [문제풀이] : BOJ 1342

섹션 3 BOJ 1342 //= 연산자 관련

해결된 질문

작성

·

40

0

안녕하세요,

코드 마지막에 순열의 중복 제거를 위한 로직을

for i in range(...):

ans //= fact(S.count(chr(i)))

 

아래처럼 직접 분모를 먼저 구하는 방식으로 구현하고 대입했는데 채점에서 풀이가 틀렸다고 나옵니다.

deno = 1

for i in range(...):

deno *= S.count(chr(i)))

ans = int(ans/deno)


순열 공식상 순열의 개수 ans/deno는 항상 정수가 나옴이 자명함에도 왜 //=를 써야 정답이 되는지 궁금합니다.

답변 3

0

Jespy님의 프로필 이미지
Jespy
질문자

import math
from itertools import permutations

s = input()

s  = list(map(ord, s))


res = 0

check = {}
for i in range(len(s)):
	check[s[i]] = check.get(s[i], 0) + 1

print(check)

for perm in permutations(s):
	for i in range(len(perm) - 1):
		if perm[i] == perm[i+1]:
			break
	else:
		res += 1

deno = 1
for i in check.values():
	deno = deno * math.factorial(i)

print(res// deno)

안녕하세요 강사님, 답변 감사드립니다.
질문에 오타가 있었습니다 ㅎㅎ

정확한 로직은 제가 위에 올려드린 코드와 같은데
백준에서는

마지막 줄을
print(res// deno) 혹은 print(int(res/deno))
라고 처리해도 오답으로 처리되고 있습니다.

sublime에서 로컬로 돌렸을 때는 정답을 내놓긴 하는데 백준에서는 계속 틀리다고 하는데 혹시 이유를 알 수 있을까요?

알리 Ally님의 프로필 이미지
알리 Ally
지식공유자

확인해 본 결과, 코드 중간에 print(check) 때문인 것 같습니다!
(print(check)를 지우고 제출하시면 됩니다. ㅎㅎ)

Jespy님의 프로필 이미지
Jespy
질문자

감사합니다!

0

알리 Ally님의 프로필 이미지
알리 Ally
지식공유자

안녕하세요, Sung Hyun Hong님!

deno *= S.count(chr(i)) 가 아닌 deno *= fact(S.count(chr(i))) 를 하셔야 합니다.
- 이 작업은 중복된 경우를 걸러주기 위한 작업이며, 이는 알파벳의 개수 S.count(chr(i))가 아닌 해당 알파벳이 자리를 바꿀 수 있는 경우의 수 fact(S.count(chr(i)))로 처리해 줘야 합니다.

 

따라서, 질문에 올려주신 코드를 아래와 같이 변경해 주시면 됩니다.

deno = 1
for i in range(ord('a'), ord('z') + 1):
    deno *= fact(S.count(chr(i)))
ans = int(ans/deno)

 


질문에 대해 만족스러운 답변이 되었기를 바랍니다!

추가로 궁금하신 점이나 더 자세한 설명이 필요하시다면 언제든지 말씀해 주세요. 😄

 

0

안녕하세요, 인프런 AI 인턴입니다. Sung Hyun Hong님.

질문하신 내용은 코드의 최종 부분에서 순열의 중복을 제거하기 위한 연산에서 //= 연산자의 사용과 관련된 것입니다. 이는 특정 계산 결과가 실수형 데이터로 처리될 수 있는 것을 방지하고, 정확한 정수 결과를 얻기 위해 사용됩니다.

// 연산자와 / 연산자의 차이

  • // 연산자는 파이썬에서 정수 나눗셈을 수행하며, 결과가 항상 정수로 반환됩니다. 한편 / 연산자는 부동소수점 나눗셈을 수행하여 결과가 실수로 표현됩니다. 따라서, 부동소수점 연산 과정에서 미세한 오차가 발생할 수 있습니다.

문제의 원인

  • 문제에서 ans //= fact(S.count(chr(i)))를 사용하여 순열의 중복을 제거한다면, 결과가 항상 정수로 보장되므로 오차 없이 정확한 정답을 반환할 수 있습니다.
  • 반면, ans = int(ans/deno) 방식은 우선 /을 통해 실수 연산을 하게 되며, 이후 int() 처리로 정수를 구하지만, 잠재적 부동소수점 오차가 반영될 수 있습니다. 이 오차는 실제 코딩 테스트 환경이나 임의의 테스트 케이스에서 오류를 유발할 수 있습니다.

권장 해결 방법

  • 정수 나눗셈이 필요한 경우에는 항상 // 연산자를 사용하는 것이 안전합니다. 이는 예상치 못한 미세한 오차로 인한 부정확한 결과를 방지합니다.

관련하여 더 깊이 있는 설명을 참고하고 싶으시다면, 브루토 포스 백준 1342 질문를 통해 자세한 사례와 솔루션을 확인할 수 있습니다. 이 링크에서는 중복된 패턴을 효율적으로 다루고 정수 연산의 중요성을 다루고 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Jespy님의 프로필 이미지
Jespy

작성한 질문수

질문하기