Skip to content

15주차 · 기말고사 안내와 연습문제

주차포함 내용시험에서 묻는 방식
10주차행렬과 벡터 기초행렬/벡터 크기 판단, 곱셈 가능 여부, 결과 shape, 간단한 계산
11주차NumPy 기초배열 연산, 평균/차이 계산, 불리언 mask, 필터링 결과 추적
13주차실용 알고리즘dict.get 카운팅, sorted(..., key=...), 정렬 방향, tie-break 설명
14주차통합 코드 읽기데이터가 생성 → 정제 → 요약되는 흐름 설명. 단, 시각화 설계안은 제외
  • 9주차 리팩토링과 테스트: 함수 분해, 테스트 설계, assert 중심 리팩토링 문제는 기말 범위에서 제외합니다.
  • 12주차 데이터 시각화(matplotlib): 그래프 작성, 축 라벨, plot_spec, matplotlib 코드는 기말 범위에서 제외합니다.
  • 14주차 내용 중에서도 시각화 설계안이나 그래프 해석은 제외합니다.

중간고사보다 달라지는 점은 다음과 같습니다.

  1. 자료형보다 shape가 중요해집니다.
    예: A @ x가 가능한지, 결과가 몇 행 몇 열인지 먼저 판단해야 합니다.
  2. for 루프보다 NumPy 배열 전체 연산이 자주 나옵니다.
    예: arr - arr.mean()이 각 원소에 동시에 적용되는 이유를 설명합니다.
  3. 정렬은 “결과만”보다 “기준 함수”를 설명해야 합니다.
    예: return (-count, name)이 왜 빈도 내림차순과 이름 오름차순을 동시에 표현하는지 씁니다.
  4. 자주 하는 실수도 시험 범위 안에서 확인할 수 있습니다.
    예: 여러 조건을 결합하는 방식, 음수 값의 정렬 방향, 동점 처리 기준을 혼동하지 않도록 점검하세요.

기말 답안은 정답 숫자만 쓰면 부족합니다. 아래 4단계를 짧게라도 포함하세요.

  1. shape/자료구조 확인: 배열인가, 리스트인가, dict인가? 행렬 크기는 얼마인가?
  2. 연산 규칙 설명: 원소별 연산인가, 행렬곱인가, 카운팅인가, 정렬인가?
  3. 중간 결과 추적: mask, counts, sorted 결과처럼 중간 변수를 한 번 이상 확인하세요.
  4. 최종 해석: 왜 그 출력/결과가 나오는지 1-2문장으로 마무리하세요.

연습문제 1 · 행렬과 벡터 계산 규칙

Section titled “연습문제 1 · 행렬과 벡터 계산 규칙”

다음 행렬과 벡터를 보고 질문에 답하세요.

A = [ 1 2 ] x = [ 10 ]
[ 3 4 ] [ 20 ]
  1. A의 shape와 x의 shape를 쓰세요.
  2. A @ x가 가능한 이유를 안쪽 크기 관점에서 설명하세요.
  3. A @ x의 결과 shape를 쓰세요.
  4. 각 행의 가중합을 계산해 결과 벡터를 구하세요.
  • 행렬곱에서는 왼쪽 행렬의 열 수와 오른쪽 벡터의 행 수가 같아야 합니다.
  • 첫 번째 결과는 1*10 + 2*20입니다.

아래 코드를 읽고, 각 변수가 어떤 값을 가지는지 추적하세요.

import numpy as np
raw = np.array([3.1, -1.0, 4.2, 5.5, 8.0])
valid_mask = (raw >= 0.0) & (raw <= 6.0)
clean = raw[valid_mask]
shifted = clean - 3.0
print(valid_mask)
print(clean)
print(shifted)
  1. valid_mask의 True/False 값을 순서대로 쓰세요.
  2. clean에 남는 값들을 쓰세요.
  3. shifted = clean - 3.0이 for 루프 없이 가능한 이유를 설명하세요.
  4. shifted의 값을 순서대로 쓰세요.
  • 조건은 “0 이상이고 6 이하”입니다.
  • NumPy 배열에서 clean - 3.0은 각 원소에 같은 연산을 적용합니다.

연습문제 3 · 카운팅과 정렬 기준

Section titled “연습문제 3 · 카운팅과 정렬 기준”

아래 코드는 상태 로그를 세고, 많이 나온 상태부터 정렬합니다.

logs = ["OK", "WARN", "OK", "ERR", "WARN", "OK"]
counts = {}
for status in logs:
counts[status] = counts.get(status, 0) + 1
def sort_key(item):
status, count = item
return (-count, status)
ordered = sorted(counts.items(), key=sort_key)
print(counts)
print(ordered)
  1. counts.get(status, 0) + 1이 처음 보는 key와 이미 본 key에서 각각 어떻게 동작하는지 설명하세요.
  2. 최종 counts 딕셔너리를 쓰세요.
  3. sort_key-count는 어떤 정렬 방향을 만들기 위한 것인지 설명하세요.
  4. ordered의 출력 순서를 예측하세요.
  • counts.items()의 원소는 ("OK", 3) 같은 tuple입니다.
  • (-count, status)는 먼저 count를 큰 순서로 보고, count가 같으면 상태 이름을 알파벳 순서로 봅니다.

수신 전력 데이터가 다음과 같이 주어졌습니다.

channels = [
{"id": "A", "power_dbm": -55},
{"id": "B", "power_dbm": -42},
{"id": "C", "power_dbm": -61},
{"id": "D", "power_dbm": -42},
]
def power_key(row):
return (-row["power_dbm"], row["id"])
ordered = sorted(channels, key=power_key)
print([row["id"] for row in ordered])
  1. dBm 값에서 -42 dBm-61 dBm 중 어느 쪽이 더 강한 신호인지 쓰세요.
  2. -row["power_dbm"]를 key로 쓰면 왜 강한 신호가 앞쪽에 오는지 설명하세요.
  3. BD는 전력이 같을 때 어떤 기준으로 순서가 정해지는지 설명하세요.
  4. 최종 출력되는 채널 ID 순서를 쓰세요.
  • RSSI/dBm은 숫자가 클수록, 즉 덜 음수일수록 강한 신호입니다.
  • tuple key는 첫 번째 기준이 같으면 두 번째 기준을 봅니다.