Given a certain array of positive and negative numbers, give the longest increasing or decreasing combination of elements of the array.

If our array is ```a = [a[0], a[1], ....a[n-1]]```:

i) For the increasing case:
there is a combination: ```a[i] < a[j] < a[k]..< a[p]```, such that ```0 ≤ i < j < k < ...< p ≤ n - 1```

For the decreasing case the combination would be:
```a[i] > a[j] > a[k]..> a[p]```, such that ```0 ≤ i < j < k < ...< p ≤ n - 1```

For that task create a function ```longest_comb()``` (Javascript: ```longestComb()``` )that will receive an array, and a command, one of the two kinds of strings: ```'< <' or '<<'``` (increasing), ```'> >' or '>>'``` (decreasing).

Let's see some examples:
```python
longest_comb([-1, 3, -34, 18, -55, 60, 118, -64], '< <') == [-1, 3, 18, 60, 118]

longest_comb([-1, 3, -34, 18, -55, 60, 118, -64], '> >') == [[-1, -34, -55, -64], [3, -34, -55, -64]] # outputs a 2D array of two combinations # of same length in the order that they appear in the given array from # left to right
```
We may have some cases without any possible combination:
```python
longest_comb([-26, 26, -36, 17, 12, 12, -10, -21], "< <") == []
```

On the other hand we may have cases with many solutions:
```python
longest_comb([-22, 40, -45, -43, -1, 7, 43, -56], "> >") == [[-22, -45, -56], [-22, -43, -56], [40, -45, -56], [40, -43, -56], [40, -1, -56], [40, 7, -56]]
```

Source: codewars | Difficulty: EASY
Tags: Data structures

Mathematics

Starter code: def longest_comb(arr, command):
	

Solutions:
from itertools import starmap, combinations
from operator import lt, gt

def longest_comb(arr, command):
	check = lt if command.startswith('<') else gt
	for i in range(len(arr), 2, -1):
		result = [list(x) for x in combinations(arr, i) if all(starmap(check, zip(x, x[1:])))]
		if result:
			return result[0] if len(result) == 1 else result
	return []


from operator import gt, lt

def longest_comb(arr, command):
	(max_length, stack, op) = (1, [], {'>': gt, '<': lt}[command[0]])
	for n in arr[::-1]:
		for i in range(len(stack)):
			if op(n, stack[i][0]):
				stack.append([n] + stack[i])
				max_length = max(max_length, len(stack[-1]))
		stack.append([n])
	ret = [seq for seq in stack if len(seq) == max_length][::-1]
	return [] if max_length < 3 else ret if len(ret) > 1 else ret.pop()


def longest_comb(a, cmd):
	r = comb(a, {'>>': lambda x, y: x > y, '<<': lambda x, y: x < y}[cmd.replace(' ', '')])
	r = [e for e in r if len(e) == max([len(k) for k in r] + [3])]
	return r[0] if len(r) == 1 else r

def comb(a, op):
	return [[e] for e in a] + [[v] + c for (i, v) in enumerate(a) for c in comb([e for e in a[i:] if op(v, e)], op)]


from operator import lt, gt
from itertools import combinations as c

def longest_comb(a, s):
	o = lt if s in '< <<' else gt
	for k in xrange(len(a) - 1, 2, -1):
		r = []
		for x in c(a, k):
			if all((o(x[i - 1], e) if i else True for (i, e) in enumerate(x))):
				r += [list(x)]
		if len(r):
			return r if len(r) > 1 else r[0]
	return []


from functools import reduce
from itertools import combinations

def longest_comb(arr, s):
	f = int.__lt__ if s[0] == '<' else int.__gt__
	ret = [list(c) for n in range(3, len(arr)) for c in combinations(arr, n) if all((f(c[i], c[i + 1]) for i in range(n - 1)))]
	m = max(map(len, ret), default=0)
	ret = [r for r in ret if len(r) == m]
	return ret if len(ret) != 1 else ret.pop()


from operator import gt, lt

def longest_comb(arr, command):
	cond = lt if command in ('< <', '<<') else gt
	lst = [[]]
	for a in arr:
		u = []
		for l in lst:
			if not l:
				u.append([a])
			elif cond(l[-1], a):
				u.append(l + [a])
			u.append(l)
		lst = u
	m_len = max(len(max(lst, key=len)), 3)
	ans = [l for l in lst if len(l) == m_len]
	return ans[0] if len(ans) == 1 else ans


from itertools import combinations

def longest_comb(arr, command):
	reverse = True if command[0] == '>' else False
	if arr == sorted(arr, reverse=reverse) and len(arr) == len(set(arr)):
		return arr
	n = len(arr) - 1
	while n > 2:
		r = []
		for c in combinations(range(0, len(arr)), n):
			a = [arr[i] for i in c]
			if a == sorted(a, reverse=reverse) and len(a) == len(set(a)):
				r.append(a)
		if len(r) == 1:
			return r[0]
		elif len(r) > 1:
			return r
		n -= 1
	return []


def longest_comb(arr, sign):
	comb = lambda p: [[(p, arr[p]), (p + j + 1, i)] for (j, i) in enumerate(arr[p + 1:]) if [arr[p] > i, arr[p] < i]['<' in sign]]
	m = []
	for (i, j) in enumerate(arr):
		r = comb(i)
		for (k, l) in enumerate(r):
			inner = comb(l[-1][0])
			if inner:
				r[k].append(inner.pop()[-1])
			if inner:
				for n in inner:
					r.append(r[k][:-1] + [tuple(n[-1])])
		m.extend(r)
	l = len(max(m, key=len))
	r = list(map(lambda x: list(map(lambda x: x[1], x)), sorted([i for i in m if len(i) == l], key=lambda x: [i[0] for i in x])))
	return (r if len(r) > 1 else r[0]) if l > 2 else []


def get_combos(arr, comm):
	if len(arr) == 1:
		return [arr]
	comm = comm.replace(' ', '')
	sublists = get_combos(arr[:-1], comm)
	newlists = []
	for sublist in sublists:
		if comm == '>>' and arr[-1] < sublist[-1] or (comm == '<<' and arr[-1] > sublist[-1]):
			newlists.append(sublist + [arr[-1]])
		newlists.append(sublist)
	newlists.append([arr[-1]])
	return newlists

def longest_comb(arr, comm):
	combos = get_combos(arr, comm)
	max_length = 3
	longest_combos = []
	for combo in combos:
		if len(combo) == max_length:
			longest_combos.append(combo)
		elif len(combo) > max_length:
			max_length = len(combo)
			longest_combos = [combo]
	if len(longest_combos) == 1:
		return longest_combos[0]
	else:
		return longest_combos


from itertools import combinations

def longest_comb(arr, command):
	(inc, mx, res) = (command.replace(' ', '') == '<<', 0, [])
	for k in range(len(arr), 2, -1):
		if k < mx:
			break
		for comb in combinations(arr, k):
			if inc and all((a < b for (a, b) in zip(comb, comb[1:]))) or (not inc and all((a > b for (a, b) in zip(comb, comb[1:])))):
				if k > mx:
					res = [list(comb)]
					mx = k
				elif k == mx:
					res.append(list(comb))
	return res[0] if len(res) == 1 else res