-1

Is there any way to search for a sequence by order (which is not continuous in the input) in a string in one command or a short block?

I'll give an example to the problem:

I gen a string from raw_input in the form of (+ or - or void)(number or void)X^2 (+ or -) (+ or - or void)X (+ or -) (+ or - or void)(number), and I want to assign a flag for (-+)aX^2 +- (-+)bX +- (+-)c and a flag for only c and a flag for only b... only b and c, only a and c, etc in any order of input (abc, cba, ac, cb, etc) by defining a search by characters "x^2", "x" "number" and assigning each order to a flag...

Can it be done without writing 300+ lines with tons of ifs and elifs? (I got frustrated in line 107).

I have tried the long agonizing way:

def sorting_abc():
    polinput = raw_input("insert a pol.: ")  # input as string
    a = 0
    b = 0
    c = 0
    temp = [] * 5

    splinput = polinput.split() #splitted string input
    lensplin = len(splinput)  #Length of splinput
    temp = splinput

    flag_1var = bool(lensplin == 1)
    flag_2var = bool(lensplin == 3)
    flag_3var = bool(lensplin == 5)
    flag_minusplus = bool(temp[1] == '-' and temp[3] == '+')
    flag_plusminus = bool(temp[1] == '+' and temp[3] == '-')
    flag_minusminus = bool(temp[1] == '-' and temp[3] == '-')
    flag_plusplus = bool(temp[1] == '+' and temp[3] == '+')
    flag_2var_minus = bool(splinput <= 3 and temp[1] == '-')
    flag_2var_plus = bool(splinput <= 3 and temp[1] == '+')

    if (flag_1var):
        p1 = tamp[0]
        p1i = p1.find('x^2')
        a = p1[:p1i:]
        if (a == ''):
            a = 1
        if (a == '-'):
            a = -1
        a = int(a)

    if (flag_2var):
        p1 = temp[0]
        p2 = temp[1]
        p3 = temp[2]
        if ('x^2' in p1):
            p1i = p1.find('x^2')
            a = p1[:p1i:]
            if (a == ''):
                a = 1
            if (a == '-'):
                a = -1
            c = p3
            if (p3 == '-'):
                c -= int(c)
        if ('x^2' in p3):
            p3i = p3.find('x^2')
            a = p3[:p3i:]
            if (a == ''):
                a = 1
            if (p2 == '-'):
                a -= int(a)
            c = p1

    if (flag_3var):
        p1 = temp[0]
        p2 = temp[1]
        p3 = temp[2]
        p4 = temp[3]
        p5 = temp[4]
        if ('x^2' in p1):
            p1i = p1.find('x^2')
            a = p1[:p1i:]
            if (a == ''):
                a = 1
            if (a == '-'):
                a = -1
            if ('x' in p3):
                p3i = p3.find('x')
                b = p3[:p3i:]
                if (b == ''):
                    b = 1
                if (p2 == '-'):
                    b -= int(b)
                c = p5
                if (p4 == '-'):
                    c -= int(c)
            if ('x' in p5):
                p5i = p5.find('x')
                b = p5[:p5i:]
                if (b == ''):
                    b = 1
                if (p4 == '-'):
                    b -= int(b)
                if (p2 == '-'):
                    c -= int(c)
                c = p3
        elif ('x^2' in p3):
            p3i = p3.find('x^2')
            a = p3[:p3i:]
            if (a == ''):

Any chance to shorten this significantly?

Machavity
  • 30,841
  • 27
  • 92
  • 100
  • It will be easier to help if you provide some sample input and desired output. – user2390182 Jan 14 '19 at 06:46
  • Sounds like a great usecase for regex for once. Add parentheses and it won't be any more. – Mad Physicist Jan 14 '19 at 07:08
  • inputs: 4x^2 + 2x - 22; -2x + (-4x^2) - (+22); 22 - 3x + 3x^2; output (for the last example): bool flag_c_minus_b_plus_a = true by using this flag to execute some cutting and filtering actions I should get: a = 3 b = -3 c = 22 (all ints) – Nitzan Weizman Jan 14 '19 at 07:14
  • What's the end goal? Do you need the flags or are you really trying to get the coefficients a, b, c from the text as numbers? – Mad Physicist Jan 14 '19 at 07:49
  • "line 107" isn't very meaningful when no line numbers are being displayed. – martineau Jan 14 '19 at 08:07
  • @MadPhysicist I need the flags to execute the right order of the coefficients so can extract the coefficients as int's from the string in the right order and apply also the right order of + and - as operations from the string input (unfortunately the input cannot be divided to more than one string - it has to be received as one input as string... – Nitzan Weizman Jan 14 '19 at 08:23
  • In that caseI don't think you really need the flags as such. Let me know if my answer has what you're looking for. – Mad Physicist Jan 14 '19 at 08:52

2 Answers2

2

I would approach it this way:

  1. remove all the spaces from your input string.
  2. apply 'all uppercase' or 'all lowercase' to your input string.
  3. split your string into a list, using the + or - symbols (both) as separators. For this, Google 'splitting strings using regular expressions' or check this post.
  4. using a loop, for each of the elements of the list, remove the parentheses if they exist.
  5. using a loop, for each of the elements of the list, check if they contain X^2, X or none (using uppercase or lowercase X depending on your previous choice).

You can combine 4. and 5. in the same loop if you want.

That should give you the answer you need, with relatively short, flexible, reusable code. Hope it helps.

Note: edit made after having a look at the example input.

jberrio
  • 972
  • 2
  • 9
  • 20
1

You can do this with the help of regular expressions if you choose. The advantage of doing it like that is that you will know if your input matches immediately, and what all the elements are when you query the match object.

The solution shown here relies on re.match to repeatedly find terms in your equation. The neat thing about doing it this way is that you can add up the coefficients to allow for terms with repeated exponents. It also makes it trivial to add support for terms beyond quadratic.

The result will be a dictionary keyed by the exponent (0 for the constant term), with the total coefficient aa the value. The regex shown here relies on a pattern for matching numbers taken from this answer to this question:

import re
from collections import defaultdict

string = '-12.5e-1 x^3 + -5 x^2 --0.5x +-0.75x^3 +6'

number = r'[-+]?(?:(?:\d*\.\d+)|(?:\d+\.?))(?:[Ee][+-]?\d+)?'
pattern = re.compile(fr'\s*([+-])\s*({number})\s*(x(\^\d+)?)?')

coefficients = defaultdict(int)
# prepend a + to avoid special-casing the first term
string = '+' + string.rstrip()
while string:
    match = pattern.match(string)
    if not match:
        raise ValueError(f'Invalid input starting with {string}')
    sign = 1 if match.group(1) == '+' else -1
    coefficient = sign * float(match.group(2))
    if match.group(3):
        exp = match.group(4)
        exp = 1 if exp is None else int(exp[1:])
    else:
        exp = 0
    coefficients[exp] += coefficient
    string = string[match.end():]

For the example string, the resulting coefficients are

defaultdict(<class 'int'>, {0: 6.0, 1: 0.5, 2: -5.0, 3: -2.0})

Here is an UDEOne link: https://ideone.com/TwtY2e

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264