Last active
January 8, 2026 01:56
-
-
Save kms0219kms/831beedb52a41bdc42fefd3e0665b04c to your computer and use it in GitHub Desktop.
2025-2026 오성고_공동교육_정보과학 Day 4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import turtle | |
| import time | |
| from typing import List, Tuple | |
| SPACING = 60 | |
| PAD_RADIUS = 20 | |
| FROG_SIZE = 1.5 | |
| BASELINE_Y = -40 | |
| JUMP_PEAK = 50 | |
| STEP_DELAY = 0.02 | |
| MOVE_PAUSE = 0.3 | |
| def compute_states(a: int, b: int, c: int) -> List[Tuple[int, int, int]]: | |
| """ | |
| Generate the sequence of frog positions until no more moves are possible. | |
| Over-jump variant: choose the outer frog on the side with the larger gap, | |
| and jump it to the pad adjacent to the middle on the opposite side | |
| (i.e., if left gap is larger, move the right outer to b-1; if right gap is larger, | |
| move the left outer to b+1). This produces sequences like the user's example. | |
| """ | |
| x = sorted([a, b, c]) | |
| states = [tuple(x)] | |
| while True: | |
| left_gap = x[1] - x[0] | |
| right_gap = x[2] - x[1] | |
| if left_gap == 1 and right_gap == 1: | |
| break | |
| if left_gap >= right_gap: | |
| # move RIGHT outer across to b-1 | |
| new_pos = x[1] - 1 | |
| x = sorted([x[0], x[1], new_pos]) | |
| else: | |
| # move LEFT outer across to b+1 | |
| new_pos = x[1] + 1 | |
| x = sorted([new_pos, x[1], x[2]]) | |
| states.append(tuple(x)) | |
| return states | |
| def max_moves(a: int, b: int, c: int) -> int: | |
| x = sorted([a, b, c]) | |
| return max(x[1] - x[0], x[2] - x[1]) - 1 | |
| def index_to_xy(idx: int, min_idx: int, max_idx: int) -> Tuple[float, float]: | |
| count = max_idx - min_idx + 1 | |
| total_width = (count - 1) * SPACING | |
| x = (idx - min_idx) * SPACING - total_width / 2 | |
| y = BASELINE_Y | |
| return x, y | |
| def draw_lily_pads(min_idx: int, max_idx: int) -> None: | |
| pen = turtle.Turtle(visible=False) | |
| pen.speed(0) | |
| pen.penup() | |
| pen.color("#247A38") | |
| pen.fillcolor("#2ECC71") | |
| for idx in range(min_idx, max_idx + 1): | |
| x, y = index_to_xy(idx, min_idx, max_idx) | |
| pen.goto(x, y) | |
| pen.setheading(0) | |
| pen.begin_fill() | |
| pen.circle(PAD_RADIUS) | |
| pen.end_fill() | |
| # label indices above pads | |
| pen.color("#2C3E50") | |
| for idx in range(min_idx, max_idx + 1): | |
| x, y = index_to_xy(idx, min_idx, max_idx) | |
| pen.goto(x, y + PAD_RADIUS + 10) | |
| pen.write(str(idx), align="center", font=("Arial", 10, "normal")) | |
| def make_frog(color: str) -> turtle.Turtle: | |
| t = turtle.Turtle(shape="turtle") | |
| t.shapesize(FROG_SIZE) | |
| t.color(color) | |
| t.penup() | |
| t.speed(0) | |
| return t | |
| def animate_jump(frog: turtle.Turtle, start: Tuple[float, float], end: Tuple[float, float]) -> None: | |
| # draw a simple arc between start and end | |
| sx, sy = start | |
| ex, ey = end | |
| steps = int(abs(ex - sx) // 8) + 12 | |
| for i in range(steps + 1): | |
| t_norm = i / steps | |
| x = sx + (ex - sx) * t_norm | |
| # parabolic arc: peak at midpoint | |
| y = sy + (ey - sy) * t_norm + JUMP_PEAK * (1 - (2 * t_norm - 1) ** 2) | |
| frog.goto(x, y) | |
| time.sleep(STEP_DELAY) | |
| frog.goto(ex, ey) | |
| def visualize(a: int, b: int, c: int) -> None: | |
| states = compute_states(a, b, c) | |
| min_idx = min(states[0]) | |
| max_idx = max(states[0]) | |
| screen = turtle.Screen() | |
| screen.title("Frogs on Lily Pads — Turtle Visualization") | |
| screen.bgcolor("#E8F6F3") | |
| screen.tracer(False) | |
| draw_lily_pads(min_idx, max_idx) | |
| # create frogs at initial positions | |
| colors = ["#E74C3C", "#3498DB", "#F39C12"] | |
| frogs = [make_frog(colors[i]) for i in range(3)] | |
| # mapping: pad index -> frog turtle | |
| pad_to_frog = {} | |
| for frog, idx in zip(frogs, states[0]): | |
| x, y = index_to_xy(idx, min_idx, max_idx) | |
| frog.goto(x, y) | |
| pad_to_frog[idx] = frog | |
| screen.tracer(True) | |
| # info writer | |
| info = turtle.Turtle(visible=False) | |
| info.penup() | |
| info.color("#2C3E50") | |
| info.goto(0, BASELINE_Y - 80) | |
| info.write( | |
| f"Start: {states[0]} | Max moves: {max_moves(a, b, c)}\nMoves use over-jump pattern\nClick anywhere to start", | |
| align="center", | |
| font=("Arial", 14, "bold"), | |
| ) | |
| moves_done = 0 | |
| def start_animation(x_click: float, y_click: float) -> None: | |
| nonlocal moves_done | |
| # disable further clicks triggering multiple runs | |
| screen.onclick(None) | |
| # clear the prompt | |
| info.clear() | |
| info.write( | |
| f"Move {moves_done}/{max_moves(a, b, c)}: {states[0]}", | |
| align="center", | |
| font=("Arial", 14, "bold"), | |
| ) | |
| for i in range(1, len(states)): | |
| prev = list(states[i - 1]) | |
| curr = list(states[i]) | |
| old_pad = next(v for v in prev if v not in curr) | |
| new_pad = next(v for v in curr if v not in prev) | |
| frog = pad_to_frog.pop(old_pad) | |
| start_xy = index_to_xy(old_pad, min_idx, max_idx) | |
| end_xy = index_to_xy(new_pad, min_idx, max_idx) | |
| animate_jump(frog, start_xy, end_xy) | |
| pad_to_frog[new_pad] = frog | |
| moves_done += 1 | |
| info.clear() | |
| info.write( | |
| f"Move {moves_done}/{max_moves(a, b, c)}: {states[i]}", | |
| align="center", | |
| font=("Arial", 14, "bold"), | |
| ) | |
| time.sleep(MOVE_PAUSE) | |
| info.clear() | |
| info.write( | |
| f"Done. Final: {states[-1]} (consecutive pads)", | |
| align="center", | |
| font=("Arial", 14, "bold"), | |
| ) | |
| # register click handler to start the animation | |
| screen.onclick(start_animation) | |
| turtle.done() | |
| def parse_input() -> Tuple[int, int, int]: | |
| try: | |
| raw = input("Enter three pad indices (e.g., 2 7 10): ") | |
| a, b, c = map(int, raw.split()) | |
| return a, b, c | |
| except Exception: | |
| print("Invalid input. Using default sample: 2 7 10") | |
| return 2, 7, 10 | |
| if __name__ == "__main__": | |
| a, b, c = parse_input() | |
| visualize(a, b, c) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment