Dynamic Programming Question - What is the base case? - dynamic-programming

Been preparing of Coding Interviews. I have been trying to beef up my dynamic programming skills and came across Alvin's awesome channel and this great video about some of the approaches to take.
In one of the programming sections - The problem statement is "Can you construct the target string with the contents in an array" - he goes on to correctly use recursion as an approach. But I got stuck in his base case.
He indicates for example that this should return true:
canConstruct('StakeBoard', ['sta', 'te', 'bo', 'ard']
He goes on to settle the recursion base case as the following returning true by literally saying "Because to generate and empty string, you can generally take no-zero elements from the array!". This is the part I did not understand. What does non-zero elements of the array mean here to make this a base case?
canConstruct('', ['cat', dog'])

"Because to generate an empty string, you can generally take no-zero elements from the array!"
It should be something like
"Because to generate an empty string, you can generally take no or zero elements from the array!"
The next question states that
What does non-zero elements of the array mean here to make this a base case?
Actually, he meant
In case the target is empty, no matter what array of words are given, taking no or zero words will return the answer true.
We call a case base case when we have a definite answer for that case. And the case described above definitely looks like one thereby addressed as the base case.

Related

How can you dynamically format a string with a user-provided template and slice of parameters in Go?

I have user-provided format strings, and for each, I have a corresponding slice. For instance, I might have Test string {{1}}: {{2}} and ["number 1", "The Bit Afterwards"]. I want to generate Test string number 1: The Bit Afterwards from this.
The format of the user-provided strings is not fixed, and can be changed if need be. However, I cannot guarantee their sanity or safety; neither can I guarantee that any given character will not be used in the string, so any tags (like {} in my example) must be escapable. I also cannot guarantee that the same number of slice values will exist as tags in the template - for example, I might quite reasonably have Test string {{1}} and ["number 1", "another parameter", "yet another parameter"].
How can I efficiently format these strings, in accordance with the input given? They are for use as strings only, and don't require HTML, SQL or any other sort of escaping.
Things I've already considered:
fmt.Sprintf - two issues: 1) using it with user-provided templates is not ideal; 2) Sprintf does not play nicely with a number of parameters that doesn't match its format string, adding %!(EXTRA type=value) to the end.
The text/template library. This would work fine in theory, but I don't want to have to make users type out {{index .arr n}} for each and every one of their tags; in this case, I only ever need slice indexes.
The valyala/fasttemplate library. This is pretty much exactly what I'm looking for, but for the fact that it doesn't currently support escaping the delimiters it uses for its tags, at the time of writing. I've opened an issue for this, but I would have thought that there's already a solution to this problem somewhere - it doesn't feel like it's that unique.
Just writing my own parser for it. This would work... but, as above, I can't be the first person to have come across this!
Any advice or suggestions would be greatly appreciated.

Python recursive function to convert binary to decimal is working. I just don't understand how

I will start this off by saying that I have not done any schooling. All of my programming knowledge has come from 12 years of doing various projects in which I had to write a program of some sort in some language.
That said. I am helping my friend who is just getting into programming and who is taking a introductory python class. Her class is currently learning about recursive functions. Due to my lack of schooling this is the first time I have heard about them. So when she asked me to explain why the function she had worked I couldn't do it. I had to learn them myself.
I have been looking around at various posts about solving this same problem. I found one here at geeksforgeeks that is a function that does exactly what we need. With my elementary understanding of recursion this is the function that I would have thought would have been the right choice.
def bintodec(n):
if len(n) == 1:
bin_digit= int(n)
return bin_digit * 2**(len(n) - 1)
else:
bin_digit = int(n[0])
return bintodec(n[1:]) + bin_digit * 2**(len(n) - 1)
This is the function she came up with
def convertToDecimal(binNum):
if len(binNum) == 0:
return 0
else:
return convertToDecimal(binNum[:-1]) * 2 + int(binNum[-1])
When I print the function call it works.
print(convertToDecimal("11111111"))
# results in 255
print(convertToDecimal("00000111"))
# results in 7
I understand that sometimes there is a shorthand way to things. I can't see any shorthand methods mentions in the documentation that I have read.
The thing that really confuses me is how it takes that string and does math with it. I see the typecast for int, but the other side doesn't have it.
This is where everything falls apart and my brain starts melting. I am thinking there is a core mechanic of recursion that I am missing. Normally that is the case.
So along to figuring out why that works, I would love to know how this method would compare to say the method we found over at geeksforgeeks
What your friend has implemented is the typical implementation of Horner's method for polynomial evaluation. Here is the formula.
Now think of the binary number as a polynomial with a's equal to one or zero, and x equals to 2.
The thing that really confuses me is how it takes that string and does math with it. I see the typecast for int, but the other side doesn't have it.
The "other side" will take the value as int number which is result of latest recursive function call. in this case it will be 0.
Ok, so in words, what this program is doing is, on each invocation, taking the string and splitting it into 2 parts, lets call them a and b. a contains the entire string, apart from the final character, while b only contains the final digit.
Next, it takes a and calls the same function again, but this time with the shorter string, and then takes the result of this and doubles it. The doubling is done, as if you were to add an additional 0 to the end of a binary number, you would be doubling it.
Finally, it converts the value of b into an integer, either 1, or 0, and adds this to the previous result, which will be the decimal version of your binary string.
In other words, this function is only computing the result one character at a time, then it calls back to itself as a way of 'looping' to the next character.
It's important that there is an exit condition in a recursive function, to prevent infinite looping, in this case, when the string is empty, the program just returns 0, ending the loop.
Now on to the syntax. The only potentially confusing thing here I can see is python's array/slice syntax. Firstly, by trying to access the -1 index in an array, you are actually accessing the final element.
Also in that snippet is slice notation, which is the colon : in the array index. This is essentially used to select a subset of an array, in this case, all elements but the final one.
I honestly couldn’t make her function run as written. I got the below error
if len(binNum) == 0:
TypeError: object of type 'int' has no len()
I'm guessing however that under testing even working this would fail at some point, I’d like to see if you have it returning say, 221 (11011101) where the 1s and 0s are not consecutive and see if that works or fails.
Lastly, back to my error, I’m assuming the intention is to go out of the loop if it’s a zero. Even if zero wasn’t a null character, len(binNum) == 1 would still exit the loop as written. A try/catch block would be better

Python3, range(a,b) function behaviour and empty lists

I am a bit confused about the behavior of the range() function in a specific use case.
When I was testing some code I wrote using nested FOR loops, in some cases, the statements in certain loops never seemed to execute at all. I eventually realized that I was in some cases feeding a range() call with an input like:
range(i,2) # where i is 2, giving range(2,2)
...which threw no error, but apparently never executed the for loop contents. After some reading on Python3's FOR implementation, I then added "else:" statements to my loop:
for i in range(a,b): # where a=b, i.e. range(2,2)
[skipped code]
else:
[other code]
...and the else-case code executed fine, as I guess all possible iterators for the given range values were (already) exhausted, and the for-else case was triggered as it's designed to be when that happens.
From what I can see in the documentation for range(), I found: "A range object will be empty if r[0] does not meet the value constraint." ( https://docs.python.org/3/library/stdtypes.html#range ). I'm not quite sure what the "value constraint" is in this case, but if I'm understanding right, "range(a,b)" will return an empty list if a >= b.
My question is, is my understanding correct about when range() returns []? Also, are there any other kinds of input cases where range(a,b) returns [], or other obscure edge case behaviors I should be aware of? Thank you.
as you can see in this documentation, when you use range(a,b) you're setting its start and stop parameters.
what you need to know is that stop parameter is always excluded just like in lists slicing.
another remark is that you can set the step, so if you set a negative step you can actually use a >= b like in this case:
range(10,4,-1)
Also please notice that all parameters need to be integers.
I recommend you visit the documentation provided above it's quite helpful.
range(n) generates an iterator to progress the integer numbers starting with 0 and ending with (n-1).
With reference to your FOR loop, it was not executed because the ending number (i.e. n - 1 = 2 - 1 = 1) is less than the starting number, 2. Since the step argument is omitted in your FOR loop, it defaults to 1. The step can be both negative and positive, but not zero.
Syntax:
range(begin, end[, step])
Examples:
Both examples below will produce empty list.
list(range(0))
list(range(2,2))

Functional alternative to caching known "answers"

I think the best way to form this question is with an example...so, the actual reason I decided to ask about this is because of because of Problem 55 on Project Euler. In the problem, it asks to find the number of Lychrel numbers below 10,000. In an imperative language, I would get the list of numbers leading up to the final palindrome, and push those numbers to a list outside of my function. I would then check each incoming number to see if it was a part of that list, and if so, simply stop the test and conclude that the number is NOT a Lychrel number. I would do the same thing with non-lychrel numbers and their preceding numbers.
I've done this before and it has worked out nicely. However, it seems like a big hassle to actually implement this in Haskell without adding a bunch of extra arguments to my functions to hold the predecessors, and an absolute parent function to hold all of the numbers that I need to store.
I'm just wondering if there is some kind of tool that I'm missing here, or if there are any standards as a way to do this? I've read that Haskell kind of "naturally caches" (for example, if I wanted to define odd numbers as odds = filter odd [1..], I could refer to that whenever I wanted to, but it seems to get complicated when I need to dynamically add elements to a list.
Any suggestions on how to tackle this?
Thanks.
PS: I'm not asking for an answer to the Project Euler problem, I just want to get to know Haskell a bit better!
I believe you're looking for memoizing. There are a number of ways to do this. One fairly simple way is with the MemoTrie package. Alternatively if you know your input domain is a bounded set of numbers (e.g. [0,10000)) you can create an Array where the values are the results of your computation, and then you can just index into the array with your input. The Array approach won't work for you though because, even though your input numbers are below 10,000, subsequent iterations can trivially grow larger than 10,000.
That said, when I solved Problem 55 in Haskell, I didn't bother doing any memoization whatsoever. It turned out to just be fast enough to run (up to) 50 iterations on all input numbers. In fact, running that right now takes 0.2s to complete on my machine.

A reverse inference engine (find a random X for which foo(X) is true)

I am aware that languages like Prolog allow you to write things like the following:
mortal(X) :- man(X). % All men are mortal
man(socrates). % Socrates is a man
?- mortal(socrates). % Is Socrates mortal?
yes
What I want is something like this, but backwards. Suppose I have this:
mortal(X) :- man(X).
man(socrates).
man(plato).
man(aristotle).
I then ask it to give me a random X for which mortal(X) is true (thus it should give me one of 'socrates', 'plato', or 'aristotle' according to some random seed).
My questions are:
Does this sort of reverse inference have a name?
Are there any languages or libraries that support it?
EDIT
As somebody below pointed out, you can simply ask mortal(X) and it will return all X, from which you can simply pick a random one from the list. What if, however, that list would be very large, perhaps in the billions? Obviously in that case it wouldn't do to generate every possible result before picking one.
To see how this would be a practical problem, imagine a simple grammar that generated a random sentence of the form "adjective1 noun1 adverb transitive_verb adjective2 noun2". If the lists of adjectives, nouns, verbs, etc. are very large, you can see how the combinatorial explosion is a problem. If each list had 1000 words, you'd have 1000^6 possible sentences.
Instead of the deep-first search of Prolog, a randomized deep-first search strategy could be easyly implemented. All that is required is to randomize the program flow at choice points so that every time a disjunction is reached a random pole on the search tree (= prolog program) is selected instead of the first.
Though, note that this approach does not guarantees that all the solutions will be equally probable. To guarantee that, it is required to known in advance how many solutions will be generated by every pole to weight the randomization accordingly.
I've never used Prolog or anything similar, but judging by what Wikipedia says on the subject, asking
?- mortal(X).
should list everything for which mortal is true. After that, just pick one of the results.
So to answer your questions,
I'd go with "a query with a variable in it"
From what I can tell, Prolog itself should support it quite fine.
I dont think that you can calculate the nth solution directly but you can calculate the n first solutions (n randomly picked) and pick the last. Of course this would be problematic if n=10^(big_number)...
You could also do something like
mortal(ID,X) :- man(ID,X).
man(X):- random(1,4,ID), man(ID,X).
man(1,socrates).
man(2,plato).
man(3,aristotle).
but the problem is that if not every man was mortal, for example if only 1 out of 1000000 was mortal you would have to search a lot. It would be like searching for solutions for an equation by trying random numbers till you find one.
You could develop some sort of heuristic to find a solution close to the number but that may affect (negatively) the randomness.
I suspect that there is no way to do it more efficiently: you either have to calculate the set of solutions and pick one or pick one member of the superset of all solutions till you find one solution. But don't take my word for it xd

Resources