2

i was helping my friend to do logic algorithm in python but i haven't come with best solution yet.

first of all, i have a list of array:

x = array[0,1,2,3,4,3,2,3,-2,-4,-7,2,2]

and he wanted to categorize the x so the output become like this:

array([0,1,2,3,4]) # increasing value
array([4,3,2]) #decreasing value
array([2,3]) # increasing value
array([3,-2,-4,-7]) #decreasing value
array([-7,2]) # increasing value
array([2,2])  # remain_the_same_value

the rule is simple:

  1. if the value keep increasing (like example above: 0,1,2,3,4) they put in one array
  2. if the value keep decreasing (like example above: 3,-2,-4,-7) they put in one array
  3. but, if there is a sudden change in value pattern such as example above: from the increasing value (0,1,2,3,4) suddenly the next value is decreasing. the new array will be made and put the last increasing value which is (4) and monitor the next value, whether it is decreasing value or not. If yes, they will be put in one array. example :array([4,3,2])
  4. if the the value is remain the same (like example above, from 2 to 2). they will be put in one array.

this is what i come so far, but still far from the solution

#categorize which types of input
if len(x) > 2 :
    for i in range(len(x)) :
        if (x[i+1]-x[i]) > 0 and i+i < len(x) : # for increasing x value

        elif (x[i+1]-x[i]) < 0 and i+i < len(x) : # for decreasing x value

        elif (x[i+1]-x[i]) == 0 and i+i < len(x) : # for foward direction of vehicle

        else :
            print 'ERROR : check the input coordinates once again!'

best regards,

Glenn

2
  • 1
    I don't understand this part: array([3,-2]) #decreasing value array([-2,-4,-7]) #decreasing value They are both decreasing so why are they different? Commented May 17, 2012 at 10:34
  • @ jamylak : yes, you're right. i made a mistake there. i'll fix it right away. thanks jamylak Commented May 17, 2012 at 15:28

3 Answers 3

5

Firstly I would like to say that I don't understand one part of your question,

array([3,-2]) #decreasing value
array([-2,-4,-7]) #decreasing value

Why are these separate?

I will post my answer so far which gives the correct results except for that section since i don't see the logic behind it. This example uses lists and tuples for simplicity but you can change it to use array if you want.

>>> from itertools import groupby
>>> data = [0,1,2,3,4,3,2,3,-2,-4,-7,2,2]
>>> def slope(a,b): #Returns 1 for inc, 0 for equal and -1 for dec
        return (a > b) - (a < b) 

>>> def groups(nums):
        for k,v in groupby(zip(nums,nums[1:]), lambda (x,y): slope(x,y)):
            yield next(v) + tuple(y for x,y in v) #Using itertools.chain this can be written as tuple(chain(next(v),(y for x,y in v)))


>>> list(groups(data))
[(0, 1, 2, 3, 4), (4, 3, 2), (2, 3), (3, -2, -4, -7), (-7, 2), (2, 2)]
Sign up to request clarification or add additional context in comments.

12 Comments

+1, but I believe cmp only guarantees that it returns positive, negative or zero. docs.python.org/library/functions.html#cmp. Also, you could write just "cmp" rather than lambda (x, y): cmp(x, y)!
@Anonymous What is wrong with that? It is either increasing, decreasing or staying the same.
It may not return the same number for different comparisons. Eg, cmp(6, 3) could be 3 and cmp(3, 1) could be 2. This'll cause your groupby to fail to join these runs.
@Anonymouse I can't just write cmp since this takes each pair as a tuple and I would be passing a tuple to cmp, try it it doesn't work. Can you show me an example that would not work as you said?
@jamlak, thanks for inspiring us. i have never use groupby before, and i'll take time to study it now. i'll give you +1 too
|
2

I find all the places where the runs change, then generate the runs including both endpoints.

def sgn(x):
  return (x > 0) - (x < 0)

def categorize(xs):
  endpoints = [0]
  endpoints.extend(i for i, x in enumerate(xs[1:-1], 1)
                   if sgn(x - xs[i - 1]) != sgn(xs[i + 1] - x))
  endpoints.append(len(xs) - 1)
  for e0, e1 in zip(endpoints, endpoints[1:]):
    yield xs[e0:e1 + 1]

print list(categorize([0,1,2,3,4,3,2,3,-2,-4,-7,2,2]))
print list(categorize([0, 1, 2, 3]))
print list(categorize([0]))

Comments

0

How about this one using numpy, it solves your second problem at the same time.

import numpy as np

x=(0, 1, 2, 3, 4, 3, 2, 3, -2, -4, -7, 2, 2)
y=range(13)

#First order differential, find slopes
dx = list((np.diff(x)>0)*1)

#First order differental looses first value, but we always want to keep it
#just decide if it's lower or higher than the 2nd value

d0=((x[0]-x[1])>0)*1

#Add the first order differential to the 2nd order differential (peaks)
ddx = [d0,]+list(np.abs(np.diff(dx)))

p=0
rx=[]
ry=[]

for n,v in enumerate(ddx):
    if v==1:
        rx.append(tuple(x[p:n+1]))
        ry.append(tuple(y[p:n+1]))
        p=n

print rx
print ry

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.