import typing def yep(s: str) -> bool: return s.strip().lower().startswith("y") def guess_bisect_repl(lower: int, upper: int) -> int: mid = lower + ((upper - lower) // 2) if yep(input(f"is it {mid}? ")): return mid if yep(input(f"higher than {mid}? ")): return guess_bisect_repl(mid, upper) return guess_bisect_repl(lower, mid) def find_sqrt_ish(n: int) -> int: return int(find_bisect(0, n, gen_sqrt_check(n))) def gen_sqrt_check(n: int) -> typing.Callable[[float], int]: def check(mid: float) -> int: mid_sq: float = mid * mid if mid_sq == n: return 0 if mid_sq < n: return 1 return -1 return check def find_bisect(lower: float, upper: float, check: typing.Callable[[float], int]) -> float: mid: float = lower + ((upper - lower) / 2) print(f"lower={lower} mid={mid} upper={upper}") if mid == lower or mid == upper or check(mid) == 0: return mid if check(mid) == 1: return find_bisect(mid, upper, check) return find_bisect(lower, mid, check) def cartesian_path(p0: tuple[int, int], p1: tuple[int, int]) -> list[tuple[int, int]]: path: list[tuple[int, int]] = [] if p0 < p1: for i in range(p0[1], p1[1]): path.append((i, p0[0])) for i in range(p0[0], p1[0]): path.append((p1[1], i)) else: for i in range(p0[1], p1[1] - 1, -1): path.append((i, p0[0])) for i in range(p0[0] - 1, p1[0], -1): path.append((p1[1], i)) return path def gen_matrix(width: int, height: int) -> list[list[int]]: return [list(range(width)) for _ in range(height)]