<commit_before># Intend to replace the original Step
import re


MOVE_RE = re.compile("([ULFRBD]w?|[MSEulfrbdxyz])(\'|i|2|2\'|)")

CLOCKWISE = 0
COUNTER = 1
HALFTURN = 2


class Move(object):

    __slots__ = ()

    def __new__(cls, representation):
        self = super().__new__(cls)
        if isinstance(representation, Move):
            symbol = representation.symbol
            sign = representation.sign
        else:
            match = MOVE_RE.match(representation.strip())
            if match is None:
                raise ValueError("Invalid move: {}".format(representation))
            symbol, sign = match
            if "w" in symbol:
                symbol = symbol[0].lower()
            if sign == "2'":
                sign = "2"

        self.symbol = symbol
        self.sign = ["", "'", "2"].index(sign)

        return self

    def __repr__(self):
        return self.symbol + ["", "'", "2"][self.sign]

    def __hash__(self):
        return hash(str(self))<commit_msg>Add addition, multiplication and equality comparison methods to Move<commit_after># Intend to replace the original Step
import re


MOVE_RE = re.compile("([ULFRBD]w?|[MSEulfrbdxyz])(\'|i|2|2\'|)")

CLOCKWISE = 1
HALFTURN = 2
COUNTER = 3


class Move(object):

    __slots__ = ()

    def __new__(cls, representation):
        self = super().__new__(cls)

        if isinstance(representation, Move):
            symbol = representation.symbol
            sign = representation.sign

        elif isinstance(representation, tuple) and len(representation) == 2:
            symbol, sign = representation
            assert symbol in "ULFRBDMSEulfrbdxyz" and sign in (1, 2, 3),
                "Invalid Move initialisation: {}".format(representation)

        elif isinstance(representation, str):
            match = MOVE_RE.match(representation.strip())
            if match is None:
                raise ValueError("Invalid move: {}".format(representation))
            symbol, sign = match
            if "w" in symbol:
                symbol = symbol[0].lower()
            if sign == "2'":
                sign = "2"

        else:
            raise ValueError("Can only accept Move, str, or 2-element tuple")

        self.symbol = symbol
        self.sign = [None, "", "2", "'"].index(sign)

        return self

    def __repr__(self):
        return self.symbol + [None, "", "2", "'"][self.sign]

    def __hash__(self):
        return hash(str(self))

    def __eq__(self, move):
        if not isinstance(move, Move):
            move = Move(move)
        return self.symbol == move.symbol and self.sign == move.sign

    def __ne__(self, move):
        return not self.__eq__(move)

    def __add__(self, move):
        if not isinstance(move, Move):
            move = Move(move)
        assert self.symbol == move.symbol, "Can't operate addition on two "
                                           "Moves with different symbols"
        sign = (self.sign + move.sign) % 4
        if sign == 0:
            return 0
        return Move((self.symbol, sign))

    def __mul__(self, i):
        assert isinstance(i, int), "Can only multiply with an integer"
        sign = (self.sign * i) % 4
        if sign == 0:
            return 0
        return Move((self.symbol, sign))
{'fraction_non_alphanumeric': 0.12271619975639464, 'fraction_numerical': 0.009439707673568819, 'mean_word_length': 2.0054894784995425, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4305136', 'n_tokens_mistral': 968, 'n_tokens_neox': 907, 'n_words': 268}