At the moment I have a command which simply takes an argument and does some mathematical operation on it:
\newcommand{\gobblenext}[1]{do some math with #1 and display it}
Now, in order to upgrade my home-made library, I also need to take into account different cases, when argument #1 is not just simply a single number. What I would need is a command which would deal with passing something more complex consisting of a description of the case and more values.
For instance:
\newcommand{\gobblenext}[1]{
if #1 has a given format R{num1}{num2} -> apply R function on num1 and num2
if #1 has a given format S{num1}{num2} -> apply S function on num1 and num2
else (if #1 is simple number) just do the math as in original function.
}
The truth is, that I have no clue what is the best approach. The reason why I cannot simply define three different commands for each case is because \gobblenext is used by other commands, so that I would have to rewrite a big portion of the library. Do you have any ideas?
Related
When I use the function to check if element is present in list in python by using element in List. Which searching method is used in the background.
ex 2 in [2,3,4,5]
for example in the following code:
list=[2,3,4]
if 2 **in** list:
print(True)
else:
print(False)
Here's the code for the implemention in cpython:
static int
list_contains(PyListObject *a, PyObject *el)
{
Py_ssize_t i;
int cmp;
for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)
cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),
Py_EQ);
return cmp;
}
So as you can see, it's literally just walking through the list from front to back until the requisite element is found. The simplest possible algorithm for something like this. This checks out with the time complexity guide, which says that x in list has O(n) complexity.
Dicts and sets use a wholly different algorithm, because they're hash tables, a completely different data structure. Said different algorithm is almost always more efficient. If you're curious, you can also look at the source codes for sets and dicts respectively (the latter is much more complicated than the former, it looks like).
The in keyword can be used in different ways, but in this case, it's used to check if something contains something else. According to a documentation page about this, the in keyword calls __contains__, i.e.: x in y is the same as y.__contains__(x).
If SomeType.__contains__ is not defined by SomeType...
...the membership test first tries iteration via __iter__(), then the old sequence iteration protocol via __getitem__().
This would most likely be in linear time (O(n)). I say "most likely" because it depends on those implementations.
The in-built list type can have elements of different types and is not typically sorted, making binary search impossible (or at least illogical) and therefore, as stated by Green Cloak Guy, the CPython implementation performs the check linearly.
To answer the question in one term, it would be: "Linear Search."
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
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))
I am using string in if-else statement from input but not getting any result.
Two issues appear when I see that:
You use the is operator, which checks if two variables refer to the same object. x is y is only true if one was defined as equal to the other. Instead, you should use the == operator to check if two string are equal. Also, you type write, not writes, whereas your program is checking for writes. Entering the correct string and using the == operator instead of is should fix your problems.
This question already has an answer here:
Julia: invoke a function by a given string
(1 answer)
Closed 6 years ago.
I know that you can call functions using their name as follows
f = x -> println(x)
y = :f
eval(:($y("hi")))
but this is slow since it is using eval is it possible to do this in a different way? I know it's easy to go the other direction by just doing symbol(f).
What are you trying to accomplish? Needing to eval a symbol sounds like a solution in search of a problem. In particular, you can just pass around the original function, thereby avoiding issues with needing to track the scope of f (or, since f is just an ordinary variable in your example, the possibility that it would get reassigned), and with fewer characters to type:
f = x -> println(x)
g = f
g("hi")
I know it's easy to go the other direction by just doing symbol(f).
This is misleading, since it's not actually going to give you back f (that transform would be non-unique). But it instead gives you the string representation for the function (which might happen to be f, sometimes). It is simply equivalent to calling Symbol(string(f)), since the combination is common enough to be useful for other purposes.
Actually I have found use for the above scenario. I am working on a simple form compiler allowing for the convenient definition of variational problems as encountered in e.g. finite element analysis.
I am relying on the Julia parser to do an initial analysis of the syntax. The equations entered are valid Julia syntax, but will trigger errors on execution because some of the symbols or methods are not available at the point of the problem definition.
So what I do is roughly this:
I have a type that can hold my problem description:
type Cmd f; a; b; end
I have defined a macro so that I have access to the problem description AST. I travers this expression and create a Cmd object from its elements (this is not completely unlike the strategy behind the #mat macro in MATLAB.jl):
macro m(xp)
c = Cmd(xp.args[1], xp.args[3], xp.args[2])
:($c)
end
At a later step, I run the Cmd. Evaluation of the symbols happens only at this stage (yes, I need to be careful of the evaluation context):
function run(c::Cmd)
xp = Expr(:call, c.f, c.a, c.b)
eval(xp)
end
Usage example:
c = #m a^b
...
a, b = 2, 3
run(c)
which returns 9. So in short, the question is relevant in at least some meta-programming scenarios. In my case I have to admit I couldn't care less about performance as all of this is mere preprocessing and syntactic sugar.