How to get multiples of 100 rounded to the nearest thousand - python

I'm learning Python and I'm trying to come up with a for loop (or any other method) that can return multiples of 100 but rounded to the nearest thousand, here's what I have right now:
huneds = [h * 100 for h in range(1,50)]
for r in huneds:
if r % 3 == float:
print(r)
else:
break

The built-in round() function will accept a negative number that you can use to round to thousands:
for r in huneds:
print(round(r, -3))
Which prints:
0
0
0
0
0
1000
1000
1000
1000
1000
1000
1000
1000
1000
2000
...
4000
4000
5000
5000
5000
5000

You can see use
for n in range(0,2500,100):
print(n, ' -> ',1000 * round(n / 1000))

For any number m, m is a multiple of n if the remainder of n / m is 0. I.e. n % m == 0 or in your case; r % 100 == 0, as the modulus operator (%) returns the remainder of a division. Use:
for r in huneds:
if r % 100 == 0:
print(r)
But every number is already a multiple of 100, as you multiplied all of them by 100.
You may be after something like:
# Range uses (start, stop, step) params
# print(list(range(0, 200, 10))) --> [0, 10, 20, ... 170, 180, 190]
for r in range(0, 200, 10):
if r % 100 == 0 and r != 0:
print(r)
Outputs
100
But you would like to round to the nearest 1000. The round() function can do that.
for r in range(0, 2000, 10):
if r % 100 == 0 and r != 0:
print(f"{r} | {round(r, -3)}")
100 | 0
200 | 0
300 | 0
400 | 0
500 | 0
600 | 1000
700 | 1000
800 | 1000
...
The f string does the same as r + ' | ' + round(r, -3)
This shows the number that is a multiple of 100 which is r, and then it rounded to the nearest 1000
round()'s second argument is the amount of digits to round too, as we are going to the nearest 1000, we use -3 as you are going on the left side of the decimal
I suggest having a read of:
https://www.w3schools.com/python/ref_func_range.asp
And I highly reccomend: this site (python principles) for learning python. Pro membership is currently free

Simply do this,
list(map(lambda x: round(x/1000) * 1000, huneds))
It'll return you a list of rounded values for all the items of the list huneds.

Related

Python numpy vectorization for heat dispersion

I'm supposed to write a code to represent heat dispersion using the finite difference formula given below.
๐‘ข(๐‘ก)๐‘–๐‘—=(๐‘ข(๐‘กโˆ’1)[๐‘–+1,๐‘—] + ๐‘ข(๐‘กโˆ’1) [๐‘–โˆ’1,๐‘—] +๐‘ข(๐‘กโˆ’1)[๐‘–,๐‘—+1] + ๐‘ข(๐‘กโˆ’1)[๐‘–,๐‘—โˆ’1])/4
The formula is supposed to produce the result only for a time step of 1. So, if an array like this was given:
100 100 100 100 100
100 0 0 0 100
100 0 0 0 100
100 0 0 0 100
100 100 100 100 100
The resulting array at time step 1 would be:
100 100 100 100 100
100 50 25 50 100
100 25 0 25 100
100 50 25 50 100
100 100 100 100 100
I know the representation using for loops would be as follows, where the array would have a minimum of 2 rows and 2 columns as a precondition:
h = np.copy(u)
for i in range(1,h.shape[0]-1):
for j in range (1, h.shape[1]-1):
num = u[i+1][j] + u[i-1][j] + u[i][j+1] + u[i][j-1]
h[i][j] = num/4
But I cannot figure out how to vectorize the code to represent heat dispersion. I am supposed to use numpy arrays and vectorization and am not allowed to use for loops of any kind, and I think I am supposed to rely on slicing, but I cannot figure out how to write it out and have started out with.
r, c = h.shape
if(c==2 or r==2):
return h
I'm sure that if the rows=2 or columns =2 then the array is returned as is, but correct me if Im wrong. Any help would be greatly appreciated. Thank you!
Try:
h[1:-1,1:-1] = (h[2:,1:-1] + h[:-2,1:-1] + h[1:-1,2:] + h[1:-1,:-2]) / 4
This solution uses slicing where:
1:-1 stays for indices 1,2, ..., LAST - 1
2: stays for 2, 3, ..., LAST
:-2 stays for 0, 1, ..., LAST - 2
During each iteration only the inner elements (indices 1..LAST-1) are updated

How to print content of an enumerated list?

I have created an enumerated list rank from a list total. But I am not able to print any specific value from the list rank.
I have tried to print the specific value from the rank list by traversing it using a for loop but getting the error
print(rank[i][0])
IndexError: list index out of range
n=int(input())
total=[]
rank=sorted(list(enumerate(total)), key=lambda x:x[1])
for i in range(n):
e,g,m,h=map(int, input().split())
total.append([-(e + g + m + h)])
#print(total)
#print(rank)
for i in range(n):
print(rank[i][0])
Input:
5
100 98 100 100
100 100 100 100
100 100 99 99
90 99 90 100
100 98 60 99
Expected Output:
(-398,0) if is rank[0][0] or so on.
You need to move rank creation after you fill total then it works fine.
n = int(input())
total = []
for i in range(n):
e, g, m, h = map(int, input().split())
total.append([-(e + g + m + h)])
rank = sorted(list(enumerate(total)), key=lambda x: x[1])
for i in range(n):
print(rank[i][0])
# print rank
for i in total:
print(i[0])

Combinations of Combinations

There are nearly 14 million combinations from a selection of 6 numbers from a range of 1-49. From the 14 million, I've cut the combinations down to 8.9 million by selecting only those where the sum of the 6 number combination must equate to between 120 and 180.
Example: 5, 10, 20, 27, 29, 40 = 131
Of the remaining 8.9 million combinations, I'm trying to remove all combinations that contain less than 2 and more than 4 odd numbers.
Basically, I want Python to show me how many combinations of those 8.9 million combinations have between 2-4 odd numbers in their combinations. All combinations of only 1 or less odd numbers and 5 or more odd numbers would be excluded from the results.
Example: 5, 10, 20, 27, 32, 40 = 2 odd numbers (it would be included in the amount of combinations).
Thank you!
import functools
_MIN_SUM = 120
_MAX_SUM = 180
_MIN_NUM = 1
_MAX_NUM = 49
_NUM_CHOICES = 6
#functools.lru_cache(maxsize=None)
def f(n, l, s):
assert(all(isinstance(v, int) and v >= 0 for v in (n, l, s)))
return 0 if s > _MAX_SUM else (
int(s >= _MIN_SUM) if n == 0 else (
sum(f(n-1, i+1, s+i) for i in range(l, _MAX_NUM+1))
)
)
result = f(_NUM_CHOICES, _MIN_NUM, 0)
print('Number of choices = {}'.format(result))
You can use the combinations() function from itertools and just brutally count the combinations that are eligible:
from itertools import combinations
eligible = 0
for combo in combinations(range(1,50),6):
total = sum(combo)
if total < 120 or total > 180:
continue
odds = sum(n&1 for n in combo)
if odds < 2 or odds > 4:
continue
eligible += 1
print(eligible) # 7221936
It only takes a few seconds (10-12)
You can do almost exactly the same as you are currently doing. Just add a parameter that counts how many odd numbers there are and increase it when you add an odd. Then you can adjust your tests accordingly:
import functools
_MIN_SUM = 120
_MAX_SUM = 180
_MIN_NUM = 1
_MAX_NUM = 49
_NUM_CHOICES = 6
_MIN_ODDS = 2
_MAX_ODDS = 4
#functools.lru_cache(maxsize=None)
def f(n, l, s = 0, odds = 0):
if s > _MAX_SUM or odds > _MAX_ODDS:
return 0
if n == 0 :
return int(s >= _MIN_SUM and odds >= _MIN_ODDS)
return sum(f(n-1, i+1, s+i, odds + i % 2) for i in range(l, _MAX_NUM+1))
result = f(_NUM_CHOICES, _MIN_NUM)
print('Number of choices = {}'.format(result))
Because it's memoized and prunes branches, this runs quickly:
150 ns ยฑ 13 ns per loop (mean ยฑ std. dev. of 7 runs, 10000000 loops each)
Running it with the more managable:
_MIN_SUM = 1
_MAX_SUM = 8
_MIN_NUM = 1
_MAX_NUM = 8
_NUM_CHOICES = 2
_MIN_ODDS = 2
_MAX_ODDS = 4
returns 4 which corresponds to the set:
(1, 3),
(1, 5),
(1, 7),
(3, 5)

get value from data that depend on other data

i am trying to get the l input which will be between 0,1. the l input will be for A column. and second input will be the 'mesafe' column so the result must be 23 which is for A and mesafe's zero column. I get some error.
import pandas as pd
import numpy as np
def var():
df = pd.read_csv('l_y.txt')
l=float(input("speed of the wind:"))
w=int(input("range:"))
for l in range(0, 1) and w in range(0, 100) :
print(df['A'].values[0])
l_y.txt=( mesafe A B C D E F
0 100 23 18 14 8 4 0
1 1000 210 170 110 60 40 30
2 5000 820 510 380 300 230 160
3 10000 1600 1200 820 560 400 250
4 20000 2800 2100 1600 1000 820 500
5 50000 5900 4600 3400 3200 1600 1100
6 100000 10000 8100 6100 3900 2800 2000 )
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
var()
File "C:\Users\user\AppData\Local\Programs\Python\Python36-32\ml.py", line
8, in var
for l in range(0, 1) and w in range(0, 100) :
TypeError: 'bool' object is not iterable
You have to follow the format of the language. In this case if you want to run a double loop with l and w:
for l in range(0, 1):
for w in range(0, 100) :
print(df['A'].values[0])
Note the indent, if you don't indent properly then the python codes won't work correctly.
Also your code here doesn't seem to accomplish anything except printing the same thing for 200 times. What are you trying to do?
Ok, I assume you want to get a certain value from your matrix, depending on two input values l and w, so that if l is between 0 and 1 column 'A' should be selected. (I further assume, that if l is between 1 nd 2 it's column 'B', 2 <= l < 3 -> 'c', and so on...)
The row is directly derived from w with the data in the mesafe-column: if w is between 0 and 100 -> row 0, between 100 and 1000 -> row 1 and so on...
Well, this can be achieved as follows:
l = .3 # let's say user types 0.3
There is some mapping between l and the letters:
l_mapping = [1, 5, 12, 20, 35, 50] # These are the thresholds between the columns A...F
l_index = np.searchsorted(l_mapping, l) # calculate the index of the column letter
col = df.columns[1:][l_index] # this translates l to the column names from A...F
col # look what col is when l was < 1
Out: 'A'
w = 42 # now the user Input for w is 42
row = np.searchsorted(df.mesafe.values, w) # this calculates the fractional index of w in df.mesafe
row
Out: 0
So with these two formulas you get column and row Information to index your desired result:
df[col].iloc[row]
Out: 23
Summing this all up in a function would look like this:
def get_l_y(l, w, df_ly):
l_mapping = [1, 5, 12, 20, 35, 50]
l_index = np.searchsorted(l_mapping, l)
col = df_ly.columns[1:][l_index]
row = np.searchsorted(df.mesafe.values, w)
print(l, w, col, row) # print Input and calculated row- and column- values for testing purpose, can be deleted/commented out if everything works as you want
return df[col].iloc[row]
This function expects l, w and the pandas-dataframe of your matrix as input Parameters and returns l_y.

How can I create three random integers which sum to a specific value? (Python) [duplicate]

This question already has answers here:
Generate random numbers summing to a predefined value
(7 answers)
Closed 5 years ago.
Let's say bob = 6
I want to create 3 random integers that have a sum of 106 (100 + whatever bob's original integer is. It could be 10, but in this case, it's 6).
I've got:
from random import *
bob = 6
bob1 = (randint(0,100))
bob2 = (randint(0,100))
bob3 = (randint(0,100))
print bob1
print bob2
print bob3
I can generate integers, but how can I make sure the sum of them = 100 + original integer? (106 total). If the sum doesn't = 106, then I want the script to keep going until it makes 106.
The general approach to generate numbers that add up to a certain number is like this:
import random
bob = 6
numbers = sorted(random.sample(range(100+bob), 2))
bob1 = numbers[0]
bob2 = numbers[1] - numbers[0]
bob3 = 100 + bob - numbers[1]
It selects two cut points between 0 and 100 + bob and assigns the numbers as illustrated:
This will also ensure all three numbers have the same distribution (simulated with 1m trials):
mean 34.700746 35.639730 35.659524
std 24.886456 24.862377 24.861724
As opposed to the numbers generated dependently:
mean 50.050665 27.863753 28.085582
std 29.141171 23.336316 23.552992
And their histograms:
Just calculate the third value:
from random import randint
bob = 6
bob1 = randint(0, 100)
bob2 = randint(0, min(100, 100 + bob - bob1))
bob3 = 100 + bob - bob1 - bob2
print bob1
print bob2
print bob3
bob1 = (randint(0,100))
bob2 = (randint(0,(100-bob1)))
bob3 = 100 - (bob1 + bob2)
Here is a general function that will always randomly generate 3 numbers in [0, n] that add to n; as the intermediate values are determined by "bob"'s initial value, we pass it this value and a target total number. The function returns a tuple of 3 numbers that together with bob-initial-value add up to the target:
import random
def three_numbers_to_n(bob, target):
n = target - bob
a = random.randrange(0, n+1)
b = random.randrange(a, n+1) - a
c = n - a - b
return a, b, c
for _ in range(5):
bob = 6
result = three_numbers_to_n(bob, 106)
print(bob, result, sum(result) + bob)
sample output:
6 (13, 3, 84) 106
6 (45, 49, 6) 106
6 (27, 2, 71) 106
6 (44, 18, 38) 106
6 (100, 0, 0) 106
If you wish, you could random.shuffle(a, b, c) before returning to remove the predictability that the first number is likely larger than the second likely larger than the 3rd.

Categories

Resources