# Path: permuta/misc/display.py
# class HTMLViewer:
#     """A class for opening html text in browser."""
# 
#     _THREAD_WAIT_TIME: ClassVar[float] = 5  # seconds
# 
#     @staticmethod
#     def _remove_file_thread(fname: str) -> None:
#         time.sleep(HTMLViewer._THREAD_WAIT_TIME)
#         if os.path.exists(fname):
#             os.remove(fname)
# 
#     @staticmethod
#     def _remove_file(fname: str) -> None:
#         threading.Thread(target=HTMLViewer._remove_file_thread, args=(fname,)).start()
# 
#     @staticmethod
#     def open_html(html: str) -> None:
#         """Open and render html string in browser."""
#         with tempfile.NamedTemporaryFile(
#             "r+", suffix=".html", delete=False
#         ) as html_file:
#             html_file.write(html)
#             webbrowser.open_new_tab(f"file://{html_file.name}")
#             HTMLViewer._remove_file(html_file.name)
# 
#     @staticmethod
#     def open_svg(svg: str) -> None:
#         """Open and render svg image string in browser."""
#         HTMLViewer.open_html(f"<html><body>{svg}</body></html>")
# 
# Path: permuta/misc/math.py
# def is_prime(n: int) -> bool:
#     """Primality test using 6k+-1 optimization."""
#     if n <= 3:
#         return n > 1
#     if n % 2 == 0 or n % 3 == 0:
#         return False
#     i = 5
#     while i ** 2 <= n:
#         if n % i == 0 or n % (i + 2) == 0:
#             return False
#         i += 6
#     return True
# 
# Path: permuta/patterns/patt.py
# class Patt(abc.ABC):
#     """A permutation pattern, e.g. classical, bivincular and mesh patterns."""
# 
#     def avoided_by(self, *patts: "Patt") -> bool:
#         """Check if self is avoided by all the provided patterns."""
#         return all(self not in patt for patt in patts)
# 
#     def contained_in(self, *patts: "Patt") -> bool:
#         """Check if self is a pattern of all the provided patterns."""
#         return all(self in patt for patt in patts)
# 
#     def count_occurrences_in(self, patt: "Patt") -> int:
#         """Count the number of occurrences of self in the pattern."""
#         return sum(1 for _ in self.occurrences_in(patt))
# 
#     @abc.abstractmethod
#     def occurrences_in(
#         self, patt: "Patt", *args, **kwargs
#     ) -> Iterator[Tuple[int, ...]]:
#         """Find all indices of occurrences of self in pattern."""
# 
#     @abc.abstractmethod
#     def __len__(self) -> int:
#         """The length of the pattern."""
# 
#     @abc.abstractmethod
#     def get_perm(self) -> "Perm":
#         """Get the permutation part of the pattern"""
# 
#     @abc.abstractmethod
#     def __contains__(self, patt: object) -> bool:
#         """Does pattern contains another?"""


import bisect
import collections
import functools
import itertools
import math
import numbers
import operator
import random
from typing import (
    TYPE_CHECKING,
    Callable,
    Deque,
    Dict,
    Iterable,
    Iterator,
    List,
    Optional,
    Set,
    Tuple,
    TypeVar,
    Union,
)
from permuta.misc import HTMLViewer
from permuta.misc.math import is_prime
from .patt import Patt
        n = len(perm_slice)
        if n == 0:
            return perm_slice
        maxind = -1
        # Note that perm does not need standardizing as sfp uses left to right maxima.
        for maxind in Perm(perm_slice).strong_fixed_points():
            pass
        if maxind != -1:
            lis: List[int] = (
                Perm._quick_sort(perm_slice[:maxind])
                + [perm_slice[maxind]]
                + Perm._quick_sort(perm_slice[maxind + 1 :])
            )
        else:
            firstval = perm_slice[0]
            lis = (
                list(filter(lambda x: x < firstval, perm_slice))
                + [perm_slice[0]]
                + list(filter(lambda x: x > firstval, perm_slice))
            )
        return lis

    def quick_sort(self) -> "Perm":
        """Quick sorting the permutation"""
        return Perm(Perm._quick_sort(list(self)))

    def quick_sortable(self) -> bool:
        """Returns true if perm is quicksort sortable."""
        return self.quick_sort().is_increasing()


# Path: permuta/misc/display.py
# class HTMLViewer:
#     """A class for opening html text in browser."""
# 
#     _THREAD_WAIT_TIME: ClassVar[float] = 5  # seconds
# 
#     @staticmethod
#     def _remove_file_thread(fname: str) -> None:
#         time.sleep(HTMLViewer._THREAD_WAIT_TIME)
#         if os.path.exists(fname):
#             os.remove(fname)
# 
#     @staticmethod
#     def _remove_file(fname: str) -> None:
#         threading.Thread(target=HTMLViewer._remove_file_thread, args=(fname,)).start()
# 
#     @staticmethod
#     def open_html(html: str) -> None:
#         """Open and render html string in browser."""
#         with tempfile.NamedTemporaryFile(
#             "r+", suffix=".html", delete=False
#         ) as html_file:
#             html_file.write(html)
#             webbrowser.open_new_tab(f"file://{html_file.name}")
#             HTMLViewer._remove_file(html_file.name)
# 
#     @staticmethod
#     def open_svg(svg: str) -> None:
#         """Open and render svg image string in browser."""
#         HTMLViewer.open_html(f"<html><body>{svg}</body></html>")
# 
# Path: permuta/misc/math.py
# def is_prime(n: int) -> bool:
#     """Primality test using 6k+-1 optimization."""
#     if n <= 3:
#         return n > 1
#     if n % 2 == 0 or n % 3 == 0:
#         return False
#     i = 5
#     while i ** 2 <= n:
#         if n % i == 0 or n % (i + 2) == 0:
#             return False
#         i += 6
#     return True
# 
# Path: permuta/patterns/patt.py
# class Patt(abc.ABC):
#     """A permutation pattern, e.g. classical, bivincular and mesh patterns."""
# 
#     def avoided_by(self, *patts: "Patt") -> bool:
#         """Check if self is avoided by all the provided patterns."""
#         return all(self not in patt for patt in patts)
# 
#     def contained_in(self, *patts: "Patt") -> bool:
#         """Check if self is a pattern of all the provided patterns."""
#         return all(self in patt for patt in patts)
# 
#     def count_occurrences_in(self, patt: "Patt") -> int:
#         """Count the number of occurrences of self in the pattern."""
#         return sum(1 for _ in self.occurrences_in(patt))
# 
#     @abc.abstractmethod
#     def occurrences_in(
#         self, patt: "Patt", *args, **kwargs
#     ) -> Iterator[Tuple[int, ...]]:
#         """Find all indices of occurrences of self in pattern."""
# 
#     @abc.abstractmethod
#     def __len__(self) -> int:
#         """The length of the pattern."""
# 
#     @abc.abstractmethod
#     def get_perm(self) -> "Perm":
#         """Get the permutation part of the pattern"""
# 
#     @abc.abstractmethod
#     def __contains__(self, patt: object) -> bool:
#         """Does pattern contains another?"""


# Path: permuta/patterns/perm.py
import bisect
import collections
import functools
import itertools
import math
import numbers
import operator
import random
from typing import (
    TYPE_CHECKING,
    Callable,
    Deque,
    Dict,
    Iterable,
    Iterator,
    List,
    Optional,
    Set,
    Tuple,
    TypeVar,
    Union,
)
from permuta.misc import HTMLViewer
from permuta.misc.math import is_prime
from .patt import Patt

        n = len(perm_slice)
        if n == 0:
            return perm_slice
        maxind = -1
        # Note that perm does not need standardizing as sfp uses left to right maxima.
        for maxind in Perm(perm_slice).strong_fixed_points():
            pass
        if maxind != -1:
            lis: List[int] = (
                Perm._quick_sort(perm_slice[:maxind])
                + [perm_slice[maxind]]
                + Perm._quick_sort(perm_slice[maxind + 1 :])
            )
        else:
            firstval = perm_slice[0]
            lis = (
                list(filter(lambda x: x < firstval, perm_slice))
                + [perm_slice[0]]
                + list(filter(lambda x: x > firstval, perm_slice))
            )
        return lis

    def quick_sort(self) -> "Perm":
        """Quick sorting the permutation"""
        return Perm(Perm._quick_sort(list(self)))

    def quick_sortable(self) -> bool:
        """Returns true if perm is quicksort sortable."""
        return self.quick_sort().is_increasing()


    def bkv_sortable(self, patterns: Tuple[Patt, ...] = ()) -> bool: