I have a VERY simple question.
Honestly, I'm so sorry to ask you this stupid question but I really don't know how to do this.
I have a list like this.
p = [2, 5, 1, 2, 4, 1, 2, 5, 1, 2, 4, 1, 2, 4, 1, 2, 5, 1, 2, 4]
The elements in the list are usually the repetition of either 2, 4, 1 or 2, 5, 1.
Sometimes, there are no 1 at the end of 2, 4 or 2, 5.
I want to put 3 in the new list where the 3 consecutive elements of 2, 4, 1 or 2, 5, 1 are.
2, 4, 1 -> 3
2, 5, 1 -> 3
And I want to put 2 in the new list where the elements of 2, 4 or 2, 5 are.
2, 4 -> 2
2, 5 -> 2
Also, if there is either 2, 4 or 2, 5 at the end of the last 2, 4, 1 or 2, 5, 1, I need to put 3.
[2, 4, 1, 2, 5, 1, 2, 5] ==> [3, 3, 3]
However, if there are more than 2 of either 2, 4 or 2, 5 in a row after 2, 4, 1 or 2, 5, 1, I want to put 2 in the list like below.
[2, 4, 1, 2, 5, 2, 5] ==> [3, 2, 2]
My simple code below doesn't give me 2 at the end of the new list. Why is that?
Actually, I altered my code a lot and I am not getting what I want...
Any help will be GREATLY appreciated!
new_list = []
p = [2, 5, 1, 2, 4, 1, 2, 5, 1, 2, 4, 1, 2, 4, 1, 2, 5, 1, 2, 4]
#p = [2, 5, 1, 2, 4, 1, 2, 5, 1, 2, 4, 1, 2, 4, 1, 2, 5, 1, 2, 4, 2, 4]
#p = [2, 4]
for i in range(0, len(p)):
if i <= len(p) - 3:
if p[i] == 2 and p[i+1] >= 4:
if p[i+2] !=1:
new_list.append(2)
elif p[i+2] == 1:
new_list.append(3)
print(new_list)
Let's do it step by step :
new_list = []
p = [2, 5, 1, 2, 4, 1, 2, 5, 1, 2, 4, 1, 2, 4, 1, 2, 5, 1, 2, 4]
# p = [2, 4, 1, 2, 5, 1, 2, 5]
# p = [2, 4, 1, 2, 5, 2, 5]
sublists = []
# First we split the list on each 2
for i in p:
if i == 2:
sublists.append([2])
else:
sublists[-1].append(i)
# Then we add the size of each sublist to the new list
new_list = [len(x) for x in sublists]
# This is the same as:
# for i in sublists:
# new_list.append(len(i))
# Finally we check the particular case of a 2 at the end of the new list
if len(new_list) > 0 and new_list[-1] == 2:
new_list[-1] = 3
if len(new_list) > 1 and new_list[-2] == 2:
new_list[-1] = 2
print(new_list)
It's often a good idea when you are dealing with multiple elements in a list to split it into sub-lists for more clarity.
I hope you find that useful.
This is my method of doing it:
new_list = []
p = [2, 5, 1, 2, 4, 1, 2, 5, 1, 2, 4, 1, 2, 4, 1, 2, 5, 1, 2, 4]
while len(p) > 0:
if p[0] == 2:
if len(p) >= 3:
if p[1] == 4 and p[2] == 1:
new_list.append(3)
p.pop(0)
p.pop(0)
p.pop(0)
elif p[1] == 4 and p[2] != 1:
new_list.append(2)
p.pop(0)
p.pop(0)
elif p[1] == 5 and p[2] == 1:
new_list.append(3)
p.pop(0)
p.pop(0)
p.pop(0)
elif p[1] == 5 and p[2] != 1:
new_list.append(2)
p.pop(0)
p.pop(0)
else:
if p[1] == 4:
new_list.append(2)
p.pop(0)
p.pop(0)
elif p[1] == 5:
new_list.append(2)
p.pop(0)
p.pop(0)
print(new_list)
Firstly, we being a while loop that works until the list p has 0 elements.
Then, we check if the first element of the list starts with a 2. In this case it does. We then check if the second and third elements are 4 and 1. If they are, we add 3 to the new list, and then remove these 3 terms from the list so that their is no repetition.
We check this for the second and third elements 5 and 1 as well, and we also check if the third element is not 1. If it is not 1, we add a 2.
Then, the code is repeated in a if statement. This is because, when the list only has 2 elements left, the 2, 4 in this case, their would be an index error when we check if p[2] == 1, as their is no 3rd element. Therefore, when their are only 2 elements, we check to see if they are 2, 4 or 2, 5, and if so, add 2 to the list.
The code works as long as the first element of the list is a 2, which it seems like it always is.
Related
I have a list named A:
A = [1, 2, 1, 2, 1, 2, 3, 4, 5]
and I want to count the number of list [1, 2] appears in A.
It will be 3 because:
A = [1, 2, 1, 2, 1, 2, 3, 4, 5]
[1, 2][1, 2][1, 2] <- appears 3 times
Here is my code:
result = 0
while len(A) > 0:
temp, tA = [1, 2], A
for i in temp:
if len(tA) == 0: break
if i in tA: tA.pop(0)
result += 1
return result
And I wonder know is there any faster way to accomplish the same function?
Suppose that we are considering a sorted list of all non-decreasing sequences with values in the range (1, max_num) and num_slots elements in each sequence, how can I find the index of some given member sequence in O(1) time complexity? I am not actually given the entire list up-front, I just want to find the index of some member sequence were the list of all sequences to exist.
For a concrete example, suppose that max_num = 3 and num_slots = 4. Then there are 15 sequences (or generally, there are (max_num + num_slots - 1) choose (num_slots) sequences):
[[1, 1, 1, 1],
[1, 1, 1, 2],
[1, 1, 1, 3],
[1, 1, 2, 2],
[1, 1, 2, 3],
[1, 1, 3, 3],
[1, 2, 2, 2],
[1, 2, 2, 3],
[1, 2, 3, 3],
[1, 3, 3, 3],
[2, 2, 2, 2],
[2, 2, 2, 3],
[2, 2, 3, 3],
[2, 3, 3, 3],
[3, 3, 3, 3]]
So given inputs of a sequence like [1, 2, 2, 3] along with the information max_num = 3, I am trying to write a function that would return its correct index of 7. I do not actually have the list of all sequences to work with.
Background info
I have come up with an algorithm to generate all non-decreasing sequences I care about, but this doesn't seem completely relevant for generating the index of a particular member sequence without the whole list of sequences materialized.
def gen(max_num, num_slots, l = None):
if l is None:
l = [[1] * num_slots]
cur = l[-1].copy()
for i in reversed(range(num_slots)):
if cur[i] < max_num:
cur[i] += 1
for j in range(i+1, num_slots):
cur[j] = cur[i]
l.append(cur)
return gen(max_num, num_slots, l)
return l
This one is O(|seq| + max_num). Note that this is still much faster than the naive generate all and search approach, which is exponential in |seq|.
The idea is that you count the sequences before the input sequence. For example,
you want to know what's the index of [2, 4, 5, 6] when max_num = 6.
Count [1, *, *, *]
Count [2, 2, *, *]
Count [2, 3, *, *]
(Note: you cannot count [2, 4, *, *], because then you would include [2, 4, 6, 6] which comes after your input. You should always go until one less than your input at the given index)
Count [2, 4, 4, *]
Count [2, 4, 5, 5]
(for each row, you can use your formula, (max_num + num_slots - 1) choose (num_slots) and sum them up)
def combinations(slots, available):
return choose(slots + available - 1, slots)
def find_index(seq, max_num):
res = 0
for digit_index in xrange(len(seq)):
prev = seq[digit_index - 1] if digit_index > 0 else 1
for digit in xrange(prev, seq[digit_index]):
res += combinations(len(seq) - digit_index - 1, max_num - digit + 1)
return res
print find_index([1, 2, 2, 3], 3)
I'll elaborate on #DavidFrank's answer on why it is O(length+max_num) and give a more easily understand example (a bit more complex too).
To start with, observe:
Assume the total series possibility in F(length, max_num) = X
Then for all of possibilities in X that starts with 1, e.g. [1, ....], we have a count of F(length-1, max_num) within this group.
For all the possibility in X that does not start with 1, e.g. [2, ....] or [3, ....], we have a count of F(length, max_num-1).
Thus we can use recursion to get this in O(length*max_num) (can become O(length+max_num) if we use memoization) number of complexity:
# This calculate the total number of X of possible entry given (length, max_num)
def calc_sum(length, max_num):
if max_num == 1:
return 1
elif length == 1:
return max_num
else:
total = calc_sum(length-1, max_num) + calc_sum(length, max_num-1)
return total
Now we examine the result to see if we can make it O(1):
# This is clearly not going to make it O(1), so now we need some generalizations to NOT run this recursion.
import numpy as np
arr = np.zeros((6,6))
for i in range(6):
for j in range(6):
arr[i, j] = calc_sum(i+1, j+1)
print(arr)
The result is:
[[ 1. 2. 3. 4. 5. 6.]
[ 1. 3. 6. 10. 15. 21.]
[ 1. 4. 10. 20. 35. 56.]
[ 1. 5. 15. 35. 70. 126.]
[ 1. 6. 21. 56. 126. 252.]
[ 1. 7. 28. 84. 210. 462.]]
This is a pascal's triangle, if you look diagonally to the top right. The diagonals of pascal's triangle are defined by (x choose y)
This makes it clear that it cannot be O(1), and will at least be O(length+max_num) because this is the general complexity of (Choose) function.
We've went all the way to prove that an O(1) solution is impossible, unless we constrain (length + max_num) to be constant.
# We can expand by solving it now:
from scipy.special import comb # this is choose function.
def get_index(my_list, max_num):
my_list = np.array(my_list)
if len(my_list) == 1:
return my_list[0] - 1
elif my_list[0] == 1:
return get_index(my_list[1:], max_num)
elif my_list[0] != 1:
return get_index(my_list - 1, max_num - 1) + comb(len(my_list)-2+max_num, max_num-1)
get_index([1,2,2,3],3) # 7
The aggregated complexity of the final function with the comb() is still O(length + max_num) as the complexity of everything outside comb is O(length + max_num) as well.
There is bijection from the k-subsets of {1...n} (with repetition) to k-subsets of {1...n + k â 1} (without repetition) by mapping {c_0, c_1...c_(kâ1)} to {c_0, c_(1+1), c_(2+2)...c_(kâ1+kâ1)} (see here).
Once converted, just use your favourite combination ranking utility.
[3, 3, 3, 3] --> [3, 4, 5, 6]
[2, 3, 3, 3] --> [2, 4, 5, 6]
[2, 2, 3, 3] --> [2, 3, 5, 6]
[2, 2, 2, 3] --> [2, 3, 4, 6]
[2, 2, 2, 2] --> [2, 3, 4, 5]
[1, 3, 3, 3] --> [1, 4, 5, 6]
[1, 2, 3, 3] --> [1, 3, 5, 6]
[1, 2, 2, 3] --> [1, 3, 4, 6]
[1, 2, 2, 2] --> [1, 3, 4, 5]
[1, 1, 3, 3] --> [1, 2, 5, 6]
[1, 1, 2, 3] --> [1, 2, 4, 6]
[1, 1, 2, 2] --> [1, 2, 4, 5]
[1, 1, 1, 3] --> [1, 2, 3, 6]
[1, 1, 1, 2] --> [1, 2, 3, 5]
[1, 1, 1, 1] --> [1, 2, 3, 4]
import pyncomb
def convert(m, S):
return (m + len(S) - 1, [ x-1 + i for x,i in zip(S, list(xrange(len(S)))) ])
def rank(m, S):
k, s = convert(m, S)
return pyncomb.ksubsetcolex.rank(k, s)
print rank(3, [1,2,2,3])
# 7
For each digit, find the difference between that and the lowest digit. Add 1 for each changed position to the right of any altered digit
idx = 0;
for i in range(0,num_slots):
d = SEQ[i]
idx += d-min_num
if (d > min_num):
idx += num_slots-1 - i
For example:
[1,1,1,3] is 0 + 0 + 0 + (2+0) or 2
[1,2,3,3] is 0 + (1+2) + (2+1) + (2+0) or 8
[3,3,3,3] is (2+3) + (2+2) + (2+1) + (2+0) or 14
Here are examples:
given: 1,2,3 [list or range of numbers]
return: 2,1,3 [reordered list]
given: 1,2,3,4,5
return: 3 1 5 2 4
given: 1,2,3,4,5,6,7
return: 4 1 7 2 6 3 5 OR 4 7 1 5 3 2 6 or similar
given: 1,2,4,5,6,7,8,9
return: 5,1,9,3,7,2,8,4,6 or similar
In rendering you start with the center, then the most extreme cases, and become more and more detailed. This is NOT random. I'm in python, but theres got to be a name for this in comp sci. Help appreciated.
Edit to add
even case -
given: 1234
return: 2,1,4,3 OR 3,1,4,2 OR 2,4,1,3 OR 3,4,1,2
A valid, although ungraceful solution:
def sigorder(lst):
result = []
l = len(lst)
if l <= 2:
return lst
if l > 2:
result.append(lst[l/2])
result.append(lst[0])
result.append(lst[-1])
right = sigord(lst[l/2+1:-1])
left = sigord(lst[1:l/2])
result.extend(slicezip(left, right))
return result
Inner, recursive function:
def sigord(lst):
result = []
if len(lst) < 3:
return lst
else:
l = len(lst)
result.append(lst[l/2])
left = sigord(lst[0:l/2])
right = sigord(lst[l/2 + 1:len(lst)])
result.extend(slicezip(left, right))
return result
slicezip() (Note: conveniently handles the potential unevenness of the left/right lists automagically)
def slicezip(a, b):
result = [0]*(len(a)+len(b))
result[::2] = a
result[1::2] = b
return result
Outputs for lists length 4-9 :
[3, 1, 4, 2]
[3, 1, 5, 2, 4]
[4, 1, 6, 2, 5, 3]
[4, 1, 7, 2, 5, 3, 6]
[5, 1, 8, 3, 6, 2, 7, 4]
[5, 1, 9, 3, 7, 2, 6, 4, 8]
This should do it:
def extreme_cases(upd_itrr, new_itrr):
new_itrr.append(min(upd_itrr))
new_itrr.append(max(upd_itrr))
upd_itrr.remove(min(upd_itrr))
upd_itrr.remove(max(upd_itrr))
if len(upd_itrr) >= 2:
extreme_cases(upd_itrr, new_itrr)
return upd_itrr, new_itrr
def reordered_range(itr):
new_itr = []
center = 0
if len(itr) % 2 != 0:
center = itr[len(itr) // 2]
elif len(itr) % 2 == 0:
center = itr[(len(itr) // 2) - 1]
new_itr.append(center)
upd_itr = itr[:]
upd_itr.remove(center)
upd_itr, new_itr = extreme_cases(upd_itr, new_itr)
if upd_itr:
new_itr.append(upd_itr[0])
return new_itr
print(reordered_range([1, 2, 3]))
print(reordered_range([1, 2, 3, 4]))
print(reordered_range([1, 2, 3, 4, 5]))
print(reordered_range([1, 2, 3, 4, 5, 6, 7]))
print(reordered_range([1, 2, 4, 5, 6, 7, 8, 9]))
Output:
[2, 1, 3]
[2, 1, 4, 3]
[3, 1, 5, 2, 4]
[4, 1, 7, 2, 6, 3, 5]
[5, 1, 9, 2, 8, 4, 7, 6]
Another solution:
import numpy as np
from copy import copy
def bisecting_order(lst):
# bisecting order of an unordered list
result = []
l = len(lst)
if l < 3:
return lst
result.append(closest(lst,np.mean(lst)))
result.append(min(lst))
result.append(max(lst))
# get bisections
while len(result)!=len(lst):
temp_list = copy(result)
temp_list.sort()
for i in xrange(len(temp_list)-1):
newnum = closest(lst,np.mean([temp_list[i],temp_list[i+1]]))
if newnum in result:
continue
else:
result.append(newnum)
return result
def closest(mylist,mynum):
return min(mylist, key=lambda x:abs(x-mynum))
Here is the code.
x=0
result=[]
for n in range(1,5):
x=x+n;
for i in range(1,10):
if x%i==0:
result.append(i)
print(x,result)
Here I have generated triangular numbers.I want to find the divisors of each triangular number.but when I execute the code I am getting the following output.
1 [1]
3 [1, 1]
3 [1, 1, 3]
6 [1, 1, 3, 1]
6 [1, 1, 3, 1, 2]
6 [1, 1, 3, 1, 2, 3]
6 [1, 1, 3, 1, 2, 3, 6]
10 [1, 1, 3, 1, 2, 3, 6, 1]
10 [1, 1, 3, 1, 2, 3, 6, 1, 2]
10 [1, 1, 3, 1, 2, 3, 6, 1, 2, 5]
Also same triangular number is repeated for several times.So I need an output looks like,
1 [1]
3 [1, 3]
6 [1, 2, 3, 6]
10 [1, 2, 5]
How can I get the output like this?thank you.
You are appending to the same result list inside the loop. You should create a new result list in the outer loop. And your print statement is wrongly indented. Move it outside the inner loop.
Your code should be:
x=0
for n in range(1,5):
x=x+n;
result = []
for i in range(1,10):
if x%i==0:
result.append(i)
print(x,result)
Output:
1 [1]
3 [1, 3]
6 [1, 2, 3, 6]
10 [1, 2, 5]
To find divisor of a number you can use this function
def divisors(n):
divisors=[]
for i in range(1,int(n**0.5)+1):
if n%i == 0:
divisors.extend((i,n/i))
return list(set(divisors))
if you find a number i which can divide a number n, both n and n/i become divisors..
The only problem will be with perfect square numbers where its root will be added twice(if i become root of n, n/i and i are equal and both will be added to list).
It is solved by set() function.
I have a hard time trying to figure out how to generate the arrangements via backtracking on python, it is something they asked us at university
A group of n (n<=10) persons, numbered from 1 to n are placed on a row
of chairs, but between every two neighbor persons some conflict of
interests appeared. Display all the possible modalities to replace the
persons, such that between any two persons in conflict stays one or at
most two other persons.
I managed to modify the code for the permutations and the queens but i don`t really know where to put the condition for example k is the number and k must be different from the previous number in the string +1 and must bee different from the next number+1
The list of person sitting on the chairs is 1 2 3 4 (is impossible for less then 3 persons)
one right solution will be 1 3 4 2 and 3 1 4 2
Here is the code:
class Permutations(Backtracking):
def __init__(self, n):
Backtracking.__init__(self, n)
def _init_value(self, k):
return 0
def _next_value(self, n, k, v):
if v < n:
return v + 1
return None
def _cond(self, k, possible, v):
if v is None:
return False
try:
possible[:k].index(v)
return False
except ValueError:
return True
def _solution(self, n, k, possible):
return k == n-1
def _handle_solution(self, n, k, possible):
print(possible)
def chairs(soln, i=0):
if i == len(soln):
yield tuple(soln)
for j in xrange(i, len(soln)):
if i == 0 or soln[j] not in (soln[i - 1] + 1, soln[i - 1] - 1):
soln[i], soln[j] = soln[j], soln[i]
for s in chairs(soln, i + 1):
yield s
soln[i], soln[j] = soln[j], soln[i]
print list(chairs(range(1, 5)))
Code:
def possible_solution(remaining, sol=None):
sol = sol or []
if not remaining:
yield sol
else:
for i, candidate in enumerate(remaining):
if not sol or abs(sol[-1] - candidate) != 1:
new_sol = sol + [candidate]
new_remaining = remaining[:i] + remaining[i+1:]
for x in possible_solution(new_remaining, new_sol):
yield x
Test code:
def possible_solutions(neighbors):
for solution in possible_solution(neighbors):
print solution
print '-' * 30
possible_solutions([1, 2, 3])
print '-' * 30
possible_solutions([1, 2, 3, 4])
print '-' * 30
possible_solutions([1, 2, 3, 4, 5])
Results:
------------------------------
------------------------------
[2, 4, 1, 3]
[3, 1, 4, 2]
------------------------------
[1, 3, 5, 2, 4]
[1, 4, 2, 5, 3]
[2, 4, 1, 3, 5]
[2, 4, 1, 5, 3]
[2, 5, 3, 1, 4]
[3, 1, 4, 2, 5]
[3, 1, 5, 2, 4]
[3, 5, 1, 4, 2]
[3, 5, 2, 4, 1]
[4, 1, 3, 5, 2]
[4, 2, 5, 1, 3]
[4, 2, 5, 3, 1]
[5, 2, 4, 1, 3]
[5, 3, 1, 4, 2]