How to propose a recurrence equation for a given DFA over a set of q states? - combinatorics

I am trying to solve question 2 on the following link: Check out Q.2.
That is I am interested in the number N(k) of binary strings of length k accepted by the following deterministic finite automaton (source: the URL).
For example N(2)=2, as only such strings are 01 and 10. In particular I am interested in a recurrence relation for N(k).

The recurrence is N(k) = 2*N(k-3) + N(k-2) for k>=3, with the boundary conditions N(0)=N(1)=0 and N(2)=2.
The reason is that given an acceptable string w (by acceptable I mean a string that the DFA accepts), you can either extend it with 11 to "remain" in the final state or add either 010 or 001 (both of length 3) to "remain" in the final state; the recurrence follows directly from these observations (think about it).
As an example, here's the first few strings of lengths k=2,3,...,7 accepted by the automaton:
For k=2 the solutions are 01, 10.
For k=3 there are no solutions.
For k=4 the solutions are 0111, 1011.
For k=5 the solutions are 01001, 01010, 10010, 10001.
For k=6 the solutions are 011111, 101111.
For k=7 the solutions are 0100111, 0101011, 1001011, 1000111, 0111001, 0111010, 1011001, 1011010.
We can see that the recurrence correctly counts the number of solutions:
N(3) = 2*N(0) + N(1) = 2*0 + 0 = 0.
N(4) = 2*N(1) + N(2) = 0+2 = 2.
N(5) = 2*N(2) + N(3) = 2*2 + 0 = 4.
N(6) = 2*N(3) + N(4) = 2*0 + 2 = 2.
N(7) = 2*N(4) + N(5) = 2*2 + 4 = 8.

Related

Am I doing this while loop correctly? [duplicate]

This question already has answers here:
How do I plot this logarithm without a "while True" loop?
(2 answers)
Closed 3 years ago.
I am trying to plot the logarithm of twelve tone equal temperament on a scale of hertz.
Is this while loop that breaks in the middle the best way to iterate all of the audible notes in the scale? Could I do the same thing more accurately, or with less code?
I do not want to use a for loop because then the range would be defined arbitrarily, not by the audible range.
When I try to use "note > highest or note < lowest" as the condition for the while loop, it doesn't work. I'm assuming that's because of the scope of where "note" is defined.
highest = 20000
lowest = 20
key = 440
TET = 12
equal_temper = [key]
i = 1
while True:
note = key * (2**(1/TET))**i
if note > highest or note < lowest:
break
equal_temper.append(note)
i += 1
i = 1
while True:
note = key * (2**(1/TET))**-i
if note > highest or note < lowest:
break
equal_temper.append(note)
i += 1
equal_tempered = sorted(equal_temper)
for i in range(len(equal_temper)):
print(equal_tempered[i])
The code returns a list of pitches (in hertz) that are very close to other tables I have looked at, but the higher numbers are further off. Setting a while loop to loop indefinitely seems to work, but I suspect there may be a more elegant way to write the loop.
As it turns out, you actually know the number of iterations! At least you can calculate it by doing some simple math. Then you can use a list comprehension to build your list:
import math
min_I = math.ceil(TET*math.log2(lowest/key))
max_I = math.floor(TET*math.log2(highest/key))
equal_tempered = [key * 2 ** (i / TET) for i in range(min_I, max_I + 1)]
You can use the piano key formula:
freq_n = freq_ref * sqrt(2, 12) ** (n − a)
The reference note is A4, 440 Hz and 49th key on the piano:
def piano_freq(key_no: int) -> float:
ref_tone = 440
ref_no = 49
freq_ratio = 2 ** (1/12)
return ref_tone * freq_ratio ** (key_no - ref_no)
Then you can do things like:
print(piano_freq(40)) # C4 = 261.6255653005985
print([piano_freq(no) for no in range(49, 49+12)]) # A4 .. G#5
Based on: https://en.wikipedia.org/wiki/Piano_key_frequencies

Create a Recursive Function as Well as a Closed Function Definition

The goal of this assignment is to take the recurrence relation given at the bottom, and then create a recursive function under recFunc(n), as well as a closed function definition underneath nonRecFunc(n). A closed function means our function should solely depend on n, and that its output should
match the recursive function's exactly. Then, find the value for n = 15 and n = 20, and use it as instructed below. You should probably need to use a characteristic equation to solve this problem.
What is the value for nonRecFunc(20) (divided by) nonRecFunc(15), rounded to the nearest integer.
Problem:
Solve the recurrence relation a_n = 12a_n-1 - 32a_n-2 with initial conditions a_0 = 1 and a_1 = 4.
I am confused as to how I should attack this problem and how I can use recursion to solve the issue.
def recFunc(n):
if n == 0:
return 1
elif n == 1:
return 2
else:
return recFunc(n - 1) + 6 * recFunc(n - 2)
def nonRecFunc(n):
return 4/5 * 3 ** n + 1/5 * (-2) ** n
for i in range(0,10):
print(recFunc(i))
print(nonRecFunc(i))
print()
As mentioned in a my comment above, I leave the recursive solution to you.
For the more mathematical question of the non-recursive solution consider this:
you have
x_n = a x_(n-1) + b x_(n-2)
This means that the change of x is more or less proportional to x as x_n and x_(n-1) will be of same order of magnitude. In other words we are looking for a function type giving
df(n)/dn ~ f(n)
This is something exponential. So the above assumption is
x_n = alpha t^n + beta s^n
(later when solving for s and t the motivation for this becomes clear) from the start values we get
alpha + beta = 1
and
alpha t + beta s = 2
The recursion provides
alpha t^n + beta s^n = a ( alpa t^(n-1) + beta s^(n-1) ) + b ( alpa t^(n-2) + beta s^(n-2) )
or
t^2 alpha t^(n-2) + s^2 beta s^(n-2) = a ( t alpa t^(n-2) + s beta s^(n-2) ) + b ( alpa t^(n-2) + beta s^(n-2) )
This equation holds for all n such that you can derive an equation for t and s.
Plugging in the results in the above equations gives you the non-recursive solution.
Try to reproduce it and then go for the actual task.
Cheers.

Change-making: Dynamic Programming

In a lecture earlier, we were told that using a greedy approach to solve a change making problem would not always work.
An example of this was given as follows:
We want to reach n = 14, and we have three coins of different values: d1 = 1,d2 = 7,d3 = 10.
Using the greedy approach this would lead us to do 10 + 1 + 1 + 1 + 1 (5 coins).
It was said the a dynamic problem approach would solve this accurately. I tried working it out but it came back to 5.
Assume F holds the number of coins needed to make an amount
F[14] = min {F[14 – 1] , F[14 – 7], F[14 – 10]} + 1
= F[14 – 10] + 1 = 4 + 1 = 5
This shows again that we need 5 coins, when this can clearly be done by using 2 coins (7 + 7).
What gives? Thanks.
You assumed that min {F[14 – 1] , F[14 – 7], F[14 – 10]}=F[14-10] when it is not the case. The minimum is actually F[14-7]=1 and hence the optimum is 2

Count the Number of Zero's between Range of integers

. Is there any Direct formula or System to find out the Numbers of Zero's between a Distinct Range ... Let two Integer M & N are given . if I have to find out the total number of zero's between this Range then what should I have to do ?
Let M = 1234567890 & N = 2345678901
And answer is : 987654304
Thanks in advance .
Reexamining the Problem
Here is a simple solution in Ruby, which inspects each integer from the interval [m,n], determines the string of its digits in the standard base 10 positional system, and counts the occuring 0 digits:
def brute_force(m, n)
if m > n
return 0
end
z = 0
m.upto(n) do |k|
z += k.to_s.count('0')
end
z
end
If you run it in an interactive Ruby shell you will get
irb> brute_force(1,100)
=> 11
which is fine. However using the interval bounds from the example in the question
m = 1234567890
n = 2345678901
you will recognize that this will take considerable time. On my machine it does need more than a couple of seconds, I had to cancel it so far.
So the real question is not only to come up with the correct zero counts but to do it faster than the above brute force solution.
Complexity: Running Time
The brute force solution needs to perform n-m+1 times searching the base 10 string for the number k, which is of length floor(log_10(k))+1, so it will not use more than
O(n (log(n)+1))
string digit accesses. The slow example had an n of roughly n = 10^9.
Reducing Complexity
Yiming Rong's answer is a first attempt to reduce the complexity of the problem.
If the function for calculating the number of zeros regarding the interval [m,n] is F(m,n), then it has the property
F(m,n) = F(1,n) - F(1,m-1)
so that it suffices to look for a most likely simpler function G with the property
G(n) = F(1,n).
Divide and Conquer
Coming up with a closed formula for the function G is not that easy. E.g.
the interval [1,1000] contains 192 zeros, but the interval [1001,2000] contains 300 zeros, because a case like k = 99 in the first interval would correspond to k = 1099 in the second interval, which yields another zero digit to count. k=7 would show up as 1007, yielding two more zeros.
What one can try is to express the solution for some problem instance in terms of solutions to simpler problem instances. This strategy is called divide and conquer in computer science. It works if at some complexity level it is possible to solve the problem instance and if one can deduce the solution of a more complex problem from the solutions of the simpler ones. This naturally leads to a recursive formulation.
E.g. we can formulate a solution for a restricted version of G, which is only working for some of the arguments. We call it g and it is defined for 9, 99, 999, etc. and will be equal to G for these arguments.
It can be calculated using this recursive function:
# zeros for 1..n, where n = (10^k)-1: 0, 9, 99, 999, ..
def g(n)
if n <= 9
return 0
end
n2 = (n - 9) / 10
return 10 * g(n2) + n2
end
Note that this function is much faster than the brute force method: To count the zeros in the interval [1, 10^9-1], which is comparable to the m from the question, it just needs 9 calls, its complexity is
O(log(n))
Again note that this g is not defined for arbitrary n, only for n = (10^k)-1.
Derivation of g
It starts with finding the recursive definition of the function h(n),
which counts zeros in the numbers from 1 to n = (10^k) - 1, if the decimal representation has leading zeros.
Example: h(999) counts the zero digits for the number representations:
001..009
010..099
100..999
The result would be h(999) = 297.
Using k = floor(log10(n+1)), k2 = k - 1, n2 = (10^k2) - 1 = (n-9)/10 the function h turns out to be
h(n) = 9 [k2 + h(n2)] + h(n2) + n2 = 9 k2 + 10 h(n2) + n2
with the initial condition h(0) = 0. It allows to formulate g as
g(n) = 9 [k2 + h(n2)] + g(n2)
with the intital condition g(0) = 0.
From these two definitions we can define the difference d between h and g as well, again as a recursive function:
d(n) = h(n) - g(n) = h(n2) - g(n2) + n2 = d(n2) + n2
with the initial condition d(0) = 0. Trying some examples leads to a geometric series, e.g. d(9999) = d(999) + 999 = d(99) + 99 + 999 = d(9) + 9 + 99 + 999 = 0 + 9 + 99 + 999 = (10^0)-1 + (10^1)-1 + (10^2)-1 + (10^3)-1 = (10^4 - 1)/(10-1) - 4. This gives the closed form
d(n) = n/9 - k
This allows us to express g in terms of g only:
g(n) = 9 [k2 + h(n2)] + g(n2) = 9 [k2 + g(n2) + d(n2)] + g(n2) = 9 k2 + 9 d(n2) + 10 g(n2) = 9 k2 + n2 - 9 k2 + 10 g(n2) = 10 g(n2) + n2
Derivation of G
Using the above definitions and naming the k digits of the representation q_k, q_k2, .., q2, q1 we first extend h into H:
H(q_k q_k2..q_1) = q_k [k2 + h(n2)] + r (k2-kr) + H(q_kr..q_1) + n2
with initial condition H(q_1) = 0 for q_1 <= 9.
Note the additional definition r = q_kr..q_1. To understand why it is needed look at the example H(901), where the next level call to H is H(1), which means that the digit string length shrinks from k=3 to kr=1, needing an additional padding with r (k2-kr) zero digits.
Using this, we can extend g to G as well:
G(q_k q_k2..q_1) = (q_k-1) [k2 + h(n2)] + k2 + r (k2-kr) + H(q_kr..q_1) + g(n2)
with initial condition G(q_1) = 0 for q_1 <= 9.
Note: It is likely that one can simplify the above expressions like in case of g above. E.g. trying to express G just in terms of G and not using h and H. I might do this in the future. The above is already enough to implement a fast zero calculation.
Test Result
recursive(1234567890, 2345678901) =
987654304
expected:
987654304
success
See the source and log for details.
Update: I changed the source and log according to the more detailed problem description from that contest (allowing 0 as input, handling invalid inputs, 2nd larger example).
You can use a standard approach to find m = [1, M-1] and n = [1, N], then [M, N] = n - m.
Standard approaches are easily available: Counting zeroes.

What can be a newbie explanation for a dynamic programming?

I am trying to learn the basics of Dynamic Programming (DP), and went through some the online resources i could get, such as...
What is dynamic programming?
Good examples, articles, books for understanding dynamic programming
Tutorial for Dynamic Programming
Dynamic Programming – From Novice to Advanced -- (I can't understand it properly (i.e. how to approach a problem using DP))
and till now i get to understand that
A dynamic problem is almost same that of
recursion with just a difference (which gives it the power it is know
for)
i.e. storing the value or solution we got and using it again to find next solution
For Example:
According to an explanation from codechef
Problem : Minimum Steps to One
Problem Statement: On a positive integer, you can perform any one of the following 3 steps.
Subtract 1 from it. ( n = n - 1 )
If its divisible by 2, divide by 2. ( if n % 2 == 0 , then n = n / 2 )
If its divisible by 3, divide by 3. ( if n % 3 == 0 , then n = n / 3 )
Now the question is, given a positive integer n, find the minimum number of steps that takes n to 1
eg:
For n = 1 , output: 0
For n = 4 , output: 2 ( 4 /2 = 2 /2 = 1 )
For n = 7 , output: 3 ( 7 -1 = 6 /3 = 2 /2 = 1 )
int memo[n+1]; // we will initialize the elements to -1 ( -1 means, not solved it yet )
Top-Down Approach for the above problem
int getMinSteps ( int n ) {
if ( n == 1 ) return 0;
if( memo[n] != -1 ) return memo[n];
int r = 1 + getMinSteps( n - 1 );
if( n%2 == 0 ) r = min( r , 1 + getMinSteps( n / 2 ) );
if( n%3 == 0 ) r = min( r , 1 + getMinSteps( n / 3 ) );
memo[n] = r ; // save the result. If you forget this step, then its same as plain recursion.
return r;
}
Am i correct in understanding the dp, or can anyone explain it in a better and easy way, so that i can learn it and can approach a problem with Dynamic programming.
The Fibonacci sequence example from wikipedia gives a good example.
Dynamic programming is an optimization technique that transforms a potentially exponential recursive solution into a polynomial time solution assuming the problem satisfies the principle of optimality. Basically meaning you can build an optimal solution from optimal sub-problems.
Another important characteristic of problems that are tractable with dynamic programming is that they are overlapping. If those problems are broken down into sub-problems that are repetitive, the same solution can be reused for solving those sub problems.
A problem with optimal substructure property and overlapping subproblems, dynamic programming is a potentially efficient way to solve it.
In the example you can see that recursive version of the Fibonacci numbers would grow in a tree like structure, suggesting an exponential explosion.
function fib(n)
if n <=1 return n
return fib(n − 1) + fib(n − 2)
So for fib(5) you get:
fib(5)
fib(4) + fib(3)
(fib(3) + fib(2)) + (fib(2) + fib(1))
And so on in a tree like fashion.
Dynamic programming lets us build the solution incrementally using optimal sub-problems in polynomial time. This is usually done with some form of record keeping such as a table.
Note that there are repeating instances of sub problems, i.e. calculating fib(2) one time is enough.
Also from Wikipedia, a dynamic programming solution
function fib(n)
if n = 0
return 0
else
var previousFib := 0, currentFib := 1
repeat n − 1 times // loop is skipped if n = 1
var newFib := previousFib + currentFib
previousFib := currentFib
currentFib := newFib
return currentFib
Here the solution is built up from previousFib and currentFib which are set initially. The newFib is calculated from the previous steps in this loop. previousFib and currentFib represent our record keeping for previous sub-problems.
The result is a polynomial time solution (O(n) in this case) for a problem whose recursive formulation would have been exponential (O(2^n) in this case).
There is wonderful answer How should I explain dynamic programming to a 4-year-old?
Just quoting same here :
Writes down "1+1+1+1+1+1+1+1 =" on a sheet of paper
"What's that equal to?"
counting "Eight!"
writes down another "1+" on the left
"What about that?"
quickly "Nine!"
"How'd you know it was nine so fast?"
"You just added one more"
"So you didn't need to recount because you remembered there were
eight! Dynamic Programming is just a fancy way to say 'remembering
stuff to save time later'"

Resources