let break_to_subscript (s : string) : (string * int) option = let rec loop (i : int) : (string * int) option = if i < 0 then None else let ch = String.get s i in if '0' <= ch && ch <= '9' then loop (i - 1) else let name = String.sub s 0 (i + 1) and sub = String.sub s (i + 1) (String.length s - i - 1) in if sub = "" then None else int_of_string_opt sub |> Option.map (fun i -> (name, i)) in loop (String.length s - 1) let%test "break_to_subscript fail" = break_to_subscript "x1y" = None let%test "break_to_subscript simple" = break_to_subscript "x1" = Some ("x", 1) let%test "break_to_subscript empty" = break_to_subscript "" = None let%test "break_to_subscript number" = break_to_subscript "123" = None let%test "break_to_subscript multi" = break_to_subscript "x12" = Some ("x", 12)