How do I write a python script to pop up a notification within scheduled time? - python-3.9

Here's what I did. It's just about a reminder for a friend to be able to take his drugs on time.
import time
from win10toast import ToastNotifier
notify = ToastNotifier()
CurrentTime = 0
IconPath = "C:\\Users\\Hash\\Downloads\\Pill0.ico"
def alert(AlertHour, AlertMinute, AlertMessage):
while True:
CurrentTime = time.time()
CurrentHour = CurrentTime // 3600 % 24
CurrentMinu = CurrentTime // 60 % 60
if (CurrentHour == AlertHour and CurrentMinu == AlertMinute):
notify.show_toast("Drop Time!", AlertMessage, duration=120, icon_path=IconPath)
alert(21, 30, ">>>> E P I C I P R I N 5ML <<<<")
alert(17, 48, ">>>> seccE P I C I P R I N 5ML <<<<")
alert(9, 15, ">>>> P A T A N O L <<<<")
alert(21, 15, ">>>> P A T A N O L <<<<")
alert(9, 32, ">>>> E P I C I P R I N 5ML <<<<")
alert(15, 32, ">>>> E P I C I P R I N 5ML <<<<")
alert(21, 32, ">>>> E P I C I P R I N 5ML <<<<")
alert(3, 32, ">>>> E P I C I P R I N 5ML <<<<")
alert(9, 50, ">>>> E P I F E N A C <<<<")
alert(17, 50, ">>>> E P I F E N A C <<<<")
alert(1, 50, ">>>> E P I F E N A C <<<<")
alert(22, 00, ">>>> E P I C I P R I N 5G <<<<")
But it only runs the first alert method ignoring the rest even if their conditions are met.
Right now I'm stranded.
Any help please?
Thank you.

Well, once you run the first function, it gets into an infinite loop, therefore the python interpreter never gets to run the other calls. What you want to look into is threading. In a nutshell, threading allows you to run multiple processes simultaneously. Look into it
here

Related

ascending order check recursively

What I try to do is to check a given array is ordered in an ascending manner by divide-and-conquer approach.
I wonder what the logic behind the additional return case (a⌊n/2⌋−1 ≤ a⌊n/2⌋) is to reach to the final result. I attempted to solve the problem without looking at its solution but I couldn't figure out how the author discovers/devises a⌊n/2⌋−1 ≤ a⌊n/2⌋ case. It is really hard for me to unearth the case.
Actually, Why not a⌊n/2⌋ ≤ a⌊n/2⌋+1 instead? And the base case case, why I'm stackoverflowed when I remove equality from the base case, that is h<l?
with trial and error approach, I tried to write the following.
def co(a, l, h):
if h <= l:
return True
mid = l + ((h-l)//2)
cl = co(a, l, mid-1)
rl = co(a, mid+1, h)
return rl and cl and a[mid] < a[mid+1]
# how is a[mid] < a[mid+1] devised ??
# why not a[mid-1] < a[mid] ??
#c = [3, 5, 7, 9, 11,12]
c = [3, 5]
print(co(c, 0, len(c) - 1))
And the base case case, why I'm stackoverflowed when I remove equality
from the base case, that is h<l?
Assume c=[3, 5]. If you replace h<=l with h<l, then when you compute co(a, 1, 1), then mid = 1+0 ... then rl = co (a, 1+1, 1) and a[2] gives you stackoverflow.
How is a[mid] <= a[mid+1] devised ??
You need to compare the most-right element of subproblem1 with the most-left element of subproblem2. The order of these two elements are not taken into account in subproblem1 and subproblem2.
Be careful with Python indexing. 1) When you split the list into a[l:mid-1] and a[mid+1,h], you leave out a[mid-1] and a[mid]. 2) When you write co(c, 0, len(c) - 1) you leave out the last element of c (see Comment4).
There are some mistakes in your code, see my comments.
def co(a, l, h):
if h <= l:
return True
mid = l + ((h-l)//2)
cl = co(a, l, mid-1)
rl = co(a, mid+1, h)
return rl and cl and a[mid] < a[mid+1] ### Comment1: this misses checking a[mid-1] <= a[mid]
# how is a[mid] < a[mid+1] devised ?? ### Comment2: you should use <= rather than <
# why not a[mid-1] < a[mid] ??
#c = [12, 3, 5, 7, 9, 11,12] ### Comment3: your code returns True for this unordered list!
#c = [3, 5, 7, 9, 11,12]
c = [3, 5]
print(co(c, 0, len(c) - 1)) ### Comment4: len(c)-1 should be len(c) otherwise it's not the whole list
Below, I fixed the list indexing in your code. Note that the test becomes h <= l+1 because in Python the list a[mid:mid+1] contains one element.
def co(a, l, h):
if h <= l+1:
return True
mid = l + ((h-l)//2)
cl = co(a, l, mid)
rl = co(a, mid, h)
return rl and cl and a[mid-1] <= a[mid]

Ruby: Is using `srand` in initializer thread safe?

Is the follow code thread safe? I am worried srand may be a variable that is not thread safe. I have a rails app and going to be using Puma with 5-10 threads. I do not want to cause issues.
class Test
def initialize(seed)
srand seed # => 1, 222, 222, 111
end # => :initialize
def letter
%w[a b c d e f g h i j k l m n o p q r s t u v w x y z aa bb cc dd].sample # => "g", "u"
end # => :letter
def letter1
%w[a b c d e f g h i j k l m n o p q r s t u v w x y z aa bb cc dd].sample # => "g", "u"
end # => :letter1
end # => :letter1
Test.new(222).letter # => "g"
Test.new(222).letter1 # => "g"
Test.new(111).letter # => "u"
Test.new(111).letter1 # => "u"
Depends what you mean by "thread-safe". The program will still work, Ruby won't enter in an inconsistent state and no data will be lost. However, the default random number generator is global, shared between threads; it will be up to thread timing to see which thread receives which random number. If your intention is that all threads just get random numbers from a single RNG, your code is fine - though the results might not be repeatable, which probably defeats the purpose of srand.
If you want to make sure that each Test only generates numbers independently (and repeatably), you want to have each Test have its own random number generator:
class Test
def initialize(seed)
#random = Random.new(seed)
end
def letter
%w[a b c d e f g h i j k l m n o p q r s t u v w x y z aa bb cc dd].sample(random: #random)
end
end
t1 = Test.new(111)
t2 = Test.new(222)
3.times.map { t1.letter }
# => ["u", "m", "u"]
3.times.map { t2.letter }
# => ["u", "m", "u"]

Maximal partition

Given an integer n, and 2 real sequences {a_1, ..., a_n} and {b_1, ..., b_n}, with a_i, b_i > 0, for all i. For a given fixed m < n let {P_1, ..., P_m} be a partition of the set {1, ..., n} as in P_1 U ... U P_n = {1, ..., n}, with the P_i's pairwise disjoint (empty intersection). I wish to find a partition of size m that maximizes the expression
The number of partitions of the set is n choose m, prohibitively large to do by brute force. Is there an iterative or approximate solution that does better?
For insight into this problem the code block at the end solves via brute-force. For realistic size problems (n ~ 1e6, k ~ 20) it is unusable as is, but easily distrubuted.
Edit: Presorting a, b by the values of a^2/b always gives increasing partition indices:
a = rng.uniform(low=0.0, high=10.0, size=NUM_POINTS)
b = rng.uniform(low=0.0, high=10.0, size=NUM_POINTS)
ind = np.argsort(a/b)
(a,b) = (seq[ind] for seq in (a,b))
a sample run with
NUM_POINTS = 16
PARTITION_SIZE = 3
gives an optimal partition of
[[0, 1, 2, 3, 4, 5, 6, 7], [8, 9], [10, 11]]
which is monotonic in the indices. I think I can prove this. If so, the brute-force search could be improved to n choose k-1 time, still long, but a significant savings.
import numpy as np
import multiprocessing
import concurrent.futures
from functools import partial
from itertools import islice
rng = np.random.RandomState(55)
def knuth_partition(ns, m):
def visit(n, a):
ps = [[] for i in range(m)]
for j in range(n):
ps[a[j + 1]].append(ns[j])
return ps
def f(mu, nu, sigma, n, a):
if mu == 2:
yield visit(n, a)
else:
for v in f(mu - 1, nu - 1, (mu + sigma) % 2, n, a):
yield v
if nu == mu + 1:
a[mu] = mu - 1
yield visit(n, a)
while a[nu] > 0:
a[nu] = a[nu] - 1
yield visit(n, a)
elif nu > mu + 1:
if (mu + sigma) % 2 == 1:
a[nu - 1] = mu - 1
else:
a[mu] = mu - 1
if (a[nu] + sigma) % 2 == 1:
for v in b(mu, nu - 1, 0, n, a):
yield v
else:
for v in f(mu, nu - 1, 0, n, a):
yield v
while a[nu] > 0:
a[nu] = a[nu] - 1
if (a[nu] + sigma) % 2 == 1:
for v in b(mu, nu - 1, 0, n, a):
yield v
else:
for v in f(mu, nu - 1, 0, n, a):
yield v
def b(mu, nu, sigma, n, a):
if nu == mu + 1:
while a[nu] < mu - 1:
yield visit(n, a)
a[nu] = a[nu] + 1
yield visit(n, a)
a[mu] = 0
elif nu > mu + 1:
if (a[nu] + sigma) % 2 == 1:
for v in f(mu, nu - 1, 0, n, a):
yield v
else:
for v in b(mu, nu - 1, 0, n, a):
yield v
while a[nu] < mu - 1:
a[nu] = a[nu] + 1
if (a[nu] + sigma) % 2 == 1:
for v in f(mu, nu - 1, 0, n, a):
yield v
else:
for v in b(mu, nu - 1, 0, n, a):
yield v
if (mu + sigma) % 2 == 1:
a[nu - 1] = 0
else:
a[mu] = 0
if mu == 2:
yield visit(n, a)
else:
for v in b(mu - 1, nu - 1, (mu + sigma) % 2, n, a):
yield v
n = len(ns)
a = [0] * (n + 1)
for j in range(1, m + 1):
a[n - m + j] = j - 1
return f(m, n, 0, n, a)
def Bell_n_k(n, k):
''' Number of partitions of {1,...,n} into
k subsets, a restricted Bell number
'''
if (n == 0 or k == 0 or k > n):
return 0
if (k == 1 or k == n):
return 1
return (k * Bell_n_k(n - 1, k) +
Bell_n_k(n - 1, k - 1))
NUM_POINTS = 13
PARTITION_SIZE = 4
NUM_WORKERS = multiprocessing.cpu_count()
INT_LIST= range(0, NUM_POINTS)
REPORT_EACH = 10000
partitions = knuth_partition(INT_LIST, PARTITION_SIZE)
# Theoretical number of partitions, for accurate
# division of labor
num_partitions = Bell_n_k(NUM_POINTS, PARTITION_SIZE)
bin_ends = list(range(0,num_partitions,int(num_partitions/NUM_WORKERS)))
bin_ends = bin_ends + [num_partitions] if num_partitions/NUM_WORKERS else bin_ends
islice_on = list(zip(bin_ends[:-1], bin_ends[1:]))
# Have to consume it; can't split work on generator
partitions = list(partitions)
rng.shuffle(partitions)
slices = [list(islice(partitions, *ind)) for ind in islice_on]
return_values = [None] * len(slices)
futures = [None] * len(slices)
a = rng.uniform(low=0.0, high=10.0, size=NUM_POINTS)
b = rng.uniform(low=0.0, high=10.0, size=NUM_POINTS)
ind = np.argsort(a/b)
(a,b) = (seq[ind] for seq in (a,b))
def start_task():
print('Starting ', multiprocessing.current_process().name)
def _task(a, b, partitions, report_each=REPORT_EACH):
max_sum = float('-inf')
arg_max = -1
for ind,part in enumerate(partitions):
val = 0
for p in part:
val += sum(a[p])**2/sum(b[p])
if val > max_sum:
max_sum = val
arg_max = part
if not ind%report_each:
print('Percent complete: {:.{prec}f}'.
format(100*len(slices)*ind/num_partitions, prec=2))
return (max_sum, arg_max)
def reduce(return_values):
return max(return_values, key=lambda x: x[0])
task = partial(_task, a, b)
with concurrent.futures.ThreadPoolExecutor() as executor:
for ind,slice in enumerate(slices):
futures[ind] = executor.submit(task, slice)
return_values[ind] = futures[ind].result()
reduce(return_values)
I'm trying to simply re-phrase the problem with sample input, let me know if I missed anything.
A = [1, 3, 2, 1, 4]
B = [2, 1, 5, 3, 1]
n = length(A) = length(B) = 5
We have two lists with positive integers.
We need to find a set of indices S (a subset of N = {1,2,3,..n}), let's assume it's {2,3,5}. Now, we get a new set S' = N - S = {1, 4}
For S and S', (sum(A[S]))^2/(sum(B[S'])) needs to be maximized.
As you said, the approximation solution will work too. One of the heuristics we can use is we need to choose such S so that the values of A list is high and values of B list is
low.
As we take the square of the sum on the subset of A, let's just sort A and choose a sublist so that we get the max score.
import numpy as np
A = np.array([1, 2, 3, 4, 1, 2, 3])
B = np.array([3, 3, 1, 2, 1, 3, 1])
sorted_idx = sorted(range(len(A)), key=lambda k: A[k]) # also other sorting strategy can be used, A[k]/B[k]
A_p = A[sorted_idx]
B_p = B[sorted_idx]
max_s = 0
part_ans = -1
for i in range(len(A_p)):
cur_s = (sum(A_p[:i])**2)/sum(B_p[i:])
if cur_s >= max_s:
print(cur_s)
max_s = cur_s
part_ans = i
print(f'The partitions are: {sorted_idx[:i]} and {sorted_idx[i:]}')

Is this shuffle algorithm right?

The following is the shuffle algorithm I implemented in ruby:
def shuffle03!(arr)
len = arr.length
for i in 0..len-1
index1 = Random.rand(0..len-1)
index2 = Random.rand(0..len-1)
arr[index1], arr[index2] = arr[index2], arr[index1]
end
end
I tested this algorithm by reckoning:
class ShuffleTest
def initialize(seed)
len = seed.length
#count = {}
for i in 0..len-1
#count[seed[i]] = Array.new(len, 0)
end
end
def test(arr)
for i in 0...arr.length
#count[arr[i]][i] += 1
end
end
def show_count
return #count
end
end
def shuffle03!(arr)
len = arr.length
for i in 0..len-1
index1 = Random.rand(0..len-1)
index2 = Random.rand(0..len-1)
arr[index1], arr[index2] = arr[index2], arr[index1]
end
end
arr = ['a', 'b', 'c', 'd']
st = ShuffleTest.new(arr)
for x in 0..100_0000
shuffle03!(arr)
st.test(arr)
end
st.show_count.each do |k, v|
puts k
p v
end
the result was :
a
[250418, 249105, 249553, 250925]
b
[249372, 250373, 250785, 249471]
c
[250519, 250097, 249369, 250016]
d
[249692, 250426, 250294, 249589]
It semms to be correct. However, I donnot know how to prove it with mathematical statistics. So I'm not sure it is correct.
No, it is not right.
Imagine that you have a four-element list, [A,B,C,D]. Observe that:
There are 4! = 24 possible permutations. For this to be a correct shuffling algorithm, each of these permutations needs to be equally likely.
You are generating 4×2 = 8 random integers, each in the range 0–3, for a total of 48 = 65,536 possible sequences of random numbers. Each of these sequences is equally likely.
65,536 is not divisible by 24, so there is no way that your algorithm can map the 65,536 possible random-number sequences to permutations in a way that assigns an equal number of random-number sequences (and hence an equal probability) to each permutation.
To see this in a test, you can create a variant of your shuffle03! that, instead of using a random-generator, takes a list of eight indices, and uses those. (shuffle03! could then be implemented by generating eight random indices and then calling this variant as a helper-function.) Your test would then iterate over all 4096 possible sequences, and for each one, create a four-element list [A,B,C,D] and then call the variant method to see the resulting permutation. The test can keep count of how often each permutation appears, and use this to find which permutations appear more times than others. What you'll find is:
Permutation # of Occurrences
------------- ------------------
A B C D 4480
A B D C 3072
A C B D 3072
A C D B 2880
A D B C 2880
A D C B 3072
B A C D 3072
B A D C 2432
B C A D 2880
B C D A 2048
B D A C 2048
B D C A 2880
C A B D 2880
C A D B 2048
C B A D 3072
C B D A 2880
C D A B 2432
C D B A 2048
D A B C 2048
D A C B 2880
D B A C 2880
D B C A 3072
D C A B 2048
D C B A 2432
As you can see, elements tend to end up in the same order they started; for example, A B C D is the most common permutation. We can pull out one aspect of this by seeing, for each pair of elements, how often they end up in the same order vs. the opposite order. We find:
Elements Same Order Opposite Order
---------- ------------ ----------------
A and B 33792 31744
A and C 34816 30720
A and D 35840 29696
B and C 33792 31744
B and D 34816 30720
C and D 33792 31744
So some pairs are more likely than others to end up in the opposite order, but each pair is more likely to end up in the same order than to end up in the opposite order.
You can reduce the imbalance by performing more passes, but since no power of 8 is divisible by 24, it will never be possible to make all permutations equally likely.
By the way, if your actual goal here is a good shuffle algorithm (rather than just the learning experience of figuring one out for yourself), then you should use a Fisher–Yates shuffle.
Of course, since you're using Ruby, you can bypass the whole issue by just using Array.shuffle!, which performs the Fisher–Yates shuffle for you.
I would like to suggest a Ruby-way of achieving your objective.
Evidently, you cannot use Array#shuffle but (thankfully!) can use Kernel#rand. (I assume you can't use Array#sample either, as: arr.sample(arr.size) has the same effect as arr.shuffle.)
There are many ways to implement shuffle that are statistically valid (on the assumption that rand(n) produces truly random numbers between 0 and n-1, which of course is not possible, but that's a reasonable assumption). Here's one way:
class Array
def shuffle
arr = self.dup
map { arr.delete_at(rand(arr.size)) }
end
end
Let's try it with:
arr = [4,:a,5,6,'b',7,8]
arr.shuffle #=> [6, 8, "b", 5, 4, :a, 7]
arr.shuffle #=> [5, :a, 8, 4, "b", 7, 6]
arr.shuffle #=> [6, 8, 5, 7, "b", :a, 4]
arr.shuffle #=> [6, 4, 7, 8, 5, :a, "b"]
arr.shuffle #=> [:a, 4, "b", 5, 7, 8, 6]
arr.shuffle #=> ["b", 4, 7, 8, :a, 6, 5]

How to check if this algorithm may not terminate?

Let x denote a vector of p values (i.e. a data point in p dimensional space).
I have two sets: set A of n elements A = {xi, .., xn} and a set B of m elements B = {xj, .., xm}, where |A| > 1 and |B| > 1. Given an integer k > 0, let dist(x, k, A) a function which returns the mean Euclidean distance from x to its k nearest points in A; and dist(x, k, B) the mean Euclidean distance from x to its k nearest points in B.
I have the following algorithm:
Repeat
{
A' = { x in A, such that dist(x, k, A) > dist(x, k, B) }
B' = { x in B, such that dist(x, k, A) < dist(x, k, B) }
A = { x in A such that x not in A' } U B'
B = { x in B such that x not in B' } U A'
}
Until CONDITION == True
Termination: CONDITION is True when no more elements move from A to B or from B to A (that is A' and B' becomes empty), or when |A| or |B| becomes less than or equals to 1.
1) Is it possible to prove that this algorithm terminates ?
2) And if so, is it also possible to have an upper bound for the number of iterations required to terminate ?
Note: the k nearest points to x in a set S, means: the k points (others than x) in S, having the smallest Euclidean distance to x.
It looks like this algorithm can loop forever, oscillating between two or more states. I determined this experimentally using the following Python program:
def mean(seq):
if len(seq) == 0:
raise IndexError("didn't expect empty sequence for mean")
return sum(seq) / float(len(seq))
def dist(a,b):
return abs(a-b)
def mean_dist(x, k, a):
neighbors = {p for p in a if p != x}
neighbors = sorted(neighbors, key=lambda p: dist(p,x))
return mean([dist(x, p) for p in neighbors[:k]])
def frob(a,b,k, verbose = False):
def show(msg):
if verbose:
print msg
seen_pairs = set()
iterations = 0
while True:
iterations += 1
show("Iteration #{}".format(iterations))
a_star = {x for x in a if mean_dist(x, k, a) > mean_dist(x,k,b)}
b_star = {x for x in b if mean_dist(x, k, a) < mean_dist(x,k,b)}
a_temp = {x for x in a if x not in a_star} | b_star
b_temp = {x for x in b if x not in b_star} | a_star
show("\tA`: {}".format(list(a_star)))
show("\tB`: {}".format(list(b_star)))
show("\tA becomes {}".format(list(a_temp)))
show("\tB becomes {}".format(list(b_temp)))
if a_temp == a and b_temp == b:
return a, b
key = (tuple(sorted(a_temp)), tuple(sorted(b_temp)))
if key in seen_pairs:
raise Exception("Infinite loop for values {} and {}".format(list(a_temp),list(b_temp)))
seen_pairs.add(key)
a = a_temp
b = b_temp
import random
#creates a set of random integers, with the given number of elements.
def randSet(size):
a = set()
while len(a) < size:
a.add(random.randint(0, 10))
return a
size = 2
k = 1
#p equals one because I don't feel like doing vector math today
while True:
a = randSet(size)
b = randSet(size)
try:
frob(a,b, k)
except IndexError as e:
continue
except Exception as e:
print "infinite loop detected for initial inputs {} and {}".format(list(a), list(b))
#run the algorithm again, but showing our work this time
try:
frob(a,b,k, True)
except:
pass
break
Result:
infinite loop detected for initial inputs [10, 4] and [1, 5]
Iteration #1
A`: [10, 4]
B`: [1, 5]
A becomes [1, 5]
B becomes [10, 4]
Iteration #2
A`: [1, 5]
B`: [10, 4]
A becomes [10, 4]
B becomes [1, 5]
Iteration #3
A`: [10, 4]
B`: [1, 5]
A becomes [1, 5]
B becomes [10, 4]
In this case, the loop never terminates because A and B continually switch entirely. While experimenting with larger set sizes, I found a case where only some elements switch:
infinite loop detected for initial inputs [8, 1, 0] and [9, 4, 5]
Iteration #1
A`: [8]
B`: [9]
A becomes [0, 1, 9]
B becomes [8, 4, 5]
Iteration #2
A`: [9]
B`: [8]
A becomes [0, 1, 8]
B becomes [9, 4, 5]
Iteration #3
A`: [8]
B`: [9]
A becomes [0, 1, 9]
B becomes [8, 4, 5]
Here, elements 8 and 9 move back and forth while the other elements stay in place.

Resources