Skip to content

The turtle-dragon Python API

Common definitions

turtle_dragon.defs

Common definitions for the turtle-dragon library.

FEATURES = {'turtle-dragon': VERSION} module-attribute

The list of features supported by the turtle-dragon library.

VERSION = '0.1.0' module-attribute

The turtle-dragon library version, semver-like.

Config dataclass

Runtime configuration for the turtle-dragon library.

Source code in src/turtle_dragon/defs.py
@dataclasses.dataclass(frozen=True)
class Config:
    """Runtime configuration for the turtle-dragon library."""

    cache: dict[int, Turn]
    """The cached turns for relatively small values of the generation."""

    log: logging.Logger
    """The logger to send diagnostic, informational, and error messages to."""
cache instance-attribute

The cached turns for relatively small values of the generation.

log instance-attribute

The logger to send diagnostic, informational, and error messages to.

Turn

Bases: StrEnum

The direction of the turn that we must make now.

Source code in src/turtle_dragon/defs.py
class Turn(enum.StrEnum):
    """The direction of the turn that we must make now."""

    LEFT = "left"
    """Turn left."""

    RIGHT = "right"
    """Turn right."""

    def converse(self) -> Self:
        """Turn the other way."""
        # https://github.com/python/mypy/issues/18029
        return Turn.LEFT if self == Turn.RIGHT else Turn.RIGHT  # type: ignore[return-value]
LEFT = 'left' class-attribute instance-attribute

Turn left.

RIGHT = 'right' class-attribute instance-attribute

Turn right.

converse()

Turn the other way.

Source code in src/turtle_dragon/defs.py
def converse(self) -> Self:
    """Turn the other way."""
    # https://github.com/python/mypy/issues/18029
    return Turn.LEFT if self == Turn.RIGHT else Turn.RIGHT  # type: ignore[return-value]

Calculate the turns of the dragon curve

turtle_dragon.calc

Calculate the turns of a dragon curve.

CACHE_MAX = 131071 module-attribute

The largest generation value that we are willing to cache.

turn(cfg, generation)

Calculate successive turns.

Source code in src/turtle_dragon/calc.py
def turn(cfg: defs.Config, generation: int) -> defs.Turn:
    """Calculate successive turns."""

    def update(value: defs.Turn) -> defs.Turn:
        """Update the cache if necessary."""
        if generation in cfg.cache:
            raise RuntimeError(repr((cfg, generation, value)))

        if generation <= CACHE_MAX:
            cfg.cache[generation] = value

        return value

    if generation < 1:
        raise ValueError(generation)

    match cfg.cache.get(generation):
        case None:
            pass

        case cached:
            cfg.log.debug(
                "turn: %(gen)d: cached: %(cached)s",
                {"gen": generation, "cached": cached},
            )
            return cached

    count = 0
    pow2 = generation
    next_pow2 = pow2 & (pow2 - 1)
    while (pow2 & next_pow2) != 0:
        count += 1
        pow2 = next_pow2
        next_pow2 = pow2 & (pow2 - 1)

    if count == 0:
        cfg.log.debug("turn: %(gen)d: power of two, easy", {"gen": generation})
        return update(defs.Turn.LEFT)

    cfg.log.debug("turn: %(gen)d: pow2 %(pow2)d", {"gen": generation, "pow2": pow2})
    return update(turn(cfg, (pow2 << 1) - generation).converse())