Extending the shunting-yard algorithm to support the conditional ternary operator - ternary-operator

How to extend the shunting yard algorithm, that's originally meant for binary operators to support the conditional ternary operator ("a ? b : c") ?
I haven't seen an answer to this here and I have one, so I'm posting it.

The way I did it was to add three new operators:
"?" ternary-open-if
":" ternary-else
ternary-closed-if
Only the first two will be created directly when reading the initial expression.
However, only the third one will exists in the output (the RPN of the initial expression).
The ternary-open-if is put on the operators stack whenever a "?" is seen.
The ternary-else is never put on the stack. Rather, the stack is poped until a ternary-open-if is found, then the ternary-open-if is replaced with the ternary-closed-if (thus indicating that we're in the else part of the conditional operator).
All three operators have higher precedence than all other operators (higher meaning they're evaluated AFTER other operators).
The ternary-if operators have the same precedence and right associativity (like in C), meaning that a ternary-if will never cause a pop of another ternary-if.
The ternary-else has a precedence higher than the ternary-ifs, and its associativity is irrelevant (since it is never put on the stack). So, when encountering a ternary-open-if it will convert it to a closed one as mentioned before.
When encountering a ternary-closed-if it will pop it.
Examples (ternary-closed-if notated as "?:"):
"a ? b : c" -->
"a b c ?:"
"a ? b : x ? y : z" -->
"a b x y z ?: ?:"
"a ? x ? y : z : b" -->
"a x y z ?: b ?:"
This method is more hard to explain than to implement, and it does make a slight change to the algorithm, so if anyone has a simpler solution, please post it.

For anyone still searching here, the conditional ternary operator can also be implemented as an IF function with three arguments:
IF([boolean], [expr_if_true], [expr_if_false])
For example, to convert IF(5 > 4, 9, 8) to Reverse Polish Notation by extending the shunting yard algorithm, do:
+-------+---------------------------------------------------+--------------+----------------+
| Token | Action | RPN Output | Operator stack |
+-------+---------------------------------------------------+--------------+----------------+
| IF | Push token to stack | | IF |
| ( | Push token to stack | | IF ( |
| 5 | Add token to output | 5 | IF ( |
| > | Push token to stack | 5 | 15 ( > |
| 4 | Add token to output | 5 4 | IF ( > |
| , | Pop from stack onto output until left parenthesis | 5 4 > | IF ( |
| 9 | Add token to output | 5 4 > 9 | IF ( |
| , | Pop from stack onto output until left parenthesis | 5 4 > 9 | IF ( |
| 8 | Add token to output | 5 4 > 9 8 | IF ( |
| ) | Pop from stack onto output until left parenthesis | 5 4 > 9 8 | IF |
| end | Pop entire stack onto output | 5 4 > 9 8 IF | |
+-------+---------------------------------------------------+--------------+----------------+
The postfix is evaluated as:
+-------+------------------------------------------------------------------------------------------+-------+
| Token | Action | Stack |
+-------+------------------------------------------------------------------------------------------+-------+
| 5 | Push to stack | 5 |
| 4 | Push to stack | 4 |
| > | Pop from stack twice (5, 4), evaluate (5 > 4) and push onto stack | TRUE |
| 9 | Push onto stack | 9 |
| 8 | Push onto stack | 8 |
| IF | Pop from stack thrice (TRUE, 9, 8), evaluate (IF TRUE THEN 9 ELSE 8) and push onto stack | 9 |
+-------+------------------------------------------------------------------------------------------+-------+

Related

Python previous month with 2 digit

I want 04 as output in premonth . Can some one help on this? tried diff format and no luck.
enter code here
premonth = str(int(time.strftime('%m'))-1)
tried using
python date of the previous month
but due to strftime restriction I am not able to proceed.
Not the best way but this should work:
a = str(int(time.strftime('%m'))-1)
a = '0'+a if len(a)==1 else a
The following f-string will give you what you need, it also handles January correctly by using arithmetic manipulation to ensure 1 becomes 12:
f'{(int(time.strftime("%m")) + 10) % 12 + 1:02}'
Breaking that down, an f-string is a modern way to build strings from arbitrary expressions, in a way that keeps formatting and data together (unlike the old "string".format(item, item) and even older "string" % (item, item)).
Inside that f-string is a rather complex looking expression which is formatted with :02, meaning two places, zero-padded on left.
The expression is what correctly decrements your month with proper wrapping, as you can see from the following table:
+-------+-----+-----+----++-------+-----+-----+----+
| Value | +10 | %12 | +1 || Value | +10 | %12 | +1 |
+-------+-----+-----+----++-------+-----+-----+----+
| 1 | 11 | 11 | 12 || 7 | 17 | 5 | 6 |
| 2 | 12 | 0 | 1 || 8 | 18 | 6 | 7 |
| 3 | 13 | 1 | 2 || 9 | 19 | 7 | 8 |
| 4 | 14 | 2 | 3 || 10 | 20 | 8 | 9 |
| 5 | 15 | 3 | 4 || 11 | 21 | 9 | 10 |
| 6 | 16 | 4 | 5 || 12 | 22 | 10 | 11 |
+-------+-----+-----+----++-------+-----+-----+----+
and the following statement:
print(", ".join([f'{mm}->{(mm + 10) % 12 + 1:02}' for mm in range(1, 13)]))
which outputs:
1->12, 2->01, 3->02, 4->03, 5->04, 6->05, 7->06, 8->07, 9->08, 10->09, 11->10, 12->11

Exponential Regression: Translate mathematical notation to Excel syntax

I have a question on the Mathematics Stack Exchange site where I ask about generating an exponential regression equation.
One of the answers provides a mathematical solution to my problem. The solution is written in mathematical notation:
Unfortunately, I'm not a math wiz, and I'm having trouble translating the mathematical notation to Microsoft Excel syntax.
What would the math look like in Excel?
+--------------+---------------+
| X (AGE) | Y (CONDITION) |
+--------------+---------------+
| 0 | 20 |
| 1 | 20 |
| 2 | 20 |
| 3 | 20 |
| 4 | 20 |
| 5 | 20 |
| 6 | 18 |
| 7 | 18 |
| 8 | 18 |
| 9 | 18 |
| 10 | 16 |
| 11 | 16 |
| 12 | 14 |
| 13 | 14 |
| 14 | 12 |
| 15 | 12 |
| 16 | 10 |
| 17 | 8 |
| 18 | 6 |
| 19 | 4 |
| 20 | 2 |
+--------------+---------------+
I can verify that your formula for a translates as follows into Excel:
=SUMPRODUCT(E2:E22,F2:F22)/SUMSQ(E2:E22)
where my E2:E22 is just your x and my F2:F22 is ln(21-y). It gives the same answer, 0.147233112, as doing an exponential fit and forcing the intercept to be zero (which corresponds to setting b=1 in
y-21=b*exp(ax)
as you can verify by taking logs).
The formula quoted is the same as the one mentioned here under Simple linear regression without the intercept term (single regressor)
So this begs the question of whether b should, in fact, be equal to 1 and this is outside the scope of the question.

Does RandomForestsClassifier have a `decision_function`?

SVC in sklearn has a decision_function function, but why doesn't random forests? Secondly, how can I emulate the decision_function for a RandomForestsClassifier?
Yes, it has a decision function.
The function is coded directly into the Forest of Randomised Trees.
Simply put RandomForest learners use this trivial decision function strategy:
Rule a): The Forest ( the ensemble ) votes on result.
Rule b): Each Randomised Tree contains a series of decisions ( represented by Node(s).
Rule c): Each Node contains one or more simple conditions, based on which the decision making process moves farther from the root-Node towards the terminal-Leaf, according to the specified values of the Example FeatureVECTOR-input values.
Rule d): Terminal-Leaf contains a value, that a particular Randomised Tree presents to the ensemble voting ( Ad-a) ).
While this is not an exact RandomForestClassifier Tree-representation ( a Node can have more than one condition there - check the Scikit documentation on parameters ) but a fairly well illustrating the principles:
VOTE[12] = IN[0] < 6.85417 ? 1 : 2
| |
| 2:[IN[5]<183]
| |
| IN[5] < 183 ? 5 : 6
| | |
| | 6:[IN[10]<1.00118]
| | |
| | IN[10] < 1.00118 ? 13 : 14
| | | |
| | | 14:
| | | |
| | |
| | |
| |
| 5:[IN[6]<187]
| |
| IN[6] < 187 ? 11 : 12
| | |
1:
IN[10] < 1.00054 ? 3 : 4
| |
| 4:
| |
|
3:
voter[12]:
0:[inp0<6.85417] yes=1,no=2,missing=1
1:[inp10<1.00054] yes=3,no=4,missing=3
3:[inp21<0.974632] yes=7,no=8,missing=7
7:[inp22<1.01021] yes=15,no=16,missing=15
15:[inp15<0.994931] yes=31,no=32,missing=31
31:[inp12<0.999151] yes=63,no=64,missing=63
63:[inp23<0.957624] yes=111,no=112,missing=111
111:leaf=0.163636
112:leaf=-0.36
64:leaf=0.323077
32:[inp19<0.993949] yes=65,no=66,missing=65
65:[inp23<0.931146] yes=113,no=114,missing=113
113:leaf=-0
114:[inp23<0.972193] yes=161,no=162,missing=161
161:leaf=-0.421782
162:leaf=-0.133333
66:[inp2<61] yes=115,no=116,missing=115
115:leaf=0.381818
116:leaf=-0.388235
16:[inp17<0.985065] yes=33,no=34,missing=33
How to emulate decision function?
One can build another RandomForest-interpreter to traverse all the Trees and vote on resulting "ensemble compromise".
That will mimick the decision function ( there is no other there ) and would provide the same results as the RandomForest Trees were constructed to work this very way.

Flipped switch statements?

Consider you have 10 boolean variables of which only one can be true at a time, and each time any one is 'switched on', all others must be 'turned off'. One of the problems that immediately arises is;
How can you quickly test which variable is true without necessarily
having to linearly check all the variable states each time?
For this, I was thinking if it was possible to have something like:
switch(true)
{
case boolean1:
//do stuff
...
//other variables
}
This looks like a bad way of testing for 10 different states of an object, but I think there're cases where this kind of feature may prove useful and would like to know if there's any programming language that supports this kind of feature?
There isn't a language feature that offers this behavior. But as an alternative, you could use the Command Pattern, in conjunction with a Priority Queue. This assumes that you would be able to prioritize what checks should be done.
Traditionally, when you have such radio button boolean values you use an integer to represent them:
+------------+---------+--------------------+
| BINARY | DECIMAL | BINARY-LOGARITHMIC |
+------------+---------+--------------------+
| 0000000001 | 1 | 0 |
| 0000000010 | 2 | 1 |
| 0000000100 | 4 | 2 |
| 0000001000 | 8 | 3 |
| 0000010000 | 16 | 4 |
| 0000100000 | 32 | 5 |
| 0001000000 | 64 | 6 |
| 0010000000 | 128 | 7 |
| 0100000000 | 256 | 8 |
| 1000000000 | 512 | 9 |
+------------+---------+--------------------+
Let's call the variable holding this boolean value flag. We can quickly jump to some code based on the flag by indexing a random access array of functions:
var functions = [ function0
, function1
, function2
, function3
, function4
, function5
, function6
, function7
, function8
, function9
];
functions[flag](); // quick jump
However, you will have to pay for the function call overhead.

incrementing the index of a list element Haskell

With my function fun, I'd like to get an output such as this:
[ ("fluffy", "loves", "bunny"), ("monkey", "feeds", "fluffy"),
("bunny", "feeds", "monkey") ]
currently my output is this:
[("fluffy","eats","bunny"),("fluffy","eats","monkey"),("fluffy","feeds","bunny")]
my problem is that the first name is the same every time, and i want it to be different so tried to use indexing: (u1 !! n+1 /= u2)
However this gives me an error when i try to run it:
Couldn't match expected type ‘Char’ with actual type ‘[Char]’
In the second argument of ‘(/=)’, namely ‘u2’
In the expression: u1 !! n + 1 /= u2
my code:
names = ["fluffy", "bunny", "monkey"]
n= 0
fun = [ (u1, v, u2) | u1 <- names, v <- ["eats", "feeds", "loves"], u2 <- names, u1 /= u2]
funThree = take 3 (cycle fun)
Can anyone tell me how i can fix this? Thank you
You have a space of possible sentences that is 3 by 3 by 3, with 9 of the sentences crossed off by u1 /= u2.
eats feeds loves <- v
|fluffy|bunny |monkey| |fluffy|bunny |monkey| |fluffy|bunny |monkey| <- u2
-------|------|------|------| |------|------|------| |------|------|------|
| | | | | | | | | | | |
fluffy | X | | | | X | | | | X | | |
| | | | | | | | | | | |
-------|------|------|------| |------|------|------| |------|------|------|
| | | | | | | | | | | |
bunny | | X | | | | X | | | | X | |
| | | | | | | | | | | |
-------|------|------|------| |------|------|------| |------|------|------|
| | | | | | | | | | | |
monkey | | | X | | | | X | | | | X |
| | | | | | | | | | | |
----------------------------- ---------------------- ----------------------
^u1
You need to decide what order to visit these in. List comprehensions treat the first source list as the outermost list and the last one as the innermost list. They run across the last list completely before taking a single step in the second to last list, then run across the last list completely again before taking a second step in the second to last list. A step in the first list isn't made until all of the combinations from the later lists are explored. This is the same as reading the above table left to right and top to bottom like you would read a book.
You can change the order of the results from a list comprehension by changing the order of the source lists. There are 6 possible orders of the source lists.
If none of these give you what you want, you'll need to figure out how to describe the order you want to visit the points in sentence space, either to tell the compiler or tell someone else to ask for help. Try numbering the boxes (including the Xed out ones) with the numbers from 1 to 27 to specify the order and look for a pattern. There are over 6 quadrillion possible orders for just the 18 possible sentences.
It's easier if you produce a list of name pairs from your names list.
namePairs names = zip cnames (drop 1 cnames) -- modify number as desired
where cnames = cycle names
which produces the pairs (fluffy, bunny), (bunny, monkey), etc.
Then your function essentially becomes a zipWith where you add the action.
Or you could start out with a zip3 in the first place, combining names, actions and sublist of the cycled names.

Resources