#!/usr/bin/env python

import enum
import sys
from collections.abc import Iterator
from typing import NamedTuple, Optional


class Point(NamedTuple):
    x: int
    y: int


class Cell(enum.StrEnum):
    PATH = "."
    NORTH_SLOPE = "^"
    SOUTH_SLOPE = "v"
    WEST_SLOPE = "<"
    EAST_SLOPE = ">"

    def neighbours(self) -> Iterator[Point]:
        match self:
            case self.PATH:
                yield from (
                    Point(-1, 0),
                    Point(1, 0),
                    Point(0, -1),
                    Point(0, 1),
                )
            case self.NORTH_SLOPE:
                yield Point(-1, 0)
            case self.SOUTH_SLOPE:
                yield Point(1, 0)
            case self.WEST_SLOPE:
                yield Point(0, -1)
            case self.EAST_SLOPE:
                yield Point(0, 1)

    def apply(self, pos: Point) -> Iterator[Point]:
        for dx, dy in self.neighbours():
            yield Point(pos.x + dx, pos.y + dy)


Trails = dict[Point, Cell]


def solve(input: list[str]) -> int:
    def parse(input: list[str]) -> Trails:
        res: Trails = {}

        for x, line in enumerate(input):
            for y, c in enumerate(line):
                if c == "#":
                    continue
                res[Point(x, y)] = Cell(c)

        return res

    def explore(trails: Trails, start: Point, dest: Point) -> int:
        def recurse(start: Point, seen: set[Point]) -> Optional[int]:
            if start == dest:
                return 0
            if start not in trails:
                return None
            next_step = (
                recurse(n, seen | {n})
                for n in trails[start].apply(start)
                if n not in seen
            )
            distances = [dist for dist in next_step if dist is not None]
            if not distances:
                return None
            return max(distances) + 1

        res = recurse(start, {start})
        assert res is not None  # Sanity check
        return res

    trails = parse(input)
    start, dest = Point(0, 1), Point(len(input) - 1, len(input[0]) - 2)
    assert start in trails  # Sanity check
    assert dest in trails  # Sanity check
    sys.setrecursionlimit(10_000)
    return explore(trails, start, dest)


def main() -> None:
    input = sys.stdin.read().splitlines()
    print(solve(input))


if __name__ == "__main__":
    main()