I am starting to learn multiprocessing in python, but have arrived to a point where my code just hangs. It is simply computing 1 000 000 factorial, using multithreading.
import multiprocessing
def part(n):
ret = 1
n_max = n + 9999
while n <= n_max:
ret *= n
n += 1
print "Part "+ str(n-1) + " complete"
return ret
def buildlist(n_max):
n = 1
L = []
while n <= n_max:
L.append(n)
n += 10000
return L
final = 1
ne = 0
if __name__ == '__main__':
pool = multiprocessing.Pool()
results = [pool.apply_async(part, (x,)) for x in buildlist(1000000)]
for r in results:
x = r.get()
final *= x
ne+= 1
print ne
print final
I have included some print functions to try to diagnose where the code hangs, and it will print the string included in the part function 100 times, as expected. The "print ne" also works 100 times.
The problem is that final won't print, and the code doesn't complete.
How do I fix this problem?
Edit: Also, since this is being downvoted, could someone explain what I am doing wrong/why I am being downvoted?
The program works fine --- until the print final. Then it spends a very large amount of time trying to print this number, which is seriously huge...
Related
Starting to learn Python 3 on HackerRank when I run this code I get
this error:
Time limit exceeded
Your code did not execute within the time limits. Please optimize your code. For more information on execution time limits, refer to the environment page
Here is a link to the question on Hackerrank.
https://www.hackerrank.com/challenges/repeated-string/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=warmup
#!/bin/python3
import math
import os
import random
import re
import sys
#
# Complete the 'repeatedString' function below.
#
# The function is expected to return a LONG_INTEGER.
# The function accepts following parameters:
# 1. STRING s
# 2. LONG_INTEGER n
#
def repeatedString(s, n):
Write your code here
i = 0
aCount = 0
while i <= n:
if 'a' == s[i]:
aCount += 1
++i
else:
++i
print(aCount)
return aCount
if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
s = input()
n = int(input().strip())
result = repeatedString(s, n)
fptr.write(str(result) + '\n')
fptr.close()
Even though ++i is syntactically valid, it doesn't do what one would expect it to do, coming from a C-like language. In Python, ++i is just unary + applied to i twice (+(+i)), without changing it. The Python way of incrementing a variable is i+=1.
You're running the while loop from 0 to n, maximum value for n is 10^12. That while loop is running 10^12 times in worst case. That's why time exceeded. Try to optimize code.
Try this code
def repeatedString(s, n):
#Write your code here
aCount = 0
for i in range(len(s)):
if 'a' == s[i]:
aCount += 1
aCount*=(n//len(s))
x=n%len(s)
for i in range(x):
if 'a' == s[i]:
aCount += 1
return aCount
If you have a range of numbers from 1-49 with 6 numbers to choose from, there are nearly 14 million combinations. Using my current code (below), I have only 85,805 combinations remaining. I want to get all those 85,805 combinations to print into the Python shell showing every combination rather than the number of combinations possible as I'm currently seeing. Is that possible? Here's my code:
import functools
_MIN_SUM = 152
_MAX_SUM = 152
_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+2, 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))
Thank you!
Printing to the console is rather slow. You might want to print it to a file instead.
print("Hello World")
# vs
with open("file.txt", "w") as f:
print("Hello World", file=f)
Try using for loops and recursion together:
def combinations(base, numbers, placesRemaining):
out = []
for i in numbers:
if placesRemaining <= 1:
out.append(base*i)
else:
out.extend(combinations(base*i, numbers, placesRemaining-1))
return out
places = 6
numbers = range(1, 50)
answer = combinations(1, numbers, places)
That solution is not likely to run into the recursion limit, as the maximum recursion depth is equal to places. I did not run this on the full problem, but it performed well on smaller ones. Altering the starting base will multiply every number you calculate by that number, so I do not recommend it.
I wrote some code for a HackerRank problem (https://www.hackerrank.com/challenges/acm-icpc-team).
import time
from itertools import combinations
start_time = time.time()
n,m = raw_input().strip().split(' ') # n = no of people and m = no of topics
n,m = [int(n),int(m)]
topic = []
topic_i = 0
for topic_i in xrange(n):
topic_t = str(raw_input().strip())
topic.append(topic_t) # populate the topic[] list with the topics
counts = []
for list1, list2 in combinations(topic, 2):
if list1 != list2:
count = 0
for i in xrange(m):
if int(list1[i]) | int(list2[i]):
count += 1
counts.append(count)
print max(counts)
print counts.count(max(counts))
print time.time() - start_time
When I try to run the code, I get an execution time of 8.37576699257 seconds. But my program got over in a jiffy. I have read that the timeit() function, by default, runs the function passed to it a million times. Does something similar happen here?
You counted the time when the program waited for the user input too. You may want to move the first time.time() invocation below raw_input().
What is an iterative implementation of the ruler function?
This website asserts that "The ruler function can be generated non-recursively" but never shows an example.
A recursive implementation (from the same webpage) in Python looks like this:
def ruler(k):
for i in range(1, k+1):
yield i
for x in ruler(i-1): yield x
For each number n, ruler(n) is equal to 1 + (number of trailing 0s in binary n).
I think (this untested) it can be implented efficiently as
def ruler(n):
return (x ^ (x - 1)).bit_length()
because in binary the tailing digits look like
...mno1000 # x
...mno0111 # x - 1
...0001111 # x XOR (x - 1)
then you want the number of 1s, which .bit_length() gives you.
I may be missing something here, but based on the description of the ruler function...
def ruler(k):
pow = 1
while ((2*k) % (2**pow)) == 0:
pow += 1
return pow-1
for x in range(1, 10):
print ruler(x)
1
2
1
3
1
2
1
4
1
Dunno, maybe I'm not understanding the question.
A look-up table and bit-twiddling lets you solve this efficiently.
ruler = dict((1<<i, i+1) for i in xrange(63))
for i in xrange(1, 20):
print ruler[i & ~(i-1)],
Using what Hugh Bothwell said, you can do the following (for n > 0):
def ruler(n):
return len(bin(n).split('1')[-1]) + 1
I was trying this prob & use some old methods. Please check it once. I have not set it up totally. But apparently it's working. Few of unfinished broken codes are there.
Apology in advance.
#!/usr/bin/env python
import os
def ruler():
print("Initiating ruler function...")
num = int(input("Enter the value to Eval:: "))
expNumrange = 1234567890
if num%2 == 0:
for i in range(num):
print(expNumrange,end='----')
else:
rem = num%2
remLen = len(str(abs(rem)))
expNumrangelen = len(str(abs(expNumrange)))
finval = len(str(abs(expNumrange - remLen)))
setVal = expNumrange - finval
#rem2 = (str(expNumrange) - str(remLen))
for i in range(num):
print(expNumrange, end=(str(setVal) + '--'))
if __name__ == '__main__':
ruler()
Now, please check output.
For "8"
1234567890----1234567890----1234567890----1234567890----1234567890----1234567890----1234567890----1234567890----
For "5"
12345678901234567880--12345678901234567880--12345678901234567880--12345678901234567880--12345678901234567880--
I'm trying to create a program that runs a basic simulation.
Create a row of ten boxes, let a random number generator pick which direction he moves, and keep track of him.
The problem for the last while now is that the initial position is not being friendly.
I want to start in the middle - five - but no matter where I put that line, I get an error.
Here's the code:
import random
def right_movement():
p = p + 1
m = m + 1
times[p] = p
print times
def left_movement():
p = p - 1
m = m + 1
times[p] =+ 1
def main():
p = 5
times = [0] * 11
times[p] = 1
m = 0
print times
while p >= 0 and p <= 10:
x = random.randint(0, 1)
if x > 0:
right_movement()
else:
left_movement()
if p == 11:
print "Movement to the right into location 11."
print "Number of moves is " + m + "."
else:
print "Movement to the left into location 0."
print "Number of moves is " + m + "."
main()
No matter where I put p = 5, I get an error in reference to that. I'm running Python 2.7.
The problem is related to something called scope.
In a nutshell, what you did is you first created a variable called "p" within your main function. However, that does not mean that the other functions you create will be able to know that p exists.
I think this might be easier to understand if I give an example. In the first line of right_movement, you do p = p + 1. Since you're using p to add 1 to it, Python is going to look to see if you've assigned the variable p within right_movement. Since you didn't, it's going to sort of "move up" a layer, and see if you assigned the variable p within the file in general. Since you didn't assign p in either of those (you assigned inside main), Python will give up.
There are several solutions to this. The quick-and-dirty one would be to use something called "global" variables, and would look like this:
import random
p = 5
m = 0
times = [0] * 11
def right_movement():
global p
global m
global times
p = p + 1
m = m + 1
times[p] = p
print times
def left_movement():
global p
global m
global times
p = p - 1
m = m + 1
times[p] =+ 1
print times
def main():
times[p] = 1
print times
while p >= 0 and p <= 10:
x = random.randint(0, 1)
if x > 0:
right_movement()
else:
left_movement()
if p == 11:
print "Movement to the right into location 11."
print "Number of moves is " + str(m) + "."
else:
print "Movement to the left into location 0."
print "Number of moves is " + str(m) + "."
main()
You move the p, m, and times variables outside of the main function to the file, and make sure to use the global keyword to let Python know that you want to modify the variables inside the function, rather then temporarily creating a new one.
However, this isn't the cleanest solution -- using global variables is considered bad practice for a variety of reasons.
A better solution might be to keep track of the state within main, and rewrite your code to look like this:
import random
def right_movement(times, p):
p += 1
times[p] += 1
return p
def left_movement(times, p):
p -= 1
times[p] =+ 1
return p
def main():
p = 5
moves = 0
times = [0] * 11
times[p] = 1
print times
while 0 <= p <= 10:
moves += 1
x = random.randint(0, 1)
if x > 0:
p = right_movement(times, p)
else:
p = left_movement(times, p)
print times
if p == 11:
print "Movement to the right into location 11."
print "Number of moves is " + str(moves) + "."
else:
print "Movement to the left into location 0."
print "Number of moves is " + str(moves) + "."
main()
You are trying to share the same variables among several functions, without passing the values in to the functions as arguments. In order to do this, you need to use global variables.
Something like this:
import random
p = 5
times = [0] * 11
m = 0
def right_movement():
global p, times, m
p = p + 1
...
So, first you need to declare the variables outside of any function, then you need that global statement in each function that uses the variables.