# Review 2 * Hajin Ju, 2024062806 ## Problem 1 Fill in the blanks when the numbers are sorted by merge sort in non-decreasing order. ```python {cmd, output='html' hide} from bs4 import BeautifulSoup def create_merge_sort_html_no_arrows(): """ BeautifulSoup를 사용하여 화살표가 없는 병합 정렬 시각화 HTML을 생성합니다. """ soup = BeautifulSoup("", "html.parser") # --- 기본 스타일 정의 --- STYLE_CONTAINER = "display: flex; flex-direction: column-reverse; align-items: center; gap: 30px; font-family: sans-serif;" STYLE_LEVEL = "display: flex; justify-content: center; align-items: flex-end; gap: 20px; position: relative;" STYLE_LEVEL_LABEL = "position: absolute; left: -80px; top: 50%; transform: translateY(-50%); font-size: 1.2em; color: rgb(51, 51, 51);" STYLE_BOX_GROUP = "display: flex; position: relative;" STYLE_BOX_BASE = "width: 40px; height: 40px; border: 2px solid rgb(85, 85, 85); display: flex; justify-content: center; align-items: center; font-size: 1.2em;" STYLE_BOX_EMPTY = f"{STYLE_BOX_BASE} background-color: rgb(255, 255, 255);" STYLE_BOX_FILLED = f"{STYLE_BOX_BASE} background-color: rgb(204, 204, 204); font-weight: bold;" # --- 메인 컨테이너 생성 --- container = soup.new_tag('div', attrs={'style': STYLE_CONTAINER}) soup.append(container) # --- Level 0 (초기 숫자 배열) --- level0 = soup.new_tag('div', attrs={'style': STYLE_LEVEL}) numbers = [6, 3, 5, 8, 1, 7, 4, 2] for num in numbers: box_group = soup.new_tag('div', attrs={'style': STYLE_BOX_GROUP}) box = soup.new_tag('div', attrs={'style': STYLE_BOX_FILLED}) box.string = str(num) box_group.append(box) level0.append(box_group) container.append(level0) # --- Level 1, 2, 3 생성 함수 --- def create_level(level_num, groups_data): level = soup.new_tag('div', attrs={'style': STYLE_LEVEL}) label = soup.new_tag('div', attrs={'style': STYLE_LEVEL_LABEL}) label.string = "merge" level.append(label) for data in groups_data: num_boxes = data['boxes'] box_group = soup.new_tag('div', attrs={'style': STYLE_BOX_GROUP}) for i in range(num_boxes): style = STYLE_BOX_EMPTY if i > 0: style += " border-left: none;" box = soup.new_tag('div', attrs={'style': style}) box_group.append(box) level.append(box_group) return level # --- Level 1, 2, 3 데이터 및 생성 --- level1_data = [{'boxes': 2}, {'boxes': 2}, {'boxes': 2}, {'boxes': 2}] container.append(create_level(1, level1_data)) level2_data = [{'boxes': 4}, {'boxes': 4}] container.append(create_level(2, level2_data)) level3_data = [{'boxes': 8}] container.append(create_level(3, level3_data)) return container.prettify() # --- 스크립트 실행 --- if __name__ == "__main__": final_html = create_merge_sort_html_no_arrows() print(final_html) ``` ### Solution 1 ```python {cmd output=html hide} from bs4 import BeautifulSoup import math # --- 실제 병합 정렬을 수행하고 중간 과정을 기록하는 함수 --- def get_merge_sort_steps(data): steps = {} n = len(data) # 원본 배열 복사하여 단계별로 정렬 진행 current_array = list(data) # step_size는 1, 2, 4 순서로 증가 (합병되는 배열의 크기) step_size = 1 level = 1 while step_size < n: level_results = [] for i in range(0, n, step_size * 2): left_start = i left_end = i + step_size right_start = i + step_size right_end = min(i + step_size * 2, n) # 두 부분 배열을 합병하고 정렬 merged = sorted(current_array[left_start:right_end]) # 정렬된 결과를 현재 배열에 다시 반영 current_array[left_start:right_end] = merged level_results.extend(merged) steps[f'level_{level}'] = level_results step_size *= 2 level += 1 return steps # --- HTML 생성을 위한 메인 함수 --- def create_populated_merge_sort_html(data): soup = BeautifulSoup("", "html.parser") # 병합 정렬 실행하여 각 단계별 결과 얻기 sort_steps = get_merge_sort_steps(data) # --- 기본 스타일 정의 (이전과 동일) --- STYLE_CONTAINER = "display: flex; flex-direction: column-reverse; align-items: center; gap: 30px; font-family: sans-serif;" STYLE_LEVEL = "display: flex; justify-content: center; align-items: flex-end; gap: 20px; position: relative;" STYLE_LEVEL_LABEL = "position: absolute; left: -80px; top: 50%; transform: translateY(-50%); font-size: 1.2em; color: rgb(51, 51, 51);" STYLE_BOX_GROUP = "display: flex; position: relative;" STYLE_BOX_BASE = "width: 40px; height: 40px; border: 2px solid rgb(85, 85, 85); display: flex; justify-content: center; align-items: center; font-size: 1.2em;" STYLE_BOX_EMPTY = f"{STYLE_BOX_BASE} background-color: rgb(255, 255, 255);" STYLE_BOX_FILLED = f"{STYLE_BOX_BASE} background-color: rgb(204, 204, 204); font-weight: bold;" container = soup.new_tag('div', attrs={'style': STYLE_CONTAINER}) soup.append(container) # --- Level 0 (초기 데이터 배열) --- level0 = soup.new_tag('div', attrs={'style': STYLE_LEVEL}) for num in data: box_group = soup.new_tag('div', attrs={'style': STYLE_BOX_GROUP}) box = soup.new_tag('div', attrs={'style': STYLE_BOX_FILLED}) box.string = str(num) box_group.append(box) level0.append(box_group) container.append(level0) # --- Level 1, 2, 3 생성 및 채우기 --- num_levels = int(math.log2(len(data))) for i in range(1, num_levels + 1): level = soup.new_tag('div', attrs={'style': STYLE_LEVEL}) label = soup.new_tag('div', attrs={'style': STYLE_LEVEL_LABEL}) label.string = "merge" level.append(label) # 해당 레벨의 정렬 결과 가져오기 level_data = sort_steps[f'level_{i}'] group_size = 2**i # 결과를 그룹 크기에 맞게 나누어 박스 생성 for j in range(0, len(level_data), group_size): chunk = level_data[j:j + group_size] box_group = soup.new_tag('div', attrs={'style': STYLE_BOX_GROUP}) for k, num in enumerate(chunk): style = STYLE_BOX_EMPTY if k > 0: style += " border-left: none;" box = soup.new_tag('div', attrs={'style': style}) box.string = str(num) box_group.append(box) level.append(box_group) container.append(level) return container.prettify() # --- 스크립트 실행 --- if __name__ == "__main__": # 정렬할 8개의 원소를 가진 데이터 배열 data_to_sort = [6, 3, 5, 8, 1, 7, 4, 2] final_html = create_populated_merge_sort_html(data_to_sort) print(final_html) ``` ## Problem 2 Fill in the blanks with proper asymptotic running times. Assume that `p = 1`, `r = n` ### Solution 2 ``` // MERGE-SORT(A, p, r) // running time if p < r then // theta(1) q = floor((p + r) / 2) // theta(1) MERGE-SORT(A, p, q) // T(n/2) MERGE-SORT(A, q + 1, r) // T(n/2) MERGE(A, p, q, r) // theta(n) ``` ## Problem 3 Solve the recurrence of merge sort by using a recursion tree. $$T(n) = \begin{cases} \theta(1) &\text{if}\; n = 1\\ 2T(n/2) + \theta(n) &\text{if}\; n > 1 \end{cases}$$ ### Solution 3 ```mermaid graph TD subgraph "Level 0: theta(n)" A["T(n) | theta(n)"] end subgraph "Level 1: theta(n)" B["T(n/2) | theta(n/2)"] C["T(n/2) | theta(n/2)"] end subgraph "Level 2: theta(n)" D["T(n/4) | theta(n/4)"] E["T(n/4) | theta(n/4)"] F["T(n/4) | theta(n/4)"] G["T(n/4) | theta(n/4)"] end subgraph "Level h = log(n)" H["T(1) = theta(1)"] I["T(1) = theta(1)"] end A --> B A --> C B --> D B --> E C --> F C --> G D --> H G --> I style A fill:#f9f,stroke:#333,stroke-width:2px style B fill:#bbf,stroke:#333,stroke-width:2px style C fill:#bbf,stroke:#333,stroke-width:2px style D fill:#9f9,stroke:#333,stroke-width:2px style E fill:#9f9,stroke:#333,stroke-width:2px style F fill:#9f9,stroke:#333,stroke-width:2px style G fill:#9f9,stroke:#333,stroke-width:2px ``` Therefore, $T(n) = \theta(n \log n)$ ## Problem 4 What is the number of multiplications to evaluate the following cubic polynomial $f(x)$ when $x=3$ if the Horner's rule is used? $$f(x) = 4x^3 + 2x^2 + 5x + 2$$ ### Solution 4 1. Applying Horner's rule $$f(x) = ((4x + 2)x + 5)x + 2$$ 2. Count the number of multiplications 1. $4x$ 2. $(4x + 2)x$ 3. $((4x + 2)x + 5)x$ **3** ## Problem 5 Fill in the blank entries when the numbers are sorted by selection sort in non-decreasing order. ### Solution 5 ```python { cmd, output='html', hide } from bs4 import BeautifulSoup as bs data = [ [(7, False), (4, False), (3, False), (6, False), (8, False), (1, False), (2, False)], ] # selection sorting process n = len(data[0]) for i in range(n): cur = data[-1].copy() min_idx = i for j in range(i, n): if cur[j][0] < cur[min_idx][0]: min_idx = j cur[i], cur[min_idx] = cur[min_idx], cur[i] cur[i] = (cur[i][0], True) data.append(cur) soup = bs("
", 'lxml') td_style = "border: 1px solid black; padding: 10px; text-align: center; font-size: 1.2rem; min-width: 3rem;" td_style_high = "border: 1px solid black; padding: 10px; text-align: center; font-size: 1.2rem; min-width: 3rem; background-color: lightgray;" for i in range(len(data)): table = soup.new_tag("table") table["style"] = "display: flex; justify-content: center;" tr = soup.new_tag("tr") for d in data[i]: td = soup.new_tag("td") if d: td['style'] = td_style_high if d[1] else td_style td.string = str(d[0]) if d else " " else: td["style"] = td_style td.string = " " tr.append(td) table.append(tr) soup.div.append(table) print(soup.prettify()) ```