Esempio n. 1
0
def remove_distances(code, r_codes=[], r_indices=[]):
    symbols = []
    par_stack = []
    new_code = ''
    # For each character in the code...
    for i, c in enumerate(code):
        # ... add the character to the new code.
        new_code += c
        in_element = -1

        if is_symbol(code, i):
            # Check if symbol c is part of one of the r_codes
            for j in range(len(r_codes)):
                if r_indices[j] <= i < r_indices[j] + len(r_codes[j]):
                    in_element = j
                    if r_codes[j] not in symbols:
                        symbols.append(r_codes[j])

            if in_element < 0 and c not in symbols:
                symbols.append(c)

        if c == '(':
            par_stack.append(i)
        # If we find a part of the code enclosed in parentheses ...
        elif c == ')':
            start = par_stack.pop(-1)
            part = code[start:i + 1].strip('()')
            # ... check whether this part contains a +/- operator.
            if ('+' in part or '-' in part) and '(' not in code[start + 1:i]:
                # If yes, remove the operation from the code ...
                new_code = new_code[:-(i - start + 1)]
                symb, op, dist = part[0], part[1], int(''.join(part[2:]))
                # ... find the code to calculate from ...
                if symb == '$':
                    symb = symbols[-1]
                # ... and get the correct distance.
                if op == '-':
                    dist *= -1
                # If it concerns a single symbol, calculate the distance from it
                if symb.isalnum() and len(symb) == 1:
                    new_symb = alphabet[alphabet.index(symb) + dist]
                # If it concerns a code ...
                else:
                    new_symb = ''
                    # ... add the distance to each symbol in the code.
                    for i, s in enumerate(symb):
                        if is_symbol(symb, i):
                            new_symb += alphabet[alphabet.index(s) + dist]
                        else:
                            new_symb += s

                #  Add the result to the new code.
                new_code += new_symb
                #if new_symb not in symbols:
                symbols.append(new_symb)

    #print('>', code)
    #print('>>', new_code)
    return new_code
def split_code(code):
    stack = []
    alternations = []
    elements = []
    # For each character in the code:
    for i in range(len(code)):
        # If it is a symbol not in an operator, add it to the elements.
        if is_symbol(code, i) and len(stack) == 0:
            elements.append(code[i])
        # If it is an opening bracket, add it to the stack
        elif code[i] in '<([':
            stack.append(i)
        # If it is a closing bracket ...
        elif code[i] in '>])':
            start = stack.pop(-1)
            # ... and the stack is not empty, it is a lower level operator.
            if len(stack) != 0:
                continue
            # Iteration, Symmetry and Alternation have different cases.
            if start > 1 and code[start-1] == '*':
                elements.append(code[start-2:i+1])
            if code[i] == ']' and start > 0 and code[start-1] == 'S':
                elements.append(code[start-1:i+1])
            elif code[i] == '>':
                if start > 0 and code[start-1] == '/':
                    lhs = alternations.pop(-1)
                    elements.append(lhs + code[start-1:i+1])
                else:
                    alternations.append(code[start:i+1])

    return elements
def replace_chunks(string, chunk, r1):
    elems, _ = chunk
    elems2 = copy(elems)
    # For each element:
    for i, elem in enumerate(elems):
        # Remove all outer parentheses, ....
        elem_stripped = elem.strip('()')
        dist = ''
        # ... find the part of the string before any + or - ...
        if '+' in elem_stripped:
            dist_ind = elem_stripped.index('+')
            dist += elem_stripped[dist_ind:]
        if '-' in elem_stripped:
            dist_ind = elem_stripped.index('-')
            dist += elem_stripped[dist_ind:]
        # ... and replace that part with a new part, given in r1 ...
        new_r = ''
        for j, c in enumerate(r1[i]):
            # ... while carrying over any distance operator.
            if is_symbol(r1[i], j) and dist != '':
                new_r += '(' + c + dist + ')'
            else:
                new_r += c
        elems2[i] = elems2[i].replace(elem_stripped, new_r)

    # Now reconstruct the string and return it.
    return reconstruct_string(string, chunk, elems2)
def get_chunks(string, l1):
    par_stack = []
    elements = []
    elem_indices = []
    # For each character in the string:
    for i, c in enumerate(string):
        # If it is an opening parenthesis, add it to the stack.
        if c == '(':
            par_stack.append(i)
        # If it is a closing parenthesis ...
        if c == ')':
            # ... get the corresponding parenthesis from the stack ...
            start = par_stack.pop(-1)
            # ... and find the substring the parentheses enclose (elem).
            elem = string[start:i+1]
            elem_len = len(elem.strip('()'))
            # if elem is already in the elements list ...
            if elements != [] and '('+''.join(elements[-elem_len:])+')' == elem:
                # ... remove those elements from the elements list.
                elements = elements[:-elem_len]
                elem_indices = elem_indices[:-elem_len]
            # if elem contains only symbols ...
            if elem.strip('()').isalnum():
                # ... add it to the elements list.
                elements.append(elem)
                elem_indices.append(start)

        # If it is a symbol, add it to the elements list.
        if is_symbol(string, i):
            elements.append(c)
            elem_indices.append(i)

    chunks = []
    symb_string = ''
    # For each sequential combination of elements ...
    for i in range(len(elements)):
        for j in range(i, len(elements)):
            # ... create a string of all symbols in those elements.
            symb_string = ''
            for e in elements[i:j+1]:
                symb = e.strip('()')
                for s in symb:
                    if s not in '+-':
                        symb_string += s
                    else:
                        break
            # If this string corresponds to l1 ...
            if symb_string == l1:
                # ... we have found a chunk.
                chunks.append((elements[i:j+1], elem_indices[i:j+1]))

    return chunks
Esempio n. 5
0
def add_distances_chunk(code, chunk):
    elems, indices = chunk
    new_string = ''
    symbols = []
    # For each character in the string:
    for i, c in enumerate(code):
        # If it is not a symbol, skip it.
        if not is_symbol(code, i):
            new_string += c
            continue
        # If it is one of the elements in the chunk ...
        in_element = False
        for j in range(len(elems)):
            if indices[j] <= i < indices[j] + len(elems[j]):
                new_string += c
                in_element = True
                # ... add it to the symbols, if it is not in already.
                if c not in symbols:
                    symbols.append(c)

        # If it was added, we don't need to do anything with it anymore.
        if in_element:
            continue

        # At this point, we have encountered a symbol not in the given elements.
        # If there are no previous symbols, we cannot find a distance.
        if symbols == []:
            return False

        # Calculate the distance from the last new symbol ...
        dist = alphabet.index(c) - alphabet.index(symbols[-1])
        new_symb = alphabet[alphabet.index(symbols[-1]) + dist]
        # ... and write the symbol as a distance from this symbol.
        if dist >= 0:
            new_string += '($+' + str(dist) + ')'
        else:
            new_string += '($-' + str(abs(dist)) + ')'
        if new_symb not in symbols:
            symbols.append(new_symb)

    return new_string
Esempio n. 6
0
 def paste(self):
     paste = pyperclip.paste()
     self.update_expression()
     if paste and not self.exp.is_error():
         self.history.out()
         paste = paste.replace('sin⁻¹',
                               'asin').replace('cos⁻¹', 'acos').replace(
                                   'tan⁻¹',
                                   'atan').replace('rootx(',
                                                   'Ŷ').replace(' ', '')
         for k, v in ADVANCED_KEYS.items():
             if k not in ['^', 'π', '√', '∛', 'Ŷ']:
                 paste = paste.replace(v, k)
         for i in paste:
             if not is_symbol(i):
                 self.last_invalid_exp = self.exp.exp
                 self.exp.set_exp(ERRORS[5])
                 self.update_monitor()
                 return
         self.exp.put_data_on_exp(paste)
         self.update_monitor()
Esempio n. 7
0
def add_distances_symbols(code, lhs, add_from_last=True):
    if isinstance(code, str):
        new_code = ''
    else:
        new_code = []
    if isinstance(lhs, list):
        symbols = lhs
    else:
        symbols = []
    # For each character in the string ...
    for i, c in enumerate(code):
        add_code = ''
        is_symb = is_symbol(code, i)
        # If c is a symbol and not already in the lefthandside ...
        if is_symb and c not in lhs:
            # ... calculate the distance from the last symbol
            dist = alphabet.index(c) - alphabet.index(symbols[-1])
            # ... and add c to the code as that distance
            if add_from_last:
                start = '($'
            else:
                start = '(' + str(symbols[-1])
            if dist >= 0:
                add_code += start + '+' + str(dist) + ')'
            else:
                add_code += start + '-' + str(abs(dist)) + ')'
        # Otherwise, just add c to the new code
        else:
            add_code += c

        if isinstance(code, str):
            new_code += add_code
        else:
            new_code.append(add_code)

        if is_symb and c not in symbols:
            if c in lhs or add_from_last:
                symbols.append(c)

    return new_code
def replace_symbols(string, l1, r1):
    new_string = ''
    symbols = []
    r_indices = []
    r_elems = []
    # For each element in the string:
    for i, c in enumerate(string):
        # If it is a symbol and occurs in l1 ...
        if is_symbol(string, i) and c in l1:
            n = symbols.count(c)%l1.count(c)
            # ... find the corresponding symbol in r1 ...
            new_symbol = r1[l1.index(c, n)%len(r1)]

            r_indices.append(len(new_string))
            r_elems.append(new_symbol)
            # ... and add it to the new string.
            new_string += new_symbol
            symbols.append(c)
        # Otherwise, just add it to the string.
        else:
            new_string += c
    return new_string, r_elems, r_indices
Esempio n. 9
0
def add_distances_positional(code, lhs, rhs):
    new_code = ''
    counts = {c: 0 for c in rhs}
    # For each character in the string ...
    for i, c in enumerate(code):
        is_symb = is_symbol(code, i)
        # If c is a symbol and not already in the lefthandside ...
        if is_symb and c not in lhs:
            # ... find the symbol in lhs at the same position as c in rhs ...
            pos_symbol = lhs[rhs.index(c, counts[c])]
            counts[c] += 1
            # ... calculate the distance from the last symbol
            dist = alphabet.index(c) - alphabet.index(pos_symbol)
            # ... and add c to the code as that distance
            if dist >= 0:
                new_code += '(' + pos_symbol + '+' + str(dist) + ')'
            else:
                new_code += '(' + pos_symbol + '-' + str(abs(dist)) + ')'

        # Otherwise, just add c to the new code
        else:
            new_code += c

    return new_code