Complex behaviour with lists - python

I need to make some strange and complex calculation with lists. I have tried and I have endeavored to get it up and running, but it runs into error. better saying quite difficult to achieve that behavior.
I have following lists.
A = [1,1,1,2,2,2]
B = [3,3] # B list is length of numbers 1 and 2.
E = [10,10]
C = 1
D = []
I have this code, but not really working:
for k in B:
for j in E:
for i in range(len(A)-k):
print(i)
if i == 0:
D.append(C)
else:
D.append(C+(E[k]))
print(D)
Explaining to achieve results.
I want to have a for-loop, which enables to append values to my empty list, which looks at first 3 values in the beginning of list A by taking B[0]= 3, do something with first 3 values. And looks at B[1]= 3, ie. take the last 3 values in the list A, then do something to them and append them all in order to empty list.
First 3 values:
When A[0] is selected, I want to have D[0] = C, and in case A[1] and A[2], B list should be B[1]= C + 1*E[0] and B[2]= C + 2*E[0].
Last 3 values:
When A[3] is selected, I want to have D[3] = C, and in case A[4] and A[5], B list should be B[4]= C + 1*E[1] and B[5]= C + 2*E[1].
Expected output:
[1,11,21,1,11,21]
I want to get it programmatically, in case changing A list to A = [1,1,2,2] and B = [2,2] or something else.

Initialization of your lists
A = [1,1,1,2,2,2]
B = [3,3] # B list is length of numbers 1 and 2.
E = [10,10]
C = 1
D = []
we want to count in A starting the first time from 0, the next times from the previous start plus how many items we have used, hence we initialize start
start = 0
We start a loop on the elements b of B, counting them in k, we extract from A the elements we need and update the start position for the next pass
for k, b in enumerate(B):
sub_A = A[start:start+b]
start = start+b
Now an inner loop on the elements a of the sub-list, counting them with i, note that for the first item i is zero and so we append C+0*E[k]=C, as requested
for i, _ in enumerate(sub_A):
D.append(C+i*E[k])
To see everything without my comments
start = 0
for k, b in enumerate(B):
sub_A = A[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
D.append(C+i*E[k])

Related

I want to make a list of list in python in loop

I want to get an output like
['a','aa','aaa','aaaa','aaaaa'],['b','bb','bbb','bbbb','bbbbb'],['c','cc','ccc','cccc','ccccc']
using the code snippet below
a = ["a","b","g","f"]
b =[1,2,3,4,5]
e = []
f = []
for i in a:
for j in b:
e.append(i*j)
f.append(e)
print(f)
Can anybody help me with this please
You're failing to reset e to a new empty list after each outer loop, so you're inserting a bunch of aliases to the same list. Just move the e = [] between the two fors (and indent to match), e.g.:
for i in a:
e = []
for j in b:
...
so you make a new list to populate on each loop.
Alternatively, as noted in the comments, a nested listcomp would do the trick:
f = [[x * y for x in b] for y in a]
removing the need for a named e at all (and running somewhat faster to boot).
It looks like you forgot to reset you e list with every iteration. This will yield your desired outcome:
a = ["a","b","g","f"]
b =[1,2,3,4,5]
e = []
f = []
for i in a:
e= []
for j in b:
e.append(i*j)
f.append(e)
print(f)
The only error is that you are not resetting e to [] after each iteration in a. Let me explain:
This is the code you need:
for i in a:
for j in b:
e.append(i*j)
f.append(e)
e = []
You need the e = [] at the end. If there was no e = [], at the end of thefirst iteration, e = ['a', 'aa'...]. During the second iteration, e would equal [a, aa, aaa, aaaa, aaaaa, b, bb, bbb...] However, setting it to an empty list stops this.
Python has a property that if u multiply a number with a string it will multiply that string for example:
print(2*"ab")
abab
You can use this for your answer:
a = ["a","b","g","f"]
b =[1,2,3,4,5]
c = [[x*y for x in b] for y in a]
print(c)
Lengthy, but this works fine too
a = ['a','b','c','d']
b = [1,2,3,4,5]
nest_array = []
for i in range(0,len(a)):
arr = []
for val in b:
str1 = ""
while len(str1) < val:
if len(str1) == val:
break
else:
str1 += a[i]
arr.append(str1)
nest_array.append(arr)
print(nest_array)

Are there any shorter way for this way?

Lets say i have variables a,b,c,d,e,f.. every time 2 of the 6 variables will have value = 0 randomly. So my code is like this
if(a == 0 and b == 0):
run c,d,e,f
elif(a == 0 and c == 0):
run b,d,e,f
...
...
continue until end of all combination
So the coding will be very long, are there any other approach ?
You can put all numbers into a list and then feed a list comp of that list into the run function - ignoring elements that are 0:
def run(p1,p2,p3,p4):
print(p1,p2,p3,p4)
# 3 test cases
for d in [ [ 1,2,0,3,4,0], [0,0,2,3,4,1], [4,3,0,2,1,0]]:
run(*[x for x in d if x]) # *[1,2,3] makes python provide the elements as params
Output:
1 2 3 4
2 3 4 1
4 3 2 1
run( *[1,2,3]) is the same as run(1,2,3)
0 is Falsy - so *[x for x in d if x] for a d=[0,1,2,3,0] does only use non falsy values of x in d: *[1,2,3]
truth value testing
you can exchange the list comp run(*[x for x in d if x]) against a generator comp if you like run(*(x for x in d if x)) to avoid the list creation (not that it matters here ;) )
#Mehrdad Dowlatabadi raised an interesting side question - if any other of the params is 0 you get an error due to a mismatch between function parameters and provided parameters from the list comprehension - you can negate that by defining defaults:
def run(p1=0, p2=0, p3=0, p4=0):
print(p1,p2,p3,p4)
So if you feed [0,1,2,0,0,0] into it it will still run.
If you want to run a function with the variables that aren't set to 0 you can first make a list of elements that are'nt 0
elements = [element for element in a, b, c, d, e if element !=0]
then call the function with elements list as arguments
run(*elements)
As a one liner :
run(*[element for element in a, b, c, d, e if element !=0])
Make run take a list:
def run(lst):
...
then use the filter function:
run(filter(None, [a, b, c, d, e, f]))
filter(None, lst) removes all fals-y elements.

Function which eliminates specific elements from a list in an efficient way

I want to create a function (without using libraries) which takes as input three integer numbers (>0) (a,b,c) , for example:
a = 6
b = 6
c = 3
and returns a list containing c elements (so in this case the returned list should contain 3 elements) taken from a list of a numbers (so in this case the initial list is [1,2,3,4,5,6]). The c elements of the returned list have to be the ones that managed to remain in the initial list after removing a number every b positions from the list of a elements until len(return_list) = c.
So for a = 6, b = 6 and c = 3 the function should do something like this:
1) initial_list = [1,2,3,4,5,6]
2) first_change = [2,3,4,5,6] #the number after the 6th (**b**) is 1 because after the last element you keep counting returning to the first one, so 1 is canceled
3) second_change = [2,4,5,6] #you don't start to count positions from the start but from the first number after the eliminated one, so new number after the 6th is 3 and so 3 is canceled
4) third_change = [2,4,5] #now the number of elements in the list is equal to **c**
Notice that if, when counting, you end up finishing the elements from the list, you keep the counting and return to the first element of the list.
I made this function:
def findNumbers(a,b,c):
count = 0
dictionary = {}
countdown = a
for x in range(1,a+1):
dictionary[x] = True
while countdown > c:
for key,value in dictionary.items():
if value == True:
count += 1
if count == b+1:
dictionary[key] = False
count = 0
countdown -= 1
return [key for key in dictionary.keys() if dictionary[key] == True]
It works in some cases, like the above example. But it doesn't work everytime.
For example:
findNumbers(1000,1,5)
returns:
[209, 465, 721, 977] #wrong result
instead of:
[209, 465, 721, 849, 977] #right result
and for bigger numbers, like:
findNumbers(100000, 200000, 5)
it takes too much time to even do its job, I don't know if the problem is the inefficiency of my algorithm or because there's something in the code that gives problems to Python. I would like to know a different approach to this situation which could be both more efficient and able to work in every situation. Can anyone give me some hints/ideas?
Thank you in advance for your time. And let me know if you need more explanations and/or examples.
You can keep track of the index of the last list item deleted like this:
def findNumbers(a, b, c):
l = list(range(1, a + 1))
i = 0
for n in range(a - c):
i = (i + b) % (a - n)
l.pop(i)
return l
so that findNumbers(6, 6, 3) returns:
[2, 4, 5]
and findNumbers(1000, 1, 5) returns:
[209, 465, 721, 849, 977]
and findNumbers(100000, 200000, 5) returns:
[10153, 38628, 65057, 66893, 89103]
I thought I could be recursive about the problem, so I wrote this:
def func(a,b,c):
d = [i+1 for i in range(a)]
def sub(d,b,c):
if c == 0: return d
else:
k = b % len(d)
d.pop(k)
d = d[k:] + d[:k]
return sub(d,b,c-1)
return sub(d,b,a-c)
so that func(6,6,3) returns: [2, 4, 5] successfully and func(1000,1,5) returns: [209, 465, 721, 849, 977] unfortunately with an error.
It turns out that for values of a > 995, the below flag is raised:
RecursionError: maximum recursion depth exceeded while calling a Python object
There was no need to try func(100000,200000,5) - lesson learnt.
Still, rather than dispose of the code, I decided to share it. It could serve as a recursive thinking precautionary.

How to compare 4 consecutive elements in a list?

I am new to coding so I apologize in advance if what I am asking is simple or doesn't make much sense but I will try to elaborate as much as I can. First of all this is not for any work or project I am simply studying to learn a bit of coding for my satisfaction. I've been trying to find some real life problems to apply into coding (pseudo code mostly but python language would also be kind of understandable to me).
I wanted to be able to have a list of x elements and compare 4 of them sequentially.
For example, myList = [a, b, c, d, e, f, g, h, i, j, k, l]
First I want to compare a,b,c and d.
If b>a, c>b, d>c and d> all of 3 previous ones (d>a, d>b, d>c) I want to do something otherwise go to next comparison.
Then I wanted to compare b,c,d and e.
Similarly if c>b, d>c, e>d and e> all of 3 previous ones (e>b, e>c, e>d) I want to do something otherwise go to next comparison.
What if my list contains infinite elements? myList = [:]
Where do I start? Do I have to have a starting point?
I am guessing I have to use a for loop to iterate through the list but I honestly can't figure out how to iterate through the first 4 elements and then continue from the second element in 4 element batches.
Since I am currently studying the Arrays and lists maybe there is some functionality I am missing? Or I simply my brain can grasp it.
I tried looking at other posts in stackoverflow but honestly I can't figure it out from other people's answers. I would appreciate any help or guidance.
Thanks in advance.
You can use the built-in all() function for this problem:
myList = [5, 4, 3, 6, 3, 5, 6, 2, 3, 10, 11, 3]
def do_somthing():
#your code here
pass
for i in range(len(myList)-4):
new_list = myList[i:i+4] #here, using list slicing to jump ahead four elements.
if all(new_list[-1] > b for b in new_list[:-1]) and all(new_list[:-1][c] > new_list[:-1][c+1] for c in range(len(new_list)-2)):
do_something()
L = [...]
# get all the valid indices of the elements in the list, except for the last 4. These are the indices at which the 4-element windows start
for i in range(len(L)-4):
window = L[i:i+4] # the 4 elements you want to compare
print("I am considering the elements starting at index", i, ". They are:", window)
a,b,c,d = window
if d>a>b>c<d and d>b:
print("The checks pass!")
Now, there is a simpler way to do this:
for a,b,c,d in (L[i:i+4] for i in range(len(L)-4):
if d>a>b>c<d and d>b:
print("The checks pass!")
to consume just one item at a time from an iterator and operate on 4 lagged elements try a circle buffer:
# make a generator as example of 'infinte list'
import string
agen = (e for e in string.ascii_lowercase)
# initialize len 4 circle buffer
cb = [next(agen) for _ in range(4)] # assumes there are at least 4 items
ptr = 0 # initialize circle buffer pointer
while True:
a,b,c,d = (cb[(i+ptr)%4] for i in range(4)) # get current 4 saved items
# some fuction here
print(a,b,c,d)
# get next item from generator, catch StopIteration on empty
try:
cb[ptr] = next(agen)
except StopIteration:
break
ptr = (ptr + 1)%4 # update circle buffer pointer
a b c d
b c d e
c d e f
d e f g
e f g h
f g h i
g h i j
h i j k
i j k l
j k l m
k l m n
l m n o
m n o p
n o p q
o p q r
p q r s
q r s t
r s t u
s t u v
t u v w
u v w x
v w x y
w x y z
'some function' could include a stopping condition too:
# random.choice() as example of 'infinte iterator'
import string
import random
random.choice(string.ascii_lowercase)
# initialize len 4 circle buffer
cb = [random.choice(string.ascii_lowercase) for _ in range(4)] # assumes there are at least 4 items
ptr = 0 # initialize circile buffer pointer
while True:
a,b,c,d = (cb[(i+ptr)%4] for i in range(4)) # get current 4 saved items
# some fuction here
print(a,b,c,d)
if a<b<c<d: # stopping condition
print("found ordered string: ", a,b,c,d)
break
# get next item from generator, catch StopIteration on empty
try:
cb[ptr] = random.choice(string.ascii_lowercase)
except StopIteration:
break
ptr = (ptr + 1)%4 # update circle buffer pointer
o s w q
s w q k
w q k j
q k j r
k j r q
j r q r
r q r u
q r u v
found ordered string: q r u v
Since you can index a list, how about start from index 0, compare the 0th, (0+1)th, (0+2)th, and (0+3)th elements. Then, by the next round, increase your index to 1, and compare the 1st, (1+1)th, (1+2)th, and (1+3)th elements, and so on. For the nth round, you compare the n, n+1, n+2, and (n+3)th elements, until you reach the 4th element before the end. This is how you generally do stuff like 'testing m elements each time from a sequence of length n', and you can easily expand this pattern to matrices or 3d arrays. The code you see in other answers are basically all doing this, and certain features in Python make this job very easy.
Now, 'what if the list contains infinite elements'? Well, then you'll need a generator, which is a bit advanced at this stage I assume, but the concept is very simple: you let a function read that infinite stream of elements in a (might be infinite) loop, set a cursor on one of them, return (yield) the element under the cursor as well as the 3 elements following it each time, and increase the cursor by one before the next loop starts:
def unsc_infinity(somelist):
cur = 0
while True:
yield somelist[c:c+4]
cur = cur + 1
infinity_reader = unsc_infinity(endless_stream)
next(infinity_reader)
# gives the 0, 1, 2, 3 th elements in endless_stream
next(infinity_reader)
# gives the 1, 2, 3, 4 th elements in endless_stream
next(infinity_reader)
# ...
And you can loop over that generator too:
for a, b, c, d in unsc_infinity(endless_stream):
if d>a>b>c<d and d>b:
do_something()
Hope that helps a bit for you to build a mental model about how this kind of problems are done.

How to iterate over list-of-list, and accumulate product of two fields

I have written some simple Python code that should select the second element of each list within the main list and provide the user with a sum of all of these values. It should also multiply the second and third elements of each list within the main list and then sum these values.
However, when I attempt to run this code I am confronted with a
list index out of range
error.
usa_univs = [ ['California Institute of Technology',2175,37704],
['Harvard',19627,39849],
['Massachusetts Institute of Technology',10566,40732],
['Princeton',7802,37000],
['Rice',5879,35551],
['Stanford',19535,40569],
['Yale',11701,40500] ]
def total_enrollment(usa_univs):
a = 0
c = (len(usa_univs)) -1
while c > 0:
a = a + ([c][1])
b = b + (([c][1])*([c][2]))
c = c - 1
print (a,b)
print total_enrollment(usa_univs)
Instead of
[c][1]
or
[c][2]
You need to use this syntax:
usa_univs[c][1]
You forgot a usa_univs before [c][1] and the like. You also need to initialize b, otherwise you will get a reference-before-assignment error in b = b + ((usa_univs[c][1])*(usa_univs[c][2])).
Although not very elegant, this should work:
def total_enrollment(usa_univs):
a = 0
b = 0
c = (len(usa_univs)) -1
while c > 0:
a = a + (usa_univs[c][1])
b = b + ((usa_univs[c][1])*(usa_univs[c][2]))
c = c - 1
print (a,b)
You are creating a new list with just one element every time, then indexing that:
[c][1]
With only one element, that indexing will fail. If c is an index into the usa_univs list, you do need to reference the list:
usa_univs[c][1]
However, rather than manually manage indexes into that list, use a for loop to access each element directly:
a = 0
b = 0
for element in usa_univs:
a = a + element[1]
b = b + (element[1] * element[2])
where I also set b to 0 (you forgot that part), and c is no longer needed at all.
Python lets you unpack sequences into their constituent parts; you can do so even in the for loop:
for name, a_value, b_value in usa_univs:
a = a + a_value
b = b + (a_value * b_value)
and you can use augmented assignment to make adding to a and b a little more compact:
for name, a_value, b_value in usa_univs:
a += a_value
b += a_value * b_value
In the end your function should use return rather than printing. Leave printing to the caller; you already do so but your function now returns None. Your whole code, with all these improvements, then looks like:
usa_univs = [ ['California Institute of Technology',2175,37704],
['Harvard',19627,39849],
['Massachusetts Institute of Technology',10566,40732],
['Princeton',7802,37000],
['Rice',5879,35551],
['Stanford',19535,40569],
['Yale',11701,40500] ]
def total_enrollment(usa_univs):
a = 0
b = 0
for name, a_value, b_value in usa_univs:
a += a_value
b += a_value * b_value
return a, b
print total_enrollment(usa_univs)
As, it has be said you forgot to use usa_univs[c][1]
Also, use simple pythonic for to iterate over each element( without having to worry about the indexing), and access the individual element
def total_enrollment(usa_univs):
a = 0
b = 0
for data in usa_univs:
a += data[1]
b += data[1] * data[2]
return a,b
print (total_enrollment(usa_univs))

Categories

Resources