This section of code is supposed to check if the neighboring points exist as part of the points list.
The points list is a given.
The check list is currently only checking the first item of the points list.
The counted list is supposed to show the points that exist within the points list that neighbor the first given point.
The rowNbr and colNbr are the following conditions of what points neighbor a given point.
points = [[3,2],[4,2],[4,3],[5,2],[5,3],[6,4]]
temp = [[3,2],[4,2],[4,3],[5,2],[5,3],[6,4]]
check = []
counted = []
rowNbr = [1, -1, 0, 0, 1, 1, -1, -1]
colNbr = [0, 0, 1, -1, 1, -1, 1, -1]
check.append(points[0])
for j in range(len(check)):
for i in range(len(rowNbr)):
temp[j][0] = check[j][0] + rowNbr[i]
temp[j][1] = check[j][1] + colNbr[i]
if temp[j] in points:
counted.append(temp[:])
print(counted)
I want it to print: [[4, 2], [4, 3]]
It prints out the following:
[[[2, 1], [4, 2], [4, 3], [5, 2], [5, 3], [6, 4]], [[2, 1], [4, 2], [4, 3], [5, 2], [5, 3], [6, 4]]]
If I include a print(temp[j]) line within the if temp[j] in points: loop, it prints the corect coordinates, but the counted list is wrong and printing out everything.
Why is this error occurring and how do I fix it?
counted.append(temp[:]) appends a copy of the whole temp array each time it is executed -- if you just want it to append a copy of temp[j], do counted.append(temp[j][:]) instead.
I think you are missing an element in the reference to temp[:] (should be counted.append(temp[j][:]) instead of counted.append(temp[:]):
points = [[3,2],[4,2],[4,3],[5,2],[5,3],[6,4]]
temp = [[3,2],[4,2],[4,3],[5,2],[5,3],[6,4]]
check = []
counted = []
rowNbr = [1, -1, 0, 0, 1, 1, -1, -1]
colNbr = [0, 0, 1, -1, 1, -1, 1, -1]
check.append(points[0])
for j in range(len(check)):
for i in range(len(rowNbr)):
temp[j][0] = check[j][0] + rowNbr[i]
temp[j][1] = check[j][1] + colNbr[i]
if temp[j] in points:
counted.append(temp[j][:])
print(counted)
Related
I have a list of lists:
[[1, 0], [2, 1], [5, 4], [1, 3], [4, 1], [3, 2], [0, <NA>]]
The list having <NA> as second element will always be the first list in nested list.
In the two subsequent lists, the first element of first list should match with second element of second list. e.g.: [0, <NA>], [1, 0], [2, 1]
The resultant list should cover all the elements from original list.
Expected output:
[[0, <NA>], [1, 0], [2, 1], [3, 2], [1, 3], [4, 1], [5, 4]]
Here, after [1, 0], we could have gone to [4, 1] as well; but that would be wrong since we won't be able to cover all the elements in the original list. I am using Python as programming language here. Any help would be appreciated. Please and thanks.
(Swapping your <NA> for a None) this looks for the longest path through the list that visits all elements exactly once.
def sort_path(elements):
def f(prefix, seq):
# get the current element to match
curr = prefix[-1][0] if len(prefix) > 0 else None
# get possible next nodes in path
next = [x for x in seq if x[1] == curr]
# get candidate paths from each next node
candidates = [f(prefix + [n], [x for x in seq if x != n]) for n in next]
# return the longest path from the candidates (or the prefix if no candidates)
return prefix if len(candidates) == 0 else max(candidates, key=len)
result = f([], elements)
return result if len(result) == len(elements) else None
input = [[1, 0], [2, 1], [5, 4], [1, 3], [4, 1], [3, 2], [0, None]]
print(sort_path(input))
# gives: [[0, None], [1, 0], [2, 1], [3, 2], [1, 3], [4, 1], [5, 4]]
This code produces your expected output using recursion.
your_list = [[1, 0], [2, 1], [5, 4], [1, 3], [4, 1], [3, 2], [0, '<NA>']]
first_item = [x for x in your_list if x[1] == '<NA>'][0] # Assuming only one of '<NA>' exists
remaining_list = your_list.copy()
remaining_list.remove(first_item)
def get_custom_order(remaining_list, ordered_list):
work_copy = remaining_list.copy()
start_value = ordered_list[-1][0]
for item in remaining_list:
if item[1] == start_value:
ordered_list.append(item)
work_copy.remove(item)
get_custom_order(work_copy, ordered_list)
break
return ordered_list
ordered_list = get_custom_order(remaining_list, [first_item])
print(ordered_list)
However, my answer is incomplete. This code only works because of the sorting of your list. It does not fulfill your requirement to cover sorting of all elements. I'll try to fix that and update my answer.
I have a project that goes like this:
Variables:
avail_res = [6, 4]
q_active = [2, 3, 4]
score = [3, 0, 10, 5]
populations = [[1, 0, 0], [0, 0, 0], [0, 1, 1], [0, 0, 1]]
chromosomes = []
for num in score:
if num <= avail_res[0]:
chromosomes.append(populations[score.index(num)])
if len(chromosomes) > 1:
k = random.choice(chromosomes)
chromosome_best = k
else:
chromosome_best = chromosomes
act = numpy.array([q_active[i] for i in numpy.flatnonzero(chromosome_best)])
The objective is to get activity in q_active corresponding to the non-zero value in chromosome_best. With the code above, the 1st step is to compare each element in score to avail_res[0]. If it satisfies the condition, then its corresponding population will be obtained and stored in chromosome_best where the non-zero value is used to get corresponding element in q_active. If chromosome_best is more than 1, then, it should choose which to select randomly.
The problem is after getting the output, the for loop is still 'looping'. So I am getting an output like this:
Output = [[1, 0, 0]] # obtained from the first loop
[0, 0, 0] # randomly selected on the 2nd iteration of for loop
[0, 0, 0] # randomly selected on the 3rd iteration of for loop
Expected Output for Populations = [[1, 0, 0]]
Expected Output for act = [2]
How could I make my code free from looping but still consider it when checking for the condition ( <= avail_res[0] )?
I tried making it if [num <= avail_res[0] for num in score]: but num gets undefined.
Any help would be appreciated! Thanks!
I would expect your code to be structured more like:
numpy
import random
avail_res = [4, 6]
q_active = [2, 3, 4]
scores = [3, 2, 8, 10]
populations = [[1, 0, 1], [0, 0, 1], [1, 1, 0], [1, 1, 1, 0]]
chromosomes = []
for score in scores:
if score <= avail_res[0]:
chromosomes.append(populations[scores.index(score)])
chromosome_best = random.choice(chromosomes)
act = numpy.array([q_active[i] for i in numpy.flatnonzero(chromosome_best)])
print(chromosome_best)
print(act)
An open question in my mind is why you only look at avail_res[0] and not the rest of avail_res -- i.e. we need to understand more about what's going on. Also, no need to handle a single entry in chromosomes specially, the random.choice() function will cope just fine.
How can I get product of nested list :
[[-1, 3, 1],[6, 1, 2],[4, 3, 1],[0, 1, 1]]
to:
[-3,12,12,1]
where eg : -1 * 3 * 1 = -3 and so on.
This is my current solution :
for i in range(len(array2)):
for j in range(len(array2[i])):
prod = array2[i][j] * array2[i][j + 1] * array2[i][j + 2]
print(prod)
I'm getting the following error :
IndexError: list index out of range
You might look at operator.mul combined with functools.reduce for this to make it short and very clear and totally avoid indexing (which is often the source of small errors):
from operator import mul
from functools import reduce
l = [[-1, 3, 1],[6, 1, 2],[4, 3, 1],[0, 1, 1]]
[reduce(mul, s) for s in l]
# [-3, 12, 12, 0]
Edit based on comment
If you want to ignore zeros, you can simply filter them out (this assumes that you don't have rows of all zeros, in which case it's not clear what the answer would be):
[reduce(mul, filter(None, s)) for s in l]
# [-3, 12, 12, 1]
Your index is out of bounds when you get j+1 and j+2, the correct way is to stop at len-2
array2 = [[-1, 3, 1],
[6, 1, 2],
[4, 3, 1],
[0, 1, 1]]
for i in range(len(array2)):
for j in range(len(array2[i])-2): # Check here the range
prod = array2[i][j] * array2[i][j + 1] * array2[i][j + 2]
print(prod)
Try the following function:
input_list = [[-1, 3, 1], [6, 1, 2], [4, 3, 1], [0, 1, 1]]
def compute_multiplication(nested_list):
for l in nested_list:
res = 1
for element in l:
res *= element
print(res)
With the final line being:
compute_multiplication(input_list)
This provides the following output:
-3
12
12
0
my_list = [[-1,3,1],[6,1,2],[4,3,1],[0,1,1]]
products = []
for sub_list in my_list:
partial_prod = 1
for item in sub_list:
partial_prod = partial_prod * item
products.append(partial_prod)
A solution using numpy.prod() :
import numpy
matrix = [
[-1, 3, 1],
[6, 1, 2],
[4, 3, 1],
[0, 1, 1]
]
for row in matrix:
prod = numpy.prod(row)
print(prod)
Assumption is that there are only three entries per row : a list comprehension should suffice. Multiply each item by the other in each row :
matrix = [
[-1, 3, 1],
[6, 1, 2],
[4, 3, 1],
[0, 1, 1]
]
first, make a condition to change zero values to 1 (this is based on the condition, that 0 be ignored and only the result of non zeros be returned)
filtered = [[ent if ent!= 0 else 1 for ent in row ] for row in matrix]
multiply each entry by the other
res = [start*middle*end for start,middle,end in filtered]
#[-3, 12, 12, 1]
if the number of entries is more than three, then #mark meyer's solution is apt for this
I am trying to write a program in python which should sort a list within a list.
Examples -
List before sorting: [[2, 1], [2, 2], [3, 3], [3, 1], [1, 1], [1, 2]]
List after sorting: [[1, 1], [1, 2], [2, 1], [2, 2], [3, 1], [3, 3]]
List before sorting: [[3, 3], [2, 2], [1, 2], [2, 1], [3, 1], [1, 1]]
List after sorting: [[1, 1], [2, 1], [1, 2], [2, 2], [3, 1], [3, 3]]
List before sorting: [[1, 1], [3, 3], [2, 1], [2, 2], [1, 2], [3, 1]]
List after sorting: [[1, 1], [1, 2], [2, 1], [2, 2], [3, 1], [3, 3]]
My code:
import math
def combsort(list1):
gap = len(list1)
shrink = 1.3
sorted = False
while sorted == False:
gap = gap/shrink
if gap > 1:
sorted = False
else:
gap = 1
sorted = True
i = 0
while i + gap < gap:
distance1 = math.sqrt(list1[i[0]]**2 + list1[i[1]]**2)
distance2 = math.sqrt(list1[i+gap[0]]**2 + list1[i+gap[1]]**2)
if distance1 > distance2:
temporary = list1[i]
list1[i] = list1[i + gap]
temporary = list1[i + gap]
sorted = False
i = i + 1
list1 = [[2, 1], [2, 2], [3, 3], [3, 1], [1, 1], [1, 2]]
combsort(list1)
print(list1)
My code doesn't work and prints out the exact same list. Any help?
This is what I was given to follow:
Comb sort is a variation of bubble sort that generally performs more efficient sorting. It accomplishes this by moving low values near the end of the list further toward the front of the list than bubble sort would during early iterations.
implement a function called combsort that does the following:
Takes as input a 2D list that contains information representing x/y points in 2D space. Each item in the list will be a list with 2
items an x and a y coordinate. For example, the list could be [ [0,
1],[2, 1], [3, 3], [1, 1], … ]
List item Performs an in-place sort (i.e., does not create a new list, but modifies the original) using the comb sort algorithm that
sorts the 2D list such that points with lower 2 Euclidean distance to
the origin (0, 0) appear earlier in the list. In this case, you are
comparing distances instead of directly comparing list values – it may
be useful to implement and use a distance calculation function. Note –
the Euclidean distance of a point (x, y) from the origin (0, 0) can be
calculated with the following equation: distance(x,y) = �! + �!
Does not return a value. As the input list is sorted in place, it will be modified directly and these modifications will be reflected
outside the function, so a return value is not needed.
The while loop never gets executed because its condition cannot be true:
while i + gap < gap:
Hint: use more print statements or a debugger to check the values of things while the program is running.
The error is in your while statement, it should be:
while i + gap < len(list1):
as shown in the pseudocode here. Currently the while loop is never even entered... which hides your other problems (see below).
You are indexing into a 2-D list wrong:
list1[i[0]] #get first item in list `i` and use that number to index into list1
list1[i][0] #get the ith sublist in list1 and get its first item
You need to make sure you use integers for your list indices:
gap = int(gap/shrink)
And for the grand finale....you swapped the order of your assignment, ruining your swap logic
temporary = list1[i + gap] #wrong
list1[i + gap] = temporary #should be this
You can also do this without the use of temporary in Python:
list1[i+gap], list1[i] = list1[i], list1[i+gap]
After all these changes, the code works as expected:
>>>combsort([[3, 3], [2, 2], [1, 2], [2, 1], [3, 1], [1, 1]])
[[1, 1], [2, 1], [1, 2], [2, 2], [3, 1], [3, 3]]
I'm trying to create a pair of functions that, given a list of "starting" numbers, will recursively add to each index position up to a defined maximum value (much in the same way that a odometer works in a car--each counter wheel increasing to 9 before resetting to 1 and carrying over onto the next wheel).
The code looks like this:
number_list = []
def counter(start, i, max_count):
if start[len(start)-1-i] < max_count:
start[len(start)-1-i] += 1
return(start, i, max_count)
else:
for j in range (len(start)):
if start[len(start)-1-i-j] == max_count:
start[len(start)-1-i-j] = 1
else:
start[len(start)-1-i-j] += 1
return(start, i, max_count)
def all_values(fresh_start, i, max_count):
number_list.append(fresh_start)
new_values = counter(fresh_start,i,max_count)
if new_values != None:
all_values(*new_values)
When I run all_values([1,1,1],0,3) and print number_list, though, I get:
[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1],
[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1],
[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1],
[1, 1, 1], [1, 1, 1], [1, 1, 1]]
Which is unfortunate. Doubly so knowing that if I replace the first line of all_values with
print(fresh_start)
I get exactly what I'm after:
[1, 1, 1]
[1, 1, 2]
[1, 1, 3]
[1, 2, 1]
[1, 2, 2]
[1, 2, 3]
[1, 3, 1]
[1, 3, 2]
[1, 3, 3]
[2, 1, 1]
[2, 1, 2]
[2, 1, 3]
[2, 2, 1]
[2, 2, 2]
[2, 2, 3]
[2, 3, 1]
[2, 3, 2]
[2, 3, 3]
[3, 1, 1]
[3, 1, 2]
[3, 1, 3]
[3, 2, 1]
[3, 2, 2]
[3, 2, 3]
[3, 3, 1]
[3, 3, 2]
[3, 3, 3]
I have already tried making a copy of fresh_start (by way of temp = fresh_start) and appending that instead, but with no change in the output.
Can anyone offer any insight as to what I might do to fix my code? Feedback on how the problem could be simplified would be welcome as well.
Thanks a lot!
temp = fresh_start
does not make a copy. Appending doesn't make copies, assignment doesn't make copies, and pretty much anything that doesn't say it makes a copy doesn't make a copy. If you want a copy, slice it:
fresh_start[:]
is a copy.
Try the following in the Python interpreter:
>>> a = [1,1,1]
>>> b = []
>>> b.append(a)
>>> b.append(a)
>>> b.append(a)
>>> b
[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
>>> b[2][2] = 2
>>> b
[[1, 1, 2], [1, 1, 2], [1, 1, 2]]
This is a simplified version of what's happening in your code. But why is it happening?
b.append(a) isn't actually making a copy of a and stuffing it into the array at b. It's making a reference to a. It's like a bookmark in a web browser: when you open a webpage using a bookmark, you expect to see the webpage as it is now, not as it was when you bookmarked it. But that also means that if you have multiple bookmarks to the same page, and that page changes, you'll see the changed version no matter which bookmark you follow.
It's the same story with temp = a, and for that matter, a = [1,1,1]. temp and a are "bookmarks" to a particular array which happens to contain three ones. And b in the example above, is a bookmark to an array... which contains three bookmarks to that same array that contains three ones.
So what you do is create a new array and copy in the elements of the old array. The quickest way to do that is to take an array slice containing the whole array, as user2357112 demonstrated:
>>> a = [1,1,1]
>>> b = []
>>> b.append(a[:])
>>> b.append(a[:])
>>> b.append(a[:])
>>> b
[[1, 1, 1], [1, 1, 1], [1, 1, 1]]
>>> b[2][2] = 2
>>> b
[[1, 1, 1], [1, 1, 1], [1, 1, 2]]
Much better.
When I look at the desired output I can't help but think about using one of the numpy grid data production functions.
import numpy
first_column, second_column, third_column = numpy.mgrid[1:4,1:4,1:4]
numpy.dstack((first_column.flatten(),second_column.flatten(),third_column.flatten()))
Out[23]:
array([[[1, 1, 1],
[1, 1, 2],
[1, 1, 3],
[1, 2, 1],
[1, 2, 2],
[1, 2, 3],
[1, 3, 1],
[1, 3, 2],
[1, 3, 3],
[2, 1, 1],
[2, 1, 2],
[2, 1, 3],
[2, 2, 1],
[2, 2, 2],
[2, 2, 3],
[2, 3, 1],
[2, 3, 2],
[2, 3, 3],
[3, 1, 1],
[3, 1, 2],
[3, 1, 3],
[3, 2, 1],
[3, 2, 2],
[3, 2, 3],
[3, 3, 1],
[3, 3, 2],
[3, 3, 3]]])
Of course, the utility of this particular approach might depend on the variety of input you need to deal with, but I suspect this could be an interesting way to build the data and numpy is pretty fast for this kind of thing. Presumably if your input list has more elements you could have more min:max arguments fed into mgrid[] and then unpack / stack in a similar fashion.
Here is a simplified version of your program, which works. Comments will follow.
number_list = []
def _adjust_counter_value(counter, n, max_count):
"""
We want the counter to go from 1 to max_count, then start over at 1.
This function adds n to the counter and then returns a tuple:
(new_counter_value, carry_to_next_counter)
"""
assert max_count >= 1
assert 1 <= counter <= max_count
# Counter is in closed range: [1, max_count]
# Subtract 1 so expected value is in closed range [0, max_count - 1]
x = counter - 1 + n
carry, x = divmod(x, max_count)
# Add 1 so expected value is in closed range [1, max_count]
counter = x + 1
return (counter, carry)
def increment_counter(start, i, max_count):
last = len(start) - 1 - i
copy = start[:] # make a copy of the start
add = 1 # start by adding 1 to index
for i_cur in range(last, -1, -1):
copy[i_cur], add = _adjust_counter_value(copy[i_cur], add, max_count)
if 0 == add:
return (copy, i, max_count)
else:
# if we have a carry out of the 0th position, we are done with the sequence
return None
def all_values(fresh_start, i, max_count):
number_list.append(fresh_start)
new_values = increment_counter(fresh_start,i,max_count)
if new_values != None:
all_values(*new_values)
all_values([1,1,1],0,3)
import itertools as it
correct = [list(tup) for tup in it.product(range(1,4), range(1,4), range(1,4))]
assert number_list == correct
Since you want the counters to go from 1 through max_count inclusive, it's a little bit tricky to update each counter. Your original solution was to use several if statements, but here I have made a helper function that uses divmod() to compute each new digit. This lets us add any increment to any digit and will find the correct carry out of the digit.
Your original program never changed the value of i so my revised one doesn't either. You could simplify the program further by getting rid of i and just having increment_counter() always go to the last position.
If you run a for loop to the end without calling break or return, the else: case will then run if there is one present. Here I added an else: case to handle a carry out of the 0th place in the list. If there is a carry out of the 0th place, that means we have reached the end of the counter sequence. In this case we return None.
Your original program is kind of tricky. It has two explicit return statements in counter() and an implicit return at the end of the sequence. It does return None to signal that the recursion can stop, but the way it does it is too tricky for my taste. I recommend using an explicit return None as I showed.
Note that Python has a module itertools that includes a way to generate a counter series like this. I used it to check that the result is correct.
I'm sure you are writing this to learn about recursion, but be advised that Python isn't the best language for recursive solutions like this one. Python has a relatively shallow recursion stack, and does not automatically turn tail recursion into an iterative loop, so this could cause a stack overflow inside Python if your recursive calls nest enough times. The best solution in Python would be to use itertools.product() as I did to just directly generate the desired counter sequence.
Since your generated sequence is a list of lists, and itertools.product() produces tuples, I used a list comprehension to convert each tuple into a list, so the end result is a list of lists, and we can simply use the Python == operator to compare them.