G'day. I am new to coding and python.
My goal is to try to create a code where if the element in y reaches the next 0, all the 0 to n (before the next zero) will become n. A sample output should look like this after executing the code below:
y = [0,1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7]
# I am interating over two inputs. y_1 = y[1:] and append 0 at the end.
y_1 = [1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7,0]
expected output:
x = [8, 8, 8, 8, 8, 8, 8, 8, 8, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7]
The problem I'm facing I believe comes from the while loop not looping over after [0,1,2,3,4,5,6,7,8] is deleted from the list as specified in the code below (which logically to me should loop over?) :
y = [0,1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7]
y_1 = [1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7,0]
x = []
while len(y):
for i, j in zip(y, y_1):
if i > j:
z = i
for k in range(z+1):
x.append(y[i])
del y[0:z+1]
del y_1[0:z+1]
elif i == j:
z = 0
x.append(z)
del y[z]
del y_1[z]
Any suggestion would be greatly appreciated :)
I don't know why you use del and while because you should get expected result doing
y = [0,1,2,3,4,5,6,7,8,0,1,0,1,2,3,4,5,6,7]
y_1 = y[1:] + [0]
x = []
for i, j in zip(y, y_1):
if i > j:
z = i
for k in range(z+1):
x.append(y[i])
elif i == j:
z = 0
x.append(z)
print(x)
In Python you shouldn't delete element from list which you use as for-loop because when it delete element then it moves other elements in list used as for-loop and it can give unexpected results.
If you really want to run it in some while len(y) then you should rather create new list with elements which you want to keep. Or you should duplicate list - y_duplicated = y.copy() - and delete in duplicated list and after for-loop replace original list y = y_duplicated
Related
I have run into a very frustrating problem in Python. I am trying to make a sorting algorithm that works like so:
I read one variable from a list
I check how many variables have a lower value than that variable and assign that to a place variable
The current variable is put in its place
continue to the next variable and repeat
The problem is that the dummy variable automatically resets to zero after being incremented. I can't do step by step program running, so figuring out what's wrong is very difficult.
I have very little experience with python, so any help is greatly appreciated.
# sorting algorithm
theList = [9, 7, 8, 5, 6, 3, 4, 1, 2, -1]
def order(n):
a = 0
m = n
print(n)
print(m)
while a < len(n):
b = 0
c = 0 #this is where the problem is
while b < len(n):
if n[b] < n[a]:
c += 1 # after this if statement isn't true, c reverts to zero
print(c)
b += 1
#I think I should be able to put m[c] = n[a], but this doesn't work
a += 1
print(n)
print(m)
order(theList)
m = n
Does not create a new list. It just maps the name m to the same list that n points to. So when you do m[c] = n[a] the original list also changes - hence the unexpected behaviour.
Try:
def order(n):
a = 0
m = n[:] # create copy
print(n)
print(m)
while a < len(n):
b = 0
c = 0
while b < len(n):
if n[b] < n[a]:
c += 1
print(c)
b += 1
m[c] = n[a] # assign in output
a += 1
print(n)
print(m)
This does create a copy & seems to solve the issue:
...
[9, 7, 8, 5, 6, 3, 4, 1, 2, -1]
[-1, 1, 2, 3, 4, 5, 6, 7, 8, 9]
PS: sorting should not require a copy of the list to be made. There are better algorithms that can modify the list in-place.
What should I do if I want to get the sum of every 3 elements?
test_arr = [1,2,3,4,5,6,7,8]
It sounds like a map function
map_fn(arr, parallel_iterations = True, lambda a,b,c : a+b+c)
and the result of map_fn(test_arr) should be
[6,9,12,15,18,21]
which equals to
[(1+2+3),(2+3+4),(3+4+5),(4+5+6),(5+6+7),(6+7+8)]
I have worked out a solution after reviewing the official docs: https://www.tensorflow.org/api_docs/python/tf/map_fn
import tensorflow as tf
def tf_map_elements_every(n, tf_op, input, dtype):
if n >= input.shape[0]:
return tf_op(input)
else:
return tf.map_fn(
lambda params: tf_op(params),
[input[i:i-n+1] if i !=n-1 else input[i:] for i in range(n)],
dtype=dtype
)
Test
t = tf.constant([1, 2, 3, 4, 5, 6, 7, 8])
op = tf_map_elements_every(3, tf.reduce_sum, t, tf.int32)
sess = tf.Session()
sess.run(op)
[Out]: array([ 6, 9, 12, 15, 18, 21])
It's even easier: use a list comprehension.
Slice the list into 3-element segments and take the sum of each.
Wrap those in a list.
[sum(test_arr[i-2:i+1])
for i in range(2, len(test_arr))]
Simply loop through your array until you are 3 from the end.
# Takes a collection as argument
def map_function(array):
# Initialise results and i
results = []
int i = 0
# While i is less than 3 positions away from the end of the array
while(i <= (len(array) - 3)):
# Add the sum of the next 3 elements in results
results.append(array[i] + array[i + 1] + array[i + 2]
# Increment i
i += 1
# Return the array
return results
I am having trouble with my code, I am writing a method that will check if the next element is smaller than the previous element and if it is, it will delete it.
Example:
Input: [1, 20, 10, 30]
Desired output: [1,20,30]
Actual output: [30]
def findSmaller(s):
i = -1
y = []
while i <= len(s):
for j in range(len(s)):
if s[i+1] <= s[i]:
del s[i + 1]
y.append(s[i])
i += 1
return y
If you are uncertain about how your loops work I recommend adding in some print statements. That way you can see what your loop is actually doing, especially in more complicated problems this is useful.
Something like this would solve your problem.
a = [1,2,3,2,4]
for k in range(0,len(a)-2): #-2 so that one don't go past the loops length
#print(k)
y = a
if(a[k]>a[k+1]):
del y[k+1] #delete the k+1 element if it is
>>> s = [5, 20, 10, 15, 30]
>>> max_so_far = s[0]
>>> result = []
>>> for x in s:
if x >= max_so_far:
result.append(x)
max_so_far = x
>>> result
[5, 20, 30]
Depending whether you need to do some calculation later with the list you can use a generator
s = [1, 20, 10, 30]
def find_smaller_generator(l: list):
last_item = None
for item in l:
if last_item is None or item >= last_item:
last_item = item
yield item
def find_smaller_list(l: list):
return list(find_smaller_generator(l))
print(find_smaller_list(s))
for i in find_smaller_generator(s):
print(i)
print([i**2 for i in find_smaller_generator(s)])
this returns:
[1, 20, 30]
1
20
30
[1, 400, 900]
You can try something like this
def findSmaller(s):
# sets p (previous) as the first value in s
p = s[0]
# initializes y to be an array and sets the first value to p
y = [p]
# iterates over s, starting with the second element
for i in s[1::]:
# checks if i is greater than or equal to the previous element
if i >= p:
# if it is, i is appended to the list y
y.append(i)
# also set the previous value to i, so the next iteration can check against p
p = i
#returns the list
return y
What this does is iterate over s and checks if the current item in the list is greater than or equal to the previous element in the list. If it is then it appends it to y, and y is returned.
Try out the code here.
Say I have a list,
A = range(1, 6) = [1, 2, 3, 4, 5]
B, the end result, is a list of lists. Given i and j, how would you make a list of iterative sums where index i bounds one side and j the other?
B[j] = sum(A[j:i+1] or A[i:j+1]) depending on whether j or i is larger.
Examples for indices 0 and 2:
B[0] = [1, 1+2, 1+2+3, 1+2+3+4, 1+2+3+4+5]
= [1, 3, 6, 10, 15]
B[2] = [1+2+3, 2+3, 3, 3+4, 3+4+5]
= [6, 5, 3, 7, 12]
======
Current code (works) is two for loops, very brute force. I think there should be a way to use reduce?
A = range(1,6)
n = len(A)
B = []
for j in xrange(n):
b = []
for i in xrange(n):
if j <= i:
b.append(sum(A[j:i+1]))
else:
b.append(sum(A[i:j+1]))
B.append(b)
# print
for b in B:
print b
Minor context: possibly part of my solution to project euler 82
You end up recalculating the sums many times. Instead create them once and look them up for each element of b:
A = range(1,6)
n = len(A)
mapping = {}
for i in xrange(n):
for j in xrange(i,n):
mapping[i,j] = sum(A[i:j+1])
B = []
for j in xrange(n):
b = []
for i in xrange(n):
if j <= i:
b.append(mapping[j,i])
else:
b.append(mapping[i,j])
B.append(b)
you could eliminate the need to check j<=i if you just make the mapping work for both [i,j] or [j,i]:
mapping = {}
A = range(1,6)
n = len(A)
for i in xrange(n):
for j in xrange(i,n):
mapping[i,j] = sum(A[i:j+1])
mapping[j,i] = mapping[i,j] #for both ways
B = [[mapping[i,j] for i in xrange(n)] for j in xrange(n)]
Although notice that this means that every B[x][y] will directly coordinate to mapping[x,y] so you may just want to use the mapping by itself.
I've never worked with 2D or 3D arrays before but i'm trying to make a maze.
In my snippet, squares is a list with each instance of a cell (so in a 3x4 maze, there would be 12 instances in squares)
I am then trying to append to row, a list of all the squares in a row, so row[0] would contain the first four square instances, row[1] would be the next four, etc.
the row[x].append(squares[y+z]) throws the IndexError, i'm guessing it's the row[x] part, but i'm not sure what to do to fix it. I tried using extend instead of append.
numberOfRows = 3
numberOfColumns = 4
z = 0
for x in range(numberOfRows):
for y in range(numberOfColumns):
row[x].append(squares[y+z])
z += 4
If I'm guessing it right, you want:
numberOfRows = 3
numberOfColumns = 4
z = 0
squares = range(numberOfRows * numberOfColumns)
row = [[] for _ in xrange(numberOfRows)]
for x in range(numberOfRows):
for y in range(numberOfColumns):
row[x].append(squares[y+z])
z += 4
print row
i.e., you were only missing the row definition.
EDIT:
After reading OP's comments, it seems that considering the following alternative is worth for the situation:
row = []
for x in range(numberOfRows):
row.append([squares[y+z] for y in range(numberOfColumns)])
z += numberOfColumns
So you don't create all the lists in row beforehand.
This can be simplified to the following:
>>> [squares[i:i+numberOfColumns] for i in range(0, len(squares), numberOfColumns)]
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]