파이썬 기초 다지기 3

류한선·2025년 7월 5일

실기연습-2

목록 보기
90/95

좋아!
지금부터 파이썬의 itertools 모듈을 이용해서 백트래킹(완전탐색) 문제를 푸는 방법
실제 정보처리기사 실기나 코딩테스트에서 나올 법한 예제로 완전 해부해줄게.


✅ 문제 예제:

1~4 사이 숫자 중에서 3개를 뽑아 나열한 모든 순열 출력하기
(단, 같은 숫자는 한 번만 사용할 수 있음)


✅ 요구 사항 요약

  • 1~4 사이 숫자 → [1, 2, 3, 4]
  • 순열(순서 O)
  • 중복 없이 3개 선택
  • 결과 예시:
(1, 2, 3)
(1, 2, 4)
(1, 3, 2)
...

✅ 1. itertools.permutations() 사용

from itertools import permutations

data = [1, 2, 3, 4]

for case in permutations(data, 3):
    print(case)

🔍 해설:

  • permutations(data, 3)
    data에서 3개를 뽑아 순서 있게 나열하는 모든 경우를 반환
  • 반환 결과는 튜플(tuple) 형태

✅ 디버깅 흐름 보기:

순번case 값 (튜플)
1(1, 2, 3)
2(1, 2, 4)
3(1, 3, 2)
24(4, 3, 2)

📌 총 결과: 4P3 = 4 × 3 × 2 = 24개 조합


✅ itertools를 백트래킹처럼 활용하는 이유

  • 원래 백트래킹 알고리즘은 보통 재귀(recursion) 기반으로 직접 구현하지만
  • itertools.permutations(), combinations() 등을 쓰면 그 자체가 완전탐색 결과를 만들어줌

✅ 추가 문제: 조합

🔹문제:

1~5 중에서 숫자 3개를 골라서 (순서 상관없이) 출력

from itertools import combinations

for comb in combinations([1, 2, 3, 4, 5], 3):
    print(comb)

📌 이건 5C3 = 10개의 조합


✅ 만약 조건을 걸고 싶다면?

예제:

1~4 중 3개를 골라 만들었을 때 합이 6인 경우만 출력

from itertools import permutations

data = [1, 2, 3, 4]

for case in permutations(data, 3):
    if sum(case) == 6:
        print(case)

✅ 조건을 걸면 → 백트래킹의 가지치기(pruning)과 유사한 효과


✅ 실전 사용 꿀팁

함수의미예시
permutations(data, r)순서 O, 중복 X4P3
combinations(data, r)순서 X, 중복 X5C3
product(data, repeat=r)순서 O, 중복 O중복 순열
combinations_with_replacement(data, r)순서 X, 중복 O중복 조합

✅ 직접 백트래킹으로 구현하면 이렇게 됨 (비교용)

def backtrack(path, used):
    if len(path) == 3:
        print(path)
        return
    for i in range(4):
        if not used[i]:
            used[i] = True
            backtrack(path + [data[i]], used)
            used[i] = False

data = [1, 2, 3, 4]
used = [False]*4
backtrack([], used)

✅ 이건 재귀 백트래킹
→ 같은 결과를 itertools.permutations()으로도 쉽게 얻을 수 있음


✅ 정리

방식장점단점
itertools 사용간단하고 빠름복잡한 조건엔 비효율적
재귀 백트래킹유연한 조건 처리 가능코드 복잡함

좋아! 너가 딱 잘 짚었어.
아래 코드를 줄마다 **"이 줄에서 지금 무슨 일이 벌어지고 있는가?"**를 기준으로
완전 초보자 기준에서 1줄도 빠짐없이 해부해줄게.
그리고 실제로 값이 어떻게 만들어지는지도 하나하나 시각화해서 설명해줄게.


✅ 코드 전체

from itertools import permutations

data = [1, 2, 3, 4]

for case in permutations(data, 3):
    print(case)

✅ [1] from itertools import permutations

📌 이 줄은 무슨 역할?

  • 파이썬의 표준 라이브러리 모듈 itertools 중에서 permutations 함수만 가져온다

📌 왜 여기 있어야 해?

  • permutations는 기본 내장 함수가 아니라 itertools 안에 있음 → 사용하려면 먼저 import 해야 함

📌 실행 순서?

  • 코드가 실행되면 가장 먼저 permutations를 쓸 수 있도록 가져와서 준비함

✅ [2] data = [1, 2, 3, 4]

📌 역할?

  • 순열을 만들기 위한 기초 리스트 생성
  • 지금 우리가 사용할 원소는 1, 2, 3, 4

📌 실행 순서?

  • 리스트를 만들고 이름을 data로 저장

📌 값:

data = [1, 2, 3, 4]

✅ [3] for case in permutations(data, 3):

이 줄이 가장 중요하니까 완전 자세히 쪼개서 설명할게.


✅ 💡 핵심 용어: permutations(data, 3)

  • 이건 data 리스트에서 3개를 선택해서 만들 수 있는 모든 순열을 만들어주는 함수야.
  • 즉, 순서가 중요하고 중복 없이 3개 뽑는 경우를 모두 반환해.

✔ 예시:

data = [1, 2, 3, 4] 에서
3개를 뽑아 만들 수 있는 순열:

(1, 2, 3)
(1, 2, 4)
(1, 3, 2)
(1, 3, 4)
(1, 4, 2)
(1, 4, 3)
(2, 1, 3)
(2, 1, 4)
...
(4, 3, 2)

➡ 총 24개 (4P3 = 4 × 3 × 2 = 24)


✅ 어떻게 동작하는가?

for case in permutations(data, 3):

이건 아래와 같이 동작해:

permutations(data, 3)[(1,2,3), (1,2,4), (1,3,2), ..., (4,3,2)] ← 이터레이터(반복 가능한 값들)를 반환

for case in ...:
    print(case)

→ 이 순열들을 하나씩 꺼내서 case에 넣고
case는 매번 (a,b,c) 같은 튜플이 됨


✅ [4] print(case)

📌 역할?

  • 앞 줄에서 얻은 각 순열 튜플을 화면에 출력

📌 예시:

(1, 2, 3)
(1, 2, 4)
...

✅ 실행 흐름 요약

루프 횟수case 값
1번째(1, 2, 3)
2번째(1, 2, 4)
3번째(1, 3, 2)
......
24번째(4, 3, 2)

✅ 시각화 정리

data = [1, 2, 3, 4]

가능한 순열 (3개 뽑기, 순서 O, 중복 X):

1. (1, 2, 3)
2. (1, 2, 4)
3. (1, 3, 2)
...
24. (4, 3, 2)

→ 하나씩 case 변수에 담겨서 출력됨

✅ 궁금할 수 있는 포인트 요약

궁금한 점설명
왜 튜플로 나오지?permutations() 함수는 튜플로 반환함 (변경 불가능한 순서 쌍)
왜 3개만 뽑아?두 번째 인자에 3을 줬기 때문 (r=3)
중복된 숫자 나오면?원본 리스트에 중복이 있으면 결과에도 중복 순열이 생김
순서 바뀌면 다른 거야?응, 순열이니까 (1, 2, 3)(2, 1, 3)은 다른 경우야

✅ 지금 흐름 완전히 이해했는지 체크 문제

from itertools import permutations

data = [5, 6, 7]
for p in permutations(data, 2):
    print(p)

❓ 결과는 총 몇 개? 어떤 식으로 출력될까?

  • 👉 결과 개수: 3P2 = 3 × 2 = 6
  • 👉 출력:
(5, 6)
(5, 7)
(6, 5)
(6, 7)
(7, 5)
(7, 6)

좋아! 이 코드를 너가 진짜로 완벽하게 이해할 수 있도록
지금부터 아주 천천히, 한 줄씩 디버깅 흐름처럼 초보자 눈높이로 쪼개서 설명해줄게.

이전 permutations()과도 비교하면서, 무엇이 다르고 왜 그렇게 동작하는지도 정확히 잡아줄게.


✅ 전체 코드

from itertools import combinations

for comb in combinations([1, 2, 3, 4, 5], 3):
    print(comb)

🔹 이 코드는 뭘 하는 코드인가?

  • [1, 2, 3, 4, 5] 중에서
  • 서로 다른 3개의 숫자를 선택하되, 순서 상관 없이
  • 가능한 모든 조합(combinations)을 만들어서 출력하는 코드야.

✅ 한 줄씩 해부 설명


✅ 1️⃣ from itertools import combinations

📌 무슨 역할?

  • 파이썬의 표준 라이브러리 itertools에서 combinations() 함수만 불러옴

📌 왜 있어야 해?

  • combinations()는 기본 내장 함수가 아님 → import 안 하면 에러남

✅ 2️⃣ for comb in combinations([1, 2, 3, 4, 5], 3):

이게 핵심이야. 이 줄을 완전히 뜯어서 설명할게.


🔸 combinations([1, 2, 3, 4, 5], 3)

  • 리스트 [1, 2, 3, 4, 5]에서
  • 3개를 뽑는 모든 조합을 반환한다
  • 조합이기 때문에 순서가 중요하지 않음!

🔹 예를 들어

조합설명
(1, 2, 3)1, 2, 3 뽑음
(1, 2, 4)1, 2, 4 뽑음
......
(3, 4, 5)마지막 조합

총 몇 개일까?

5C3 = 5! / (3! * (5-3)!) = 10

🔸 for comb in ...:

  • combinations(...)튜플들의 이터레이터를 반환해
  • 이 튜플들을 comb 변수에 하나씩 꺼내서 반복

✅ 3️⃣ print(comb)

  • 각 조합 튜플을 화면에 출력함

✅ 전체 실행 결과 (순서 보장)

(1, 2, 3)
(1, 2, 4)
(1, 2, 5)
(1, 3, 4)
(1, 3, 5)
(1, 4, 5)
(2, 3, 4)
(2, 3, 5)
(2, 4, 5)
(3, 4, 5)

combinations()permutations() 차이 정리

항목combinations()permutations()
순서상관 없음 ❌순서 중요 ✅
(1,2,3) vs (3,2,1)같은 조합다른 순열
예제복권 번호 뽑기자리를 배치할 때
결과 수nCr (작음)nPr (큼)

✅ 시각화 예제

입력 리스트: [1, 2, 3, 4, 5]
선택 개수: 3

가능한 조합 (순서 X):
--------------------------------
1. (1, 2, 3)
2. (1, 2, 4)
3. (1, 2, 5)
4. (1, 3, 4)
5. (1, 3, 5)
6. (1, 4, 5)
7. (2, 3, 4)
8. (2, 3, 5)
9. (2, 4, 5)
10. (3, 4, 5)

✅ 궁금할 수 있는 점 정리

궁금한 점설명
왜 튜플로 나와?itertools.combinations()이 튜플로 결과 반환함
중복 허용 안 돼?응, 기본 combinations()은 중복 없이 뽑음
순서 바뀌면 다른 조합이야?아니야, (1, 2, 3)(3, 2, 1)은 같은 조합이라 한 번만 나와

✅ 확장 예제: 조건 걸기

from itertools import combinations

for comb in combinations([1, 2, 3, 4, 5], 3):
    if sum(comb) == 10:
        print(comb)

조합 중 합이 10인 것만 출력


좋아, 이제 이어서 파이썬 실전 트랩 14번, 15번을 완전히 해부해줄게.
이 두 개는 실제 정보처리기사 실기나 알고리즘 문제에서도 자주 혼동해서 틀리는 부분이야.


✅ 14. in 연산자 동작 방식 (문자, 리스트, 딕셔너리 다 다름)


✅ 기본 개념

파이썬에서 in 연산자는

"이 값이 이 안에 있니?" 라는 질문을 할 때 사용하는 연산자야.

그런데 자료형에 따라 동작 방식이 미묘하게 다르다는 걸 꼭 알고 있어야 해.


🔸 문자열에서 in

print('a' in 'apple')  # True
print('pp' in 'apple')  # True
print('x' in 'apple')   # False

✔️ 문자열 안에 해당 문자 또는 문자열이 포함되어 있는지 확인
→ 부분 문자열 검색


🔸 리스트에서 in

print(3 in [1, 2, 3])  # True
print(5 in [1, 2, 3])  # False

✔️ 리스트 안에 해당 요소가 존재하는지


🔸 딕셔너리에서 in

d = {'a': 1, 'b': 2}
print('a' in d)      # ✅ True
print(1 in d)        # ❌ False
print('b' in d.keys())  # ✅ True
print(2 in d.values())  # ✅ True

📌 딕셔너리에서 in은 기본적으로 "key"를 기준으로 검사함!


✅ 실전 트랩 예제

d = {'a': 1, 'b': 2}
if 2 in d:
    print("있다")

✅ 이건 출력 안 됨
왜냐면 in은 key만 보기 때문에 → 2는 value라서 False

2 in d.values() 로 써야 맞음


✅ 요약

자료형in 대상예시
문자열부분 문자열'a' in 'cat'
리스트/튜플요소3 in [1,2,3]
딕셔너리기본은 key만'a' in {'a':1}
딕셔너리의 값 검사.values() 필요1 in d.values()

✅ 15. 리스트, 딕셔너리, 집합의 내부 구조 차이와 사용법


✅ 1. 리스트 (list)

🔸 순서 있음 / 중복 허용

a = [1, 2, 2, 3]
print(a[0])  # 1
  • 인덱스(index)로 접근 가능
  • 삽입/삭제가 빠르지 않음 (특히 중간에)

✅ 2. 집합 (set)

🔸 순서 없음 / 중복 허용 안 함

s = {1, 2, 2, 3}
print(s)  # {1, 2, 3} ← 중복 제거됨
  • 요소의 존재 여부 빠르게 검사 가능: x in s (O(1))
  • 정렬된 순서가 아님

✅ 3. 딕셔너리 (dict)

🔸 키-값 쌍 / 키는 유일

d = {'a': 1, 'b': 2}
print(d['a'])  # 1
  • key는 중복 불가
  • 내부적으로는 해시 테이블 기반 (속도 빠름)
  • key in d는 매우 빠름 (O(1))

✅ 차이 요약표

자료형중복 허용순서 유지용도
listO (중복 허용)O (순서 유지)순차 데이터
set❌ (중복 제거됨)❌ (순서 X)존재 여부 확인, 집합 연산
dictkey 중복 ❌O (파이썬 3.7+)키-값 매핑

✅ 실전 문제 예시

items = [1, 2, 2, 3, 4]
unique = set(items)
print(len(unique))  # 4 ← 중복 제거됨

✅ 집합 연산 예시 (면접 단골)

a = {1, 2, 3}
b = {2, 3, 4}

print(a & b)  # {2, 3} ← 교집합
print(a | b)  # {1, 2, 3, 4} ← 합집합
print(a - b)  # {1} ← 차집합

✅ 14~15 마무리 요약

주제핵심 포인트주의점
in 연산자포함 여부 검사딕셔너리는 key만 검사함
list순서 있음, 중복 O인덱싱 가능
set순서 없음, 중복 ❌빠른 탐색용
dictkey-value 구조key만 중복 ❌

0개의 댓글