How do I count list items by every 10th element - python-3.x

I've got a list of tuples where I need to return a list of the frequency of elements per every 10-second interval depending on a variable ie
data_list =[(0, 84), (1, 84), (2, 84), (3, 84), (4, 84), (5, 84), (6, 84), (7, 84), (8, 84), (9, 84), (10, 84), (11, 84), (12, 84), (13, 84), (14, 84), (15, 84), (16, 84), (17, 84), (18, 84), (19, 84), (20, 84)]
and size = 3
should return
[[0, 10], [1, 10], [2, 1]]
as there are 10(index 2) elements in range 0-9(index 1), 10 elements in range 10-19 and 1 element in range 20-29
I was thinking about creating a for loop that creates x many lists depending on the variable size but not sure that would work at all. Then I tried using a counter but not sure how I would group them in groups of 10 and by the index
Any ideas would be much appreciated.
from collections import Counter
def get_frequency(tuple_list):
x = Counter(elem[0] for elem in tuple_list)
return x

Related

How to change two-dimension label to one-dimension label?

I have a two-dimension (10,2) coordinate which indicates each points label, like
coord_list = [(19, 17), (19, 17), (5, 26), (19, 17), (5, 26), (5, 26), (15, 17), (19, 5), (18, 6), (5, 26)]
I want to change it to a label list that only have one dimension (10,1),(assign a "label" to every unique item and replace each item by its label),like
label_list = [1,1,0....2,3]
I just want to classified points that have same coordinate in a same label, is there some more simple way can achieve it?
I tried to use this code,
label_list = []
for idx, coord in enumerate(coord_list):
if coord == (19,17):
label = 1
label_list.append(label)
if ...
But the problem is I don't know how many different coordinate in my coord_list, so I cannot write all if sentence in my code
Here's what I think you're after. I convert the list to a set, which eliminates duplicates. Then back to a list, and I sort it. Then I map each element of the original list to its index in that sorted list. There are only 5 unique points here, so the indexes will be from 0 to 4:
coord_list = [(19, 17), (19, 17), (5, 26), (19, 17), (5, 26), (5, 26), (15, 17), (19, 5), (18, 6), (5, 26)]
a = sorted(list(set(coord_list)))
print(a)
b = [a.index(i) for i in coord_list]
print(b)
Output:
[(5, 26), (15, 17), (18, 6), (19, 5), (19, 17)]
[4, 4, 0, 4, 0, 0, 1, 3, 2, 0]

algorithms and run-time analysis

A file (included with two examples) is a list of banned number intervals. A line that contains, for example, 12-18, indicates that all numbers 12 to (inclusive) 18 are prohibited. The intervals may overlap.
We want to know what the minimum number is.
Use variables to analyze run-time (not necessarily need all them):
• N: Maximum (not maximum permissible) number; So the numbers are between 0 and N
• K: number of intervals in a file
• M: width of maximum interval.
A. There is an obvious way to solve this problem: we're checking all numbers until we run into the smallest allowed.
• How fast is such an algorithm?
B. You can probably imagine another simple algorithm that uses N bytes (or bits) of memory.
(Hint: strikethrough.)
• Describe it with words. For example, you can make your own assignment (say a few intervals with numbers between 0 and 20), and show the algorithm on them. However, it also draws up a general description.
• How fast is this algorithm? When thinking, use N, K, and M (if you need it).
C. Make an algorithm that does not consume additional memory (more accurately: the memory consumption should be independent of N, K and M), but it is faster than the algorithm under point A.
• Describe it.
• How fast is it? Is it faster than the B algorithm?
D. Now we are interested in how many numbers are allowed (between 0 and N). How would you adjust the above algorithms for this question? What happens to their rates?
file = "0-19.txt"
intervals = [tuple(map(int, v.split("-"))) for v in open(file)]
#example# intervals = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]#
my current code just executes the program but better algorithms for the code i am yet to figure, still need a lot of work to understand, i would need a quick solution code/algorithm for examples A, B, and C and maybe D. Then i can study the time analysis myself. Appreciate help!
def generator_intervala(start, stop, step):
forbidden_numbers = set()
while start <= stop:
forbidden_numbers.add(start)
start += step
return (forbidden_numbers)
mnozica = set()
for interval in intervals:
a, b = interval
values = (generator_intervala(a, b, 1))
for i in values:
mnozica.add(i)
allowed_numbers = set()
N = max(mnozica)
for i in range(N):
if i not in mnozica:
allowed_numbers.add(i)
print(intervals)
print(mnozica)
print(min(allowed_numbers))
print(max(mnozica))
Output:
[(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19}
10
19
Your set approach is needlessly complex:
N = 100
ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
do_not_use = set()
for (a,b) in ranges:
do_not_use.update(range(a,b+1))
print(do_not_use)
print( min(a for a in range(N+1) if a not in do_not_use))
Is about all that is needed. Output:
set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19])
10
This is independend of N it just depends on how many numbers are in the ranges.
Storing only forbidden numbers in a set takes O(1) for checking, using the min() buildin over a range to get the minimum.
You can make it faster if you sort your tuples first and then iterate them until you find the first gap making it Θ(N log N) for the sort, followed by Θ(N) for the search:
def findme():
ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
ranges.sort() # inplace sort, no additional space requirements
if ranges[0][0]>0:
return 0
for ((a_min,a_max),(b_min,b_max)) in zip(ranges,ranges[1:]):
if a_max < b_min-1:
return a_max+1
return ranges[-1][1]+1 # might give you N+1 if no solution in 0-N exists
timeit of yours vs mine:
Your code uses 2 sets, as well as multiple loops, incremental addition to your set and function calls that makes it slower:
N = 100
def findme():
ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
ranges.sort()
if ranges[0][0]>0:
return 0
for ((a_min,a_max),(b_min,b_max)) in zip(ranges,ranges[1:]):
if a_max < b_min-1:
return a_max+1
return ranges[-1][1]+1
def mine():
ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
N = 100
do_not_use = set()
for (a,b) in ranges:
do_not_use.update(range(a,b+1))
return min(a for a in range(N+1) if a not in do_not_use)
def yours():
ranges = [(12, 18), (2, 5), (3, 8), (0, 4), (15, 19), (6, 9), (13, 17), (4, 8)]
def generator_intervala(start, stop, step):
forbidden_numbers = set()
while start <= stop:
forbidden_numbers.add(start)
start += step
return (forbidden_numbers)
mnozica = set()
for interval in ranges:
a, b = interval
values = (generator_intervala(a, b, 1))
for i in values:
mnozica.add(i)
allowed_numbers = set()
N = max(mnozica)
for i in range(N):
if i not in mnozica:
allowed_numbers.add(i)
return min(allowed_numbers)
import timeit
print("yours", timeit.timeit(yours,number=100000))
print("mine", timeit.timeit(mine,number=100000))
print("findme", timeit.timeit(findme,number=100000))
Output:
yours 1.3931225209998956
mine 1.263602267999886
findme 0.1711935210005322

Log plots in matplotlib is creating two lines

I was wondering why my loglog plots are creating two lines when it's just the orange one I want and why the labels won't show? Any insight would be greatly appreciated.
import matplotlib.pyplot as plt
data1 = [(3, 5034), (2, 4596), (4, 1469), (5, 1209), (6, 540), (7, 380), (8, 196), (9, 136), (10, 71), (11, 47), (12, 39), (13, 20), (14, 16), (15, 12), (16, 6), (18, 5), (17, 2), (19, 2), (22, 2), (1, 1), (24, 1), (20, 1)]
plt.loglog(data1, basex=2, basey=2, label='N1')
plt.show()

(Algorithms) Finding the shortest path that passes through a required set of nodes (possibly with BFS) and returns to the origin in Python

I am trying to find a shortest path that passes through a set of nodes [4,7,9] (order does not need to be preserved) and then returns to the origin (node 1). I have the set of edges:
E = [(1, 10), (1, 11), (2, 3), (2, 10), (3, 2), (3, 12), (4, 5), (4, 12), (5, 4), (5, 14), (6, 7), (6, 11), (7, 6), (7, 13), (8, 9), (8, 13), (9, 8), (9, 15), (10, 1), (10, 11), (10, 2), (11, 1), (11, 10), (11, 6), (12, 13), (12, 3), (12, 4), (13, 12), (13, 7), (13, 8), (14, 15), (14, 5), (15, 14), (15, 9)]
and I tried adapting the answer at How can I use BFS to get a path containing some given nodes in order? but yielded the error:
Traceback (most recent call last):
File "C:/Users/../rough-work.py", line 41, in <module>
graph[edge[0]].link(graph[edge[-1]])
KeyError: 15
My adapted code is as follows:
class Node:
def __init__(self, name):
self.name = name
self.neighbors = []
def link(self, node):
# The edge is undirected: implement it as two directed edges
self.neighbors.append(node)
node.neighbors.append(self)
def shortestPathTo(self, target):
# A BFS implementation which retains the paths
queue = [[self]]
visited = set()
while len(queue):
path = queue.pop(0) # Get next path from queue (FIFO)
node = path[-1] # Get last node in that path
for neighbor in node.neighbors:
if neighbor == target:
# Found the target node. Return the path to it
return path + [target]
# Avoid visiting a node that was already visited
if not neighbor in visited:
visited.add(neighbor)
queue.append(path + [neighbor])
###
n = 15
nodes = list(range(1,n))
E = [(1, 10), (1, 11), (2, 3), (2, 10), (3, 2), (3, 12), (4, 5), (4, 12), (5, 4), (5, 14), (6, 7), (6, 11), (7, 6), (7, 13), (8, 9), (8, 13), (9, 8), (9, 15), (10, 1), (10, 11), (10, 2), (11, 1), (11, 10), (11, 6), (12, 13), (12, 3), (12, 4), (13, 12), (13, 7), (13, 8), (14, 15), (14, 5), (15, 14), (15, 9)]
# Create the nodes of the graph (indexed by their names)
graph = {}
for letter in nodes:
graph[letter] = Node(letter)
print(graph)
# Create the undirected edges
for edge in E:
graph[edge[0]].link(graph[edge[-1]])
# Concatenate the shortest paths between each of the required node pairs
start = 1
path = [graph[1]]
for end in [4,7,9,1]:
path.extend( graph[start].shortestPathTo(graph[end])[1:] )
start = end
# Print result: the names of the nodes on the path
print([node.name for node in path])
What could possibly be the problem with the code? I will like to extend the graph to a arbitrarily large number of nodes, greater than 26 - the number of alphabets (as I infer that the previous implementation was only for character-based nodes). Or, if there is a more straightforward way in doing this that will be great!
Thanks and some help will be deeply appreciated!
The KeyError: 15 and your line print(graph) should have given you the clue: the latter shows that your graph dictionary contains only 14 entries, whereas your edges in E clearly make reference to 15 separate indices.
Change n = 15 to n = 16 and it works:
[1, 10, 2, 3, 12, 4, 12, 13, 7, 13, 8, 9, 8, 13, 7, 6, 11, 1]
Remember that:
>>> len(list(range(1,16)))
15

Python: Split list into list of lists

Suppose that I have list:
list = [(4, 7), (3, 7), (5, 7), (4, 6), (4, 8), (2, 7), (3, 6), (3, 8), (6, 7)]
That I want to divide the list into sublists of lengths: [2, 3, 4] (these lengths can vary)
To produce: sublist_list = [[(4, 7), (3, 7)],[(5, 7), (4, 6), (4, 8)], [(2, 7), (3, 6), (3, 8), (6, 7)]]
What's the quickest way that I can do this? Thanks in advance.
myList = [(4, 7), (3, 7), (5, 7), (4, 6), (4, 8), (2, 7), (3, 6), (3, 8), (6, 7)]
listOfLengths = [2, 3, 4]
def getSublists(listOfLengths,myList):
listOfSublists = []
for i in range(0,len(listOfLengths)):
if i == 0:
listOfSublists.append(myList[:listOfLengths[i]])
else:
listOfSublists.append(myList[listOfLengths[i-1]:listOfLengths[i-1]+listOfLengths[i]])
return listOfSublists
Then if you call getSublists on your myList (original list input) and listOfLengths (a list containing the length of your sublists), you get
#In: getSublists(listOfLengths,myList)
#Out: [[(4, 7), (3, 7)], [(5, 7), (4, 6), (4, 8)], [(4, 6), (4, 8), (2, 7), (3, 6)]]
You can user list[i:j] feature in python which returns a new list contains
list[i] to list[j-1] elements of original list.
base = 0
Lengths =[] #list of lengths
for num in Length:
sub_list.append(List[base:num+base])
base += num #jump to next length
What about simply iterating the list and appending to the new lists?
c = 0
for sublist in list:
sublistlist[len(sublistlist)-1].append(sublist)
c += 1
if c % 2:
sublistlist.append([])

Resources