Randomizing logic in python using enumerate [duplicate] - python-3.x

This question already has answers here:
A weighted version of random.choice
(28 answers)
Closed 1 year ago.
Need to write a program using Randomizing logic(Python). It can be like a generic function which takes versions and probability as input and returns a version. Probability can be anything like 1/2,1/3,1/4,1/5 and versions should be equally distributed accordingly

Python has a built-in random library that has a choice function that can do exactly what you want.
import random
My_choice = random.choices(population, weights=None, cum_weights=None, k=1)
The value of the weights may be used to build a non-uniform probability density function. and cum_weights can be used to make a uniform probability with the sum of all weights.
You can read more about the random modules in their documentation.

from random import randint
def random_version_generator(no_of_version):
"""
As we have only 4 versions of template currently limiting with the
validation and returning version 1
"""
if no_of_version > 4:
return 1
r =randint(0,100)
propability_per_version = [100 // no_of_version + int(x < 100 % no_of_version)for x in range(no_of_version)]
for idx, i in enumerate(range(len(propability_per_version))):
if r <= propability_per_version[i]:
return idx + 1
elif r <= propability_per_version[i] + propability_per_version[i+1]:
return idx + 2
elif r <= propability_per_version[i] + propability_per_version[i+1] + propability_per_version[i+1]:
return idx + 3
else:
return idx + 4
You can get more about randomizing logic here https://www.geeksforgeeks.org/write-a-function-to-generate-3-numbers-according-to-given-probabilities/
To Know Regarding enumerate click here https://www.geeksforgeeks.org/enumerate-in-python/

Related

Dijkstra's algorithm in graph (Python)

I need some help with the graph and Dijkstra's algorithm in python 3. I tested this code (look below) at one site and it says to me that the code works too long. Can anybody say me how to solve that or paste the example of code for this algorithm? I don't know how to speed up this code. I read many sites but l don't found normal examples...
P.S. Now l edit code in few places and tried to optimize it, nut it still too slow(
from collections import deque
class node:
def __init__(self, name, neighbors, distance, visited):
self.neighbors = neighbors
self.distance = distance
self.visited = visited
self.name = name
def addNeighbor(self, neighbor_name, dist): # adding new neighbor and length to him
if neighbor_name not in self.neighbors:
self.neighbors.append(neighbor_name)
self.distance.append(dist)
class graph:
def __init__(self):
self.graphStructure = {} # vocabulary with information in format: node_name, [neighbors], [length to every neighbor], visited_status
def addNode(self, index): # adding new node to graph structure
if self.graphStructure.get(index) is None:
self.graphStructure[index] = node(index, [], [], False)
def addConnection(self, node0_name, node1_name, length): # adding connection between 2 nodes
n0 = self.graphStructure.get(node0_name)
n0.addNeighbor(node1_name, length)
n1 = self.graphStructure.get(node1_name)
n1.addNeighbor(node0_name, length)
def returnGraph(self): # printing graph nodes and connections
print('')
for i in range(len(self.graphStructure)):
nodeInfo = self.graphStructure.get(i + 1)
print('name =', nodeInfo.name, ' neighborns =', nodeInfo.neighbors, ' length to neighborns =', nodeInfo.distance)
def bfs(self, index): # bfs method of searching (also used Dijkstra's algorithm)
distanceToNodes = [float('inf')] * len(self.graphStructure)
distanceToNodes[index - 1] = 0
currentNode = self.graphStructure.get(index)
queue = deque()
for i in range(len(currentNode.neighbors)):
n = currentNode.neighbors[i]
distanceToNodes[n - 1] = currentNode.distance[i]
queue.append(n)
while len(queue) > 0: # creating queue and visition all nodes
u = queue.popleft()
node_u = self.graphStructure.get(u)
node_u.visited = True
for v in range(len(node_u.neighbors)):
node_v = self.graphStructure.get(node_u.neighbors[v])
distanceToNodes[node_u.neighbors[v] - 1] = min(distanceToNodes[node_u.neighbors[v] - 1], distanceToNodes[u - 1] + node_u.distance[v]) # update minimal length to node
if not node_v.visited:
queue.append(node_u.neighbors[v])
return distanceToNodes
def readInputToGraph(graph): # reading input data and write to graph datatbase
node0, node1, length = map(int, input().split())
graph.addNode(node0)
graph.addNode(node1)
graph.addConnection(node0, node1, length)
def main():
newGraph = graph()
countOfNodes, countOfPairs = map(int, input().split())
if countOfPairs == 0:
print('0')
exit()
for _ in range(countOfPairs): # reading input data for n(countOfPairs) rows
readInputToGraph(newGraph)
# newGraph.returnGraph() # printing information
print(sum(newGraph.bfs(1))) # starting bfs from start position
main()
The input graph structure may look like this:
15 17
3 7 2
7 5 1
7 11 5
11 5 1
11 1 2
1 12 1
1 13 3
12 10 1
12 4 3
12 15 1
12 13 4
1 2 1
2 8 2
8 14 1
14 6 3
6 9 1
13 9 2
I'm only learning python so l think l could do something wrong(
The correctness of Dijkstra's algorithm relies on retrieving the node with the shortest distance from the source in each iteration. Using your code as an example, the operation u = queue.popleft() MUST return the node that has the shortest distance from the source out of all nodes that are currently in the queue.
Looking at the documentation for collections.deque, I don't think the implementation guarantees that popleft() always returns the node with the lowest key. It simply returns the left most item in what is effectively a double linked list.
The run time of Dijkstra's algorithm (once you implement it correctly) almost entirely lies on the underlying data structure used to implement queue. I would suggest that you first revisit the correctness of your implementation, and once you can confirm that it is actually correct, then start experimenting with different data structures for queue.

Problem in the function of my program code python

I tried to make a program to do the below things but apparently, the function doesn't work. I want my function to take two or more arguments and give me the average and median and the maximum number of those arguments.
example input:
calc([2, 20])
example output : (11.0, 11.0, 20)
def calc():
total = 0
calc = sorted(calc)
for x in range(len(calc)):
total += int(calc[x])
average = total / len(calc)
sorted(calc)
maximum = calc[len(calc) - 1]
if len(calc) % 2 != 0:
median = calc[(len(calc) // 2) + 1]
else:
median = (float(calc[(len(calc) // 2) - 1]) + float(calc[(len(calc) // 2)])) / 2
return (average, median, maximum)
There are some things I'm going to fix as I go since I can't help myself.
First, you main problem is arguments.
If you hand a function arguments
calc([2, 20])
It needs to accept arguments.
def calc(some_argument):
This will fix your main problem but another thing is you shouldn't have identical names for your variables.
calc is your function name so it should not also be the name of your list within your function.
# changed the arg name to lst
def calc(lst):
lst = sorted(lst)
# I'm going to just set these as variables since
# you're doing the calculations more than once
# it adds a lot of noise to your lines
size = len(lst)
mid = size // 2
total = 0
# in python we can just iterate over a list directly
# without indexing into it
# and python will unpack the variable into x
for x in lst:
total += int(x)
average = total / size
# we can get the last element in a list like so
maximum = lst[-1]
if size % 2 != 0:
# this was a logical error
# the actual element you want is mid
# since indexes start at 0
median = lst[mid]
else:
# here there is no reason to explicity cast to float
# since python division does that automatically
median = (lst[mid - 1] + lst[mid]) / 2
return (average, median, maximum)
print(calc([11.0, 11.0, 20]))
Output:
(14.0, 11.0, 20)
Because you are passing arguments into a function that doesn't accept any, you are getting an error. You could fix this just by making the first line of your program:
def calc(calc):
But it would be better to accept inputs into your function as something like "mylist". To do so you would just have to change your function like so:
def calc(mylist):
calc=sorted(mylist)

simpson integration on python

I am trying to integrate numerically using simpson integration rule for f(x) = 2x from 0 to 1, but keep getting a large error. The desired output is 1 but, the output from python is 1.334. Can someone help me find a solution to this problem?
thank you.
import numpy as np
def f(x):
return 2*x
def simpson(f,a,b,n):
x = np.linspace(a,b,n)
dx = (b-a)/n
for i in np.arange(1,n):
if i % 2 != 0:
y = 4*f(x)
elif i % 2 == 0:
y = 2*f(x)
return (f(a)+sum(y)+f(x)[-1])*dx/3
a = 0
b = 1
n = 1000
ans = simpson(f,a,b,n)
print(ans)
There is everything wrong. x is an array, everytime you call f(x), you are evaluating the function over the whole array. As n is even and n-1 odd, the y in the last loop is 4*f(x) and from its sum something is computed
Then n is the number of segments. The number of points is n+1. A correct implementation is
def simpson(f,a,b,n):
x = np.linspace(a,b,n+1)
y = f(x)
dx = x[1]-x[0]
return (y[0]+4*sum(y[1::2])+2*sum(y[2:-1:2])+y[-1])*dx/3
simpson(lambda x:2*x, 0, 1, 1000)
which then correctly returns 1.000. You might want to add a test if n is even, and increase it by one if that is not the case.
If you really want to keep the loop, you need to actually accumulate the sum inside the loop.
def simpson(f,a,b,n):
dx = (b-a)/n;
res = 0;
for i in range(1,n): res += f(a+i*dx)*(2 if i%2==0 else 4);
return (f(a)+f(b) + res)*dx/3;
simpson(lambda x:2*x, 0, 1, 1000)
But loops are generally slower than vectorized operations, so if you use numpy, use vectorized operations. Or just use directly scipy.integrate.simps.

Cubic Polynomial in Python

For my latest project in my coding class (python), we need to program and compute a cubic function. So something like 3x^3+2x^2+7x+1. I cannot figure out how to code in the different x powers. I know this is a very simple question, but I can't find what I am looking for on the internet and have searched. How would I write out this polynomial given the 3,2,7 & 1 values? I assume I need to use numpy but can only figure that out with a degree one polynomial.
powers can be represented with ** in python (there is also a more sophisticated pow) function:
def f(x):
return 3*x**3 + 2*x**2 + 7*x + 1
(in python ^ is the xor operator; if you use your expression python would not complain but just not calculate what you want)
if you need to be able to do symbolic math, i suggest you install the sympy package:
from sympy import symbols
def f(x):
return 3*x**3 + 2*x**2 + 7*x + 1
x = symbols('x')
print(f(x)) # 3*x**3 + 2*x**2 + 7*x + 1
print(f(x).subs(x, 5)) # 461
You can also create a custom function like this example:
def cubic(x, args):
args_len = len(args)
for k in args:
yield k * x ** (args_len-1)
args_len -=1
Demo:
user_input = [3, 2, 7, 1]
user_var_x = 1
somme = sum(cubic(user_var_x, user_input))
print(somme)
Output:
13

Round a number to a given set of values [duplicate]

This question already has answers here:
From list of integers, get number closest to a given value
(10 answers)
Closed 5 years ago.
Talking Python 3 here.
I'm looking to round a number to a given set of values which can vary
Assume value_set = [x, y, z] and for the sake of the example x, y, z = 1, 3.12, 4 I'm looking for a function that will round a given float to the closest number
custom_round(0) --> 1
custom_round(2.7) --> 3.12
Notice that it should be generic enough that value_set length will vary also
You can use the min function in order to find the minimum in your list when the key is the absolute value of x-n (x is each item in the list).
value_set = [1, 3.12, 4]
def return_closest(n):
return min(value_set, key=lambda x:abs(x-n))
number_to_check = 3
print (return_closest(number_to_check))
>>> 3.12
You can do this by first sorting the list, and then use binary search:
from bisect import bisect_left
class CustomRound:
def __init__(self,iterable):
self.data = sorted(iterable)
def __call__(self,x):
data = self.data
ndata = len(data)
idx = bisect_left(data,x)
if idx <= 0:
return data[0]
elif idx >= ndata:
return data[ndata-1]
x0 = data[idx-1]
x1 = data[idx]
if abs(x-x0) < abs(x-x1):
return x0
return x1
You can than construct your CustomRound like:
values = [1,3.12,4]
custom_round = CustomRound(values)
and simply call it:
>>> custom_round(0)
1
>>> custom_round(0.5)
1
>>> custom_round(1.5)
1
>>> custom_round(2.5)
3.12
>>> custom_round(3.12)
3.12
>>> custom_round(3.9)
4
>>> custom_round(4.1)
4
>>> custom_round(4.99)
4
This approach will work in O(log n) for rounding and O(n log n) for construction. So you will invest some additional time to construct the custom_round, but if you call it often, it will eventually pay off in rounding individual numbers.

Resources