Skip to content

Instantly share code, notes, and snippets.

@kms0219kms
Last active January 8, 2026 01:56
Show Gist options
  • Select an option

  • Save kms0219kms/831beedb52a41bdc42fefd3e0665b04c to your computer and use it in GitHub Desktop.

Select an option

Save kms0219kms/831beedb52a41bdc42fefd3e0665b04c to your computer and use it in GitHub Desktop.
2025-2026 오성고_공동교육_정보과학 Day 4
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