Python code to convert ffmpeg time duration value to seconds - python-3.x

I am seeking python 3.x code that can take a user-provided value in ffmpeg's time duration format and provide a float for the number of seconds represented by that duration. It would parse both formats described in the documentation and handle the s/ms/us prefix for the second format. The only thing I would not need is the optional negative. I mostly need this so I can provide the correct 'start_time' (seconds) for the fade and afade filters.
Please note, I am not asking how to get the duration of an input file. These are string values provided by the user.

I came up with the following code. It's not perfect, as it would probably accept some strings that ffmpeg would not, but it should be close enough for my immediate needs.
def duration_to_seconds(duration):
"""
Converts an ffmpeg duration string into a decimal representing the number of seconds
represented by the duration string; None if the string is not parsable.
"""
pattern = r'^((((?P<hms_grp1>\d*):)?((?P<hms_grp2>\d*):)?((?P<hms_secs>\d+([.]\d*)?)))|' \
'((?P<smu_value>\d+([.]\d*)?)(?P<smu_units>s|ms|us)))$'
match = re.match(pattern, duration)
if match:
groups = match.groupdict()
if groups['hms_secs'] is not None:
value = float(groups['hms_secs'])
if groups['hms_grp2'] is not None:
value += int(groups['hms_grp1']) * 60 * 60 + int(groups['hms_grp2']) * 60
elif groups['hms_grp1'] is not None:
value += int(groups['hms_grp1']) * 60
else:
value = float(groups['smu_value'])
units = groups['smu_units']
if units == 'ms':
value /= 1000.0
elif units == 'us':
value /= 1000000.0
return value
else:
return None

Related

How do I write a python function to count consecutive zeros in a binary representation of a number?

Given a number N, the function should convert the number to binary form, count the number of consecutive zero (the binary gap), and return the maximum binary gap. For example, 9 = 1001, the binary gap of length 2. The number 529 = 1000010001, has 2 binary gaps with length 4 and 3. If the number has 2 or more binary gaps, the function should return the maximum binary gap i.e. 4 in the case of N = 529.
I tried this function:
def solution(N):
binaryN = bin(N)[2:]
n = len(binaryN)
binaryGap = []
for i in range(n):
if binaryN[i] == 0 and binaryN[i + 1] == 0:
m = len(binaryN)
else:
return 0
binaryGap = binaryGap.append(m)
return max(binaryGap)
The function returns 0 for all values of N which is incorrect. How do I debug/improve the code to produce the accurate result?
Check out the below code. It would solve your problem.
The code is self-explanatory, yet let me know in-case of any doubts.
The Code:
import sys
num = int(sys.argv[1])
# Function to get the binary gap.
def binaryGapFinder(num):
binnum = bin(num).replace("0b", "") # binnum is binary form of the given number.
i = 0
x = 0
x_list = []
while i <= len(binnum)-1:
if binnum[i] == "0":
x += 1
if i == len(binnum)-1: # This loop will also consider if binary form is ending with 0. for example: 12 -> 1100
x_list.append(x)
else:
x_list.append(x)
x = 0
i += 1
return f"The Number: {num}\nIt's Binary Form: {binnum}\nMaximum Consecutive 0's: {max(x_list)}"
print(binaryGapFinder(num))
The Output:
python3 /the/path/to/your/script/binarygap.py 529
The Number: 529
It's Binary Form: 1000010001
Maximum Consecutive 0's: 4
python3 /the/path/to/your/script/binarygap.py 12
The Number: 12
It's Binary Form: 1100
Maximum Consecutive 0's: 2
python3 /the/path/to/your/script/binarygap.py 512
The Number: 512
It's Binary Form: 1000000000
Maximum Consecutive 0's: 9
There's a few issues here worth mentioning to aid you. (Just a side note to start with is that, in Python, it's recommended/best practice to use all lower case for variable names, so I'll replace them in my examples below.)
The bin() built in function returns a string. So you should be checking for equality with "0" (or '0') instead of an integer. e.g.
if binaryN[i] == "0" and binaryN[i + 1] == "0":
With Python you don't need to bother with checking for lengths of strings (or any other iterables) to use in a for loop in scenarios like this. e.g. You can replace:
n = len(binaryN)
for i in range(n):
with the more "Pythonic" way:
for bit in binary_number:
You can then use the variable bit (call it whatever you want of course, bearing in mind that good variable names make code more readable) instead of binary_number[index]. In this case, with each iteration of the for loop, bit will be replaced with the next character in the binary_number string.
From there on in your code:
m = len(binaryN)
will always be the same value, which is the total length of the string binaryN. e.g. 4 for '1001'.) This is not what you intended.
The first statement in your else block of code return 0 will terminate your function immediately and return 0 and thus your binaryGap = binaryGap.append(m) code will never, ever execute as it's unreachable due to that preceding return stopping any further execution of code in that suite.
You've got the right idea(s) and heading towards the right track for a solution but I don't think your code, even when the issues above are corrected, will match all possible binary numbers you may encounter. So, another possible alternative (and yet roughly sticking with the solution I think that you had in mind yourself) would be something like this which I hope will help you:
def solution(n):
binary_no = bin(n)[2:]
binary_gaps = []
gap_counter = 0
for bit in binary_no:
if bit == "0":
gap_counter += 1
else:
# Encountered a 1 so add current count of 0's -- if any -- to list and reset gap_counter
if gap_counter > 0:
binary_gaps.append(gap_counter)
gap_counter = 0
else:
# A for else suite (block of code) is run when all iterables have been exhausted.
if gap_counter > 0:
binary_gaps.append(gap_counter)
if binary_gaps: # If there is at least one element in the list
if len(binary_gaps) > 1:
return max(binary_gaps)
else:
return binary_gaps[0]
else:
# The list is empty, so no gaps were found at all. i.e. Binary number was all 1's.
return 0
print(solution(529))

Python bitcoin miner not letting me define variable after mine

I have been trying to create a python bitcoin miner, that ACTUALLY puts the coins somewhere, so thats the first part of my quesiton, and the second part is how do I fix this error?
This is all of my code:
import hashlib
import time
max_nonce = 2 ** 32 # 4 billion
def proof_of_work(header, difficulty_bits):
# calculate the difficulty target
target = 2 ** (256-difficulty_bits)
for nonce in range(max_nonce):
hash_result = hashlib.sha256(str(header)+str(nonce)).hexdigest()
# check if this is a valid result, below the target
if int(hash_result, 16) < target:
print ("Success with nonce %d" % nonce)
print ("Hash is %s" % hash_result)
return (hash_result,nonce)
print ("Failed after %d (max_nonce) tries" % nonce)
return nonce
if __name__ == '__main__':
nonce = 0
hash_result = ''
# difficulty from 0 to 31 bits
for difficulty_bits in range(32):
difficulty = 2 ** difficulty_bits
print ("Difficulty: %ld (%d bits)" % (difficulty, difficulty_bits))
print ("Starting search...")
# checkpoint the current time
start_time = time.time()
# make a new block which includes the hash from the previous block
# we fake a block of transactions - just a string
new_block = 'test block with transactions' + hash_result
# find a valid nonce for the new block
(hash_result, nonce) = proof_of_work((new_block, difficulty_bits).hexdigest()
# checkpoint how long it took to find a result
end_time = time.time()
The line above this, The end_time seems to get an error, with no definition to what the error is. Please help.
Please note that I have tried a great deal of commenting out a bunch of things, changing code, and this is in python 3
I'm writing this as an answer because of the many issues.
First, hashllib requires byte strings. You would need
hash_result = hashlib.sha256((header+str(nonce)).encode('utf-8')).hexdigest()
Second, you're doing proof_of_work(...).hexdigest(), but that function isn't returning a hash object. You are already calling hexdigest. Your function either returns a 2-tuple, or a nonce. You want to remove the hexdigest call:
# find a valid nonce for the new block
(hash_result, nonce) = proof_of_work((new_block, difficulty_bits)
And, in the final line of proof_of_work change
return nonce
to
return (None, nonce)
Next, you are converting the nonce to decimal digits to tack it on to the block. That is completely wrong. The nonce needs to be a 4-byte value. Something like:
enonce = struct.pack('I', nonce)
hash_result = hashlib.sha256(header.encode('utf-8')+enonce).hexdigest()
Finally, this whole thing is silly. Have you timed that inner loop to see how long it takes? On my box, it takes about 500 microseconds per loop. To run that 4 billion times would require a month and a half. To repeat that for all 32 difficult values would make it take 4 years.

I am getting a "Time Limit Exceeded " error in the following code. How to fix that error

The following code is my view of checking whether the sum of a number and it's reverse is a palindrome or not.If the sum is a palindrome then sum will be displayed.Otherwise the process will be repeated until we get a palindrome. When it is set to execute, I am getting a time limit exceeded error.Where do I need to correct the code?
def pal(n1):
temp=n1
rev=0
while(temp>0):
rev=(rev*10)+(temp%10)
temp=temp/10
sum1=n1+rev
temp=sum1
rev=0
while(temp>0):
rev=(rev*10)+(temp%10)
temp=temp/10
if(rev==sum1):
print(sum1)
else:
pal(sum1)
n=int(input())
pal(n)
I expect the output of a number 453 to be 6666.
i.e.
453+354=807 (not a palindrome. So repeat the process)
807+708=1515
1515+5151=6666 (it is a palindrome)
Your problem is that you are checking for while temp > 0: but inside that loop you are using float division: temp=temp/10. So the condition will always hold. For example:
>>> 8/10
0.8
>>> 0.8/10
0.08
What you want is to change your divisions to int division:
>>> 8//10
0
Still you might consider working with strings which is much easier in that case:
def pal(n):
rev_n = str(n)[::-1]
sum_str = str(n + int(rev_n))
while sum_str != sum_str[::-1]:
# print(sum_str)
sum_rev = sum_str[::-1]
sum_str = str(int(sum_str) + int(sum_rev))
print(sum_str)
And with the commented print this gives:
>>> pal(453)
807
1515
6666
Here is one way of doing this using string manipulation, which goes a lot easier than trying to do this with numbers. It is also a more direct translation of what you describe afterwards. (I do not really see the link between your code and your description...)
def is_palindrome(text):
# : approach1, faster for large inputs
# mid_length = len(text) // 2
# offset = 0 if len(text) % 2 else 1
# return text[:mid_length] == text[:-mid_length - offset:-1]
# : approach2, faster for small inputs
return text == text[::-1]
def palindrome_sum(num):
while not is_palindrome(num):
num = str(int(num) + int(num[::-1]))
return num
num = input() # 453
palindrome = palindrome_sum(num)
print(palindrome)
# 6666

Unsupported operand types python3

So I keep getting the above error message, and I don't understand why. This is what I have so far:
#request user input for property value
def getPropertyValue():
value = 0
value = float(input('Please enter value of desired property: '))
#eliminate negative answers
if value < 0:
print('Invalid property value, please re-enter a positive value. ')
getPropertyValue()
#return valid answers
else:
return value
#calculate assessed value
def calc_assessed_value(value):
a_value = value * 0.60
return a_value
#calculate property tax, 72 cents of each 100 dollars
def calc_property_tax(a_value):
p_tax = a_value / 100 * 0.72
p_tax = round(p_tax, 2)
return p_tax
#display results with meaningful text
def print_message(value, a_value , p_tax):
print('Property Value: $' , value)
print('Assessed Property Value: $' , a_value)
print('Property Tax: $' , p_tax)
#run functions in order
value = getPropertyValue()
a_value = calc_assessed_value(value)
p_tax = calc_property_tax(a_value)
print_message(value , a_value , p_tax)
And when I run it with a positive number out of the gate, it works. If I continuously run negative numbers it cuts it off as intended, and loops them until they enter a non-negative number. However, when you enter a positive number after that, it give the error message. I've been at this a while and it's not making sense to me. I thought maybe entering a negative number was affecting what type of number it was trying to use, so I tried zeroing the total before inputting (which is why there is a value = 0), but it still doesn't allow it through.
If you want to do getPropertyValue recursive, you should return function instead of executing it only.
Add return statement here:
#eliminate negative answers
if value < 0:
print('Invalid property value, please re-enter a positive value. ')
return getPropertyValue()
In your getPropertyValue function, when the user enters a negative number, you recursively call getPropertyValue() again and yet you aren't returning its return value, so it returns None by default, causing the calc_assessed_value to do calculation with a None value later.
Simply change:
getPropertyValue()
to:
return getPropertyValue()

How to convert an improper fraction to a mixed number, using python

I have to write a program that converts an improper fraction to a mixed number. Prompt the user for the numerator and the denominator, then calculate and display the equivalent mixed number. numerator is 23 and denominator is 6.
This is what I have so far...
num = int(input('Type numerator'))
dem = int(input('Type denominator'))
I'm not exactly sure what the next step is...I know the answer is supposed to be The mixed number is 3 and 5/6.
Assuming that your inputs are always integer values, you can use the divide and mod operators to do this.
The following should work:
a = num // dem
b = num % dem
print 'The mixed number is {} and {}/{}'.format(a, b, dem)
Good question. Here's one solution using Fraction function. Fraction is nice because it reduces fractions. You use floor divide (//) to strip out the whole number and then feed the remaining fraction to Fraction:
From fractions import Fraction
num = int(input('Type numerator'))
dem = int(input('Type denominator'))
Print str(num // dem) + ' and ' + str(Fraction(num%dem,dem)) if num//dem != 0 else str(Fraction(num%dem,dem))
[Python 3.5] (https://docs.python.org/2/library/fractions.html#fractions.Fraction) Extended reading on Fraction. Because you feed it num and dem rather than a pure decimal, it is pretty fail-safe.
This also gets rid of response of '0 and ...' which was bothering me.
Without using fractions module, we have to find the greatest common divider (borrowing gcd function from fractions) reduce our initial fraction and then use brilliant solution from #Jenner Felton
def gcdm(num,dem):
while dem:
num, dem = dem, num%dem
return num
gcd = gcdm(num,dem)
num, dem = num/gcd, dem/gcd
Print "%d and %d/%d" % ((num//dem), (num%dem),dem) if num//dem !=0 else "%d/%d" % (num%dem,dem)
As the other answers point out, you can use the integer division and modulo operators to get the numbers you want.
Another aspect to coding this problem that will make things easier is creating a while loop along with a try, except block for the entry of the improper fraction so that you do not get exceptions.
It would look like this:
while True:
try:
num = int(input('Type numerator'))
break
except:
continue
Split this off into a separate function to make things a bit nicer:
def get_data(message, f = lambda data: data):
'''Prompts the user for data entry.
Function f is applied to data; any exception encountered
results in user being prompted again.
Entry is simply returned if no function is supplied.'''
message = str(message)
while True:
try:
num = f(input(message))
break
except:
continue
return num
num = get_data('Type numerator', int)
den = get_data('Type denominator', int)
Here's my one-liner for obtaining the mixed number:
'%s%s%s' % ('%s ' % (num//den) if num//den != 0 else '', '%s/' % (num%den) if num%den != 0 else '', '%s' % den if num%den != 0 else '')

Resources