How to use switch with multiple enum values? - haxe

I m trying this code:
enum SideType
{
Vex;
Cav;
Plano;
}
function drawLense(aLeftType:SideType){
switch (aLeftType)
{
case Cav:
leftCenter = -aRadius - d * 0.5;
case Vex:
leftCenter = -Math.cos(( -90 + offset) * Math.PI / 180) * aRadius-d*0.5;
case Plano:return ;
case Cav, Vex:
points1= drawCurve(1, -90 + offset + trim, 180 - offset * 2 - (trim * 2), leftCenter, aRadius);
_LB = points1[0];
_LA = points1[1];
}
}
But I get an error when compile:
characters 8-16 : This pattern is unused
So, it pointing at case Cav, Vex:
How can I check Cav or Vex in the case above?
EDIT
I found that if I removed case Cav & Case Vex, then case Cav, Vex will work, but this is not what I want, can't I repeat the pattern usage in an or experision?
like (case Cav||Vex)?
case (Cav || Vex) would result into:
src/com/optics/components/Lense.hx:343: characters 8-38 : Case expression must be a constant value or a pattern, not an arbitrary expression

There are only 3 choices for the value of aLeftType, either Vex, Cav, or Plano.
var aLeftType = Vex;
switch (aLeftType)
{
case Cav:
// If aLeftType is `Cav`, run this line.
case Vex:
// If aLeftType is `Vex`, run this line.
case Plano:
// If aLeftType is `Plano`, run this line.
case Cav, Vex:
// If aLeftType is `Vex` or `Plano`, run this line...
// But the first 2 cases already covered `Vex` and `Plano`,
// so it will never be reached.
}
So really, the code of the 4th case will never be run. It is similar to:
if (a == 1) {
trace("a is 1");
} else if (a == 1) {
trace("a is really 1"); // This can never be reached.
}
That means, you have to think again want do you really want to do.

Usually when you want to make the same thing in different situation, you make a function for that :)
function drawLense(aLeftType:SideType){
switch (aLeftType)
{
case Cav:
leftCenter = -aRadius - d * 0.5;
functionCalledIfCavOrVex();
case Vex:
leftCenter = -Math.cos(( -90 + offset) * Math.PI / 180) * aRadius-d*0.5;
functionCalledIfCavOrVex();
case Plano:return ;
}
}
function functionCalledIfCavOrVex(/*...*/){
points1= drawCurve(1, -90 + offset + trim, 180 - offset * 2 - (trim * 2), leftCenter, aRadius);
_LB = points1[0];
_LA = points1[1];
}

Short answer: no way currently, you can only match one enum option in one place(not counting guarded options). So, duplicate your code for each enum option and live a happy life(this code will be also easier to read) or use a seconds switch(which might be shorter and easier in some more complex cases).

try:
case Cav | Vex:
trace("cav or vex");
Hope it helps.

Related

Taking strnig as input for calculator program in Perl

I am new to Perl and I'm trying to create a simple calculator program, but the rules are different from normal maths. All operations have the same power and the math problem must be solved from left to right.
Here is an example:
123 - 10 + 4 * 10 = ((123 - 10) + 4) * 10 = 1170
8 * 7 / 3 + 2 = ((8 * 7) / 3) + 2 = 20.666
So in the first case the user needs to enter one string: 123 - 10 + 4 * 10.
How do i approach this task?
I'm sorry if it's too much of a general question, but i'm not sure how to even begin. Do i need a counter? Like - every second character of the string is an operator, while the two on the sides are digits.
I'm afraid I'm lazy so I'll parse with a regex and process as I parse.
#!/usr/bin/env perl
#use Data::Dumper;
use Params::Validate (':all');
use 5.01800;
use warnings;
my $string=q{123 - 10 + 4 * 10};
my $result;
sub fee {
my ($a)=validate_pos(#_,{ type=>SCALAR });
#warn Data::Dumper->Dump([\$a],[qw(*a)]),' ';
$result=$a;
};
sub fi {
my ($op,$b)=validate_pos(#_,{ type=>SCALAR},{ type=>SCALAR });
#warn Data::Dumper->Dump([\$op,\$b],[qw(*op *b)]),' ';
$result = $op eq '+' ? $result+$b :
$op eq '-' ? $result-$b :
$op eq '*' ? $result*$b :
$op eq '/' ? $result/$b :
undef;
#warn Data::Dumper->Dump([\$result],[qw(*result)]),' ';
};
$string=~ m{^(\d+)(?{ fee($1) })(?:(?: *([-+/*]) *)(\d+)(?{ fi($2,$3) }))*$};
say $result;
Note the use of (?{...}) 1
To be clear, you are not looking for a regular calculator. You are looking for a calculator that bends the rules of math.
What you want is to extract the operands and operators, then handle them 3 at the time, with the first one being the rolling "sum", the second an operator and the third an operand.
A simple way to handle it is to just eval the strings. But since eval is a dangerous operation, we need to de-taint the input. We do this with a regex match: /\d+|[+\-*\/]+/g. This matches either 1 or more + digits \d or |, 1 or more + of either +-*/. And we do this match as many times as we can /g.
use strict;
use warnings;
use feature 'say';
while (<>) { # while we get input
my ($main, #ops) = /\d+|[+\-*\/]+/g; # extract the ops
while (#ops) { # while the list is not empty
$main = calc($main, splice #ops, 0, 2); # take 2 items off the list and process
}
say $main; # print result
}
sub calc {
eval "#_"; # simply eval a string of 3 ops, e.g. eval("1 + 2")
}
You may wish to add some input checking, to count the args and make sure they are the correct number.
A more sensible solution is to use a calling table, using the operator as the key from a hash of subs designed to handle each math operation:
sub calc {
my %proc = (
"+" => sub { $_[0] + $_[1] },
"-" => sub { $_[0] - $_[1] },
"/" => sub { $_[0] / $_[1] },
"*" => sub { $_[0] * $_[1] }
);
return $proc{$_[1]}($_[0], $_[2]);
}
As long as the middle argument is an operator, this will perform the required operation without the need for eval. This will also allow you to add other math operations that you might want for the future.
Just to read raw input from the user you would simply read the STDIN file handle.
$input = <STDIN>;
This will give you a string, say "123 + 234 - 345" which will have a end of line marker. You can remove this safely with the chomp command.
After that you will want to parse your string to get your appropriate variables. You can brute force this with a stream scanner that looks at each character as you read it and processes it accordingly. For example:
#input = split //, $input;
for $ch (#input) {
if ($ch > 0 and $ch <= 9) {
$tVal = ($tVal * 10) + $ch;
} elsif ($ch eq " ") {
$newVal = $oldVal
} elsif ($ch eq "+") {
# Do addition stuff
}...
}
Another approach would be to split it into words so you can just deal with whole terms.
#input = split /\s+/, $input;
Instead of a stream of characters, as you process the array values will be 123, +, 234, -, and 345...
Hope this points you in the right direction...

Minimum add to make parentheses string consisting of '{', '}', '[', ']', '(', ')' valid

This problem is an addition to the familiar stack question(https://leetcode.com/problems/minimum-add-to-make-parentheses-valid/) where we have to return the minimum number of additions to make the parentheses string valid. But that question consists of only '(' and ')'. What will happen if we extend that question to other types of parentheses like '[', ']', '{', '}'. I just came across this in a discussion among my friends and need help on how to approach.
For example: [[[{{}]]){)}) -> [[[{{}}]]] (){()}()
in this case answer is 5 additions to make it valid.
I couldn't come up with a proper approach. 2 approaches I considered are:
Similar to normal question, we push the opening types '(', '{', '[' to the stack as we browse through the string and if we find closing type ')', '}', ']' we check the top of the stack, if they both compliment each other, we pop and continue else we increment the counter and continue without popping out. After traversing the string, we output the answer as sum of counter and stack's size. In this approach the above example will not work as that extra '{' will break the approach.
Another approach is similar to above ie. we push the opening type of parentheses and if we find a closing type and if the stack's top compliment it, we pop and continue with the string, else we will pop out till we get a matching string and for every pop we increment the counter. After traversing the string, the total value is sum of counter and stack's size. But that will not work for cases like {{{{]}}}} where the character ']' will pop out everything and it will increase the answer.
I was also thinking of combining these, more like a Dynamic Programming where we will take the maximum of either seeing the top most value or seeing till we get a match in the stack or if stack becomes empty. But I am not sure on whether these 2 are the only cases to consider.
Explanation
We will process our input string character by character and update certain information about brackets encountered so far. For each bracket type, create a stack that keeps positions of uncompensated opening brackets. Basically, it says how many closing brackets of the current type are needed to make the string valid at the time of checking.
For each bracket of the input, do one of the following:
If the bracket is an opening one (any type), just add its position to the corresponding stack.
Otherwise, it's a closing bracket. If there are no opening brackets in the stack, just increment the resulting sum - unbalanced closing bracket can be compensated right away.
Finally, it's a closing bracket and there are opening brackets in the stack of the current type. So, add the number of all unbalanced brackets of the other types that are located between the last opening bracket of the same type and the current bracket! Don't forget to remove the matching elements from the stacks.
At the end, add a remaining size of each stack to the resulting sum because there may still be unbalanced opening brackets of each type.
Code
I created a simple solution in C++, but it can be easily converted to any other language if needed:
#include <iostream>
#include <stack>
#include <unordered_map>
bool isOpeningBracket(char bracket) {
return bracket == '(' || bracket == '[' || bracket == '{';
}
int main() {
std::string line;
std::cin >> line;
std::unordered_map<char, char> closingToOpeningBracket = {
{')', '('},
{']', '['},
{'}', '{'}
};
std::unordered_map<char, std::unique_ptr<std::stack<uint64_t>>> bracketsMap;
bracketsMap['{'] = std::make_unique<std::stack<uint64_t>>();
bracketsMap['['] = std::make_unique<std::stack<uint64_t>>();
bracketsMap['('] = std::make_unique<std::stack<uint64_t>>();
uint64_t addOperations = 0;
for(auto i = 0; i < line.size(); i++) {
auto bracket = line[i];
bool isOpening = isOpeningBracket(bracket);
auto key = bracket;
if (!isOpening) {
key = closingToOpeningBracket[bracket];
}
auto &bracketStack = bracketsMap[key];
if (isOpening) {
bracketStack->push(i);
} else if (!bracketStack->empty()) {
auto openingBracketPosition = bracketStack->top();
bracketStack->pop();
for (auto & [key, value] : bracketsMap) {
while (!value->empty() && value->top() > openingBracketPosition) {
addOperations++;
value->pop();
}
}
} else {
addOperations++;
}
}
for (auto & [key, value] : bracketsMap) {
addOperations += value->size();
}
std::cout << addOperations << "\n";
return 0;
}
Time and Space Complexity
The time and space complexity of this solution is O(n).
Just Think Greedily, for every closing tag there must be an opening tag if it is not so then we have to add an opening bracket.
So we can find the minimum add by iterating over the string and keeping the count of opening brackets. So when we encounter an opening bracket we increase our count variable and when we encounter a closing bracket we decrease our count variable if we have some positive count otherwise if the count is zero it means that we have to add an opening bracket here. Below is the code for this greedy approach. Time Complexity O(n) and Space Complexity O(1).
int minAddToMakeValid(string s) {
int cnt1 = 0 , cnt2 = 0, cnt3 = 0, ans = 0;
for(char ch : s){
if(ch == '(')cnt1++;
else if(ch == ')'){
if(cnt1==0)ans++;
else cnt1--;
}
if(ch == '{')cnt2++;
else if(ch == '}'){
if(cnt2==0)ans++;
else cnt2--;
}
if(ch == '[')cnt3++;
else if(ch == ']'){
if(cnt3==0)ans++;
else cnt3--;
}
}
return ans + cnt1 + cnt2 + cnt3;
}
You can do this in O(n^3) time (for any number of bracket types) with dynamic programming. This is not a lower bound on the runtime, but it appears that a greedy approach doesn't work for this problem.
First, it's helpful to realize that the 'minimum additions to balance' is the same as the 'minimum deletions to balance' for any bracket string, since the deletion framework is easier to work with. To see why this is true, consider a minimum set of additions: for every bracket that is now matched but was unmatched before, we could have also deleted that bracket, and vice versa.
The idea is to compute all possible bracket pairs: create a list of all indices [i, j], 0 <= i < j < n, where s[i] and s[j] are an open and closed bracket pair of the same type. Then, we find the maximum number of intervals [i, j] we can have, such that any two intervals are either nested or disjoint. This is exactly the requirements to be balanced, and, if you're curious, means that we're looking for the maximum size trivially perfect subgraph of the intersection graph formed by our intervals.
There are O(n^2) intervals, so any modification of this approach has an O(n^2) lower bound. We sort these intervals (by start, then by end if tied), and use dynamic programming (DP) to find the maximum number of nested or disjoint intervals we can have.
Our DP equation has 3 parameters: left, right, and min_index. [left, right] is an inclusive range of indices of s we are allowed to use, and min_index is the smallest index (in our interval list) interval we are allowed to use. If we know the leftmost interval that we can feasibly use, say, [start, end], the answer will come from either using or not using this interval. If we don't use it, we get dp(left, right, min_index+1). If we do use the interval, we add the maximum number of intervals we can nest inside (start, end), plus the maximum number of intervals starting strictly after end. This is 1 + dp(start+1, end-1, min_index+1) + dp(end+1, right, min_index+1).
For a fuller definition:
dp(left, right, min_index) :=
maximum number of intervals from interval_list[min_index:]
that are contained in [left, right] and all pairwise nested or disjoint.
Also, let
first_index := max(smallest index of an interval starting at or after left,
min_index)
so that interval_list[first_index] = (first_start, first_end).
dp(left, right, min_index) = 0 if (left > right or first_index >= length(interval_list)),
max(dp(left, right, first_index+1),
1
+ dp(first_start+1, first_end-1, first_index+1)
+ dp(first_end+1, right, first_index+1))
otherwise.
Here's a Python implementation of the algorithm:
def balance_multi_string(s: str) -> int:
"""Given a multi-paren string s, return minimum deletions to balance
it. 'Balanced' means all parentheses are matched, and
all pairs from different types are either nested or disjoint
Runs in O(n^3) time.
"""
open_brackets = {'{', '[', '('}
closed_brackets = {'}', ']', ')'}
bracket_partners = {'{': '}', '[': ']', '(': ')',
'}': '{', ']': '[', ')': '('}
n = len(s)
bracket_type_to_open_locations = collections.defaultdict(list)
intervals = []
for i, x in enumerate(s):
if x in closed_brackets:
for j in bracket_type_to_open_locations[bracket_partners[x]]:
intervals.append((j, i))
else:
bracket_type_to_open_locations[x].append(i)
if len(intervals) == 0:
return n
intervals.sort()
num_intervals = len(intervals)
#functools.lru_cache(None)
def point_to_first_interval_strictly_after(point: int) -> int:
"""Given a point, return index of first interval starting
strictly after, or num_intervals if there is none."""
if point > intervals[-1][0]:
return num_intervals
if point < intervals[0][0]:
return 0
return bisect.bisect_right(intervals, (point, n + 2))
#functools.lru_cache(None)
def dp(left: int, right: int, min_index: int) -> int:
"""Given inclusive range [left,right], and minimum interval index,
return the maximum number of intervals we can add
within this range so that all added intervals
are either nested or disjoint."""
if left >= right or min_index >= num_intervals:
return 0
starting_idx = max(point_to_first_interval_strictly_after(left - 1), min_index)
if starting_idx == num_intervals or intervals[starting_idx][0] >= right:
return 0
first_start, first_end = intervals[starting_idx]
best_answer = dp(first_start, right, starting_idx + 1) # Without first interval
if first_end <= right: # If we include the first interval
best_answer = max(best_answer,
1
+ dp(first_start + 1, first_end - 1, starting_idx + 1)
+ dp(first_end + 1, right, starting_idx + 1))
return best_answer
return n - 2 * dp(0, n - 1, 0)
Examples:
( [ ( [ ) } ] --> 3
} ( } [ ) [ { } --> 4
} ( } } ) ] ) { --> 6
{ ) { ) { [ } } --> 4
) ] } { } [ ( { --> 6
] ) } } ( [ } { --> 8

Define 2 switchable implementations of the same functions in NodeJS / Express

I have a bunch of field to calculate, and I have 3 cases.
Fields are mostly the same, but there is some differences.
Also, calculation to obtain each field may depend on differents variable, so function may have different signature.
In other languages, I would define an interface, use constructors using interface instead of concrete class and use dependency injection.
In nodeJS, I'm a newbie, and I saw there is no such thing that interfaces.
To take a concrete example, I must calculate
I have 2 case:
case sup36 === true
fixedRouting = (CG + CC + CSF * subscribedPower) / 12
case sup36 === false
fixedRouting = (CG + CC) / 12 + subscribedPower * billedCSFCoef * numDayInPeriod / 100
Right now, I add a parameter:
getFixedRouting(isSup36, CG, CC, subscribedPower, billedCSFCoef, numDayInPeriod) {
if isSup{
return (CG + CC + CSF * subscribedPower) / 12
}else{
return (CG + CC) / 12 + subscribedPower * billedCSFCoef * numDayInPeriod / 100
}
},
Problem is I will have more than 2 cases, and I will have to code more cases in the future. This way of coding will also increase the complexity of my code.
How should I do to be able to have 2 switchable implementations of getFixedRouting(...) ?
You can either have different functions for the different cases like this:
function getFixedRoutingSup36(CG, CC, subscribedPower) {
return (CG + CC + CSF * subscribedPower) / 12;
}
function getFixedRoutingNonSup36(CG, CC, subscribedPower, billedCSFCoef, numDayInPeriod) {
return (CG + CC) / 12 + subscribedPower * billedCSFCoef * numDayInPeriod / 100;
}
This can be helpful if the parameters sent to each differ greatly (for example above the sup36 case does not need or use billedCSFCoef or numDayInPeriod).
If you like having one entry point for all of this you can still have the functions split above like that but have this one entry point that you tell people to use:
function getFixedRouting(dataType, CG, CC, subscribedPower, billedCSFCoef, numDayInPeriod) {
switch (dataType) {
case 1:
return getFixedRoutingSup36(CG, CC, subscribedPower);
case 2:
return getFixedRoutingNonSup36(CG, CC, subscribedPower, billedCSFCoef, numDayInPeriod);
case 3:
return someOtherFunction();
}
}
The drawback here is that if your variety of cases take a different set of parameters it can get ugly.
Another variant is to pass the parameters as a Javascript Object so the contents can vary:
function getFixedRouting(data) {
switch (data.type) {
case 1:
return getFixedRoutingSup36(data.CG, data.CC, data.subscribedPower);
case 2:
return getFixedRoutingNonSup36(data.CG, data.CC, data.subscribedPower, data.billedCSFCoef, data.numDayInPeriod);
case 3:
return someOtherFunction();
}
}

sed command to remove a string and everything after it in that line

The .cpp file in a directory contains this text:
/**
* Performs the standard binary search using two comparisons per level.
* Returns index where item is found or or the index where it chould
* be inserted if not found
*/
template <typename Comparable>
int binarySearch( const Comparable* a, int size, const Comparable & x )
{
int low = 0, high = size - 1; // Set the bounds for the search
while( low <= high )
{
// Examine the element at the midpoint
int mid = ( low + high ) / 2;
if( a[ mid ] < x )
low = mid + 1; // If x is in the array, it must be in the upper
else if( a[ mid ] > x )
high = mid - 1; // If x is in the array, it must be in the lower
else
return mid; // Found
}
// Return the position where x would be inserted to
// preserve the ordering within the array.
return low;
}
Using the unix sed command, how would I print the contents of the .cpp file above with all the inline comments strings deleted (which look like this: // ) and all the text after it in that row deleted? I put an example below of what I am looking for. All the // marks and everything after them on that row is gone in this desired output.
/**
* Performs the standard binary search using two comparisons per level.
* Returns index where item is found or or the index where it chould
* be inserted if not found
*/
template <typename Comparable>
int binarySearch( const Comparable* a, int size, const Comparable & x )
{
int low = 0, high = size - 1;
while( low <= high )
{
int mid = ( low + high ) / 2;
if( a[ mid ] < x )
low = mid + 1;
else if( a[ mid ] > x )
high = mid - 1;
else
return mid;
}
return low;
}
If you don't need to use sed, this can be done easily with grep:
cat file.cpp | grep -v \/\/
Explanation:
grep -v will print all lines that don't match the pattern, and the pattern \/\/ is just an escaped version of //
If you do need to use sed, this can still be done easily (it's just arguably not the right tool for the job, and quite a bit slower).
cat file.cpp | sed '/\/\//d'
This matches every line that starts with // and deletes it.
To remove every line that contains "//":
sed '/\/\//d' file.cpp
To remove "//" and all that follows it on the line:
sed 's|//.*||' file.cpp
To do both (i.e. remove the "//" and all that follows it on the line, and remove that whole line if nothing but whitespace came before it):
sed '/^ *\/\//d;s|//.*||' file.cpp

lpeg grammar to parse comma separated groups that may have internal groups

I need to parse comma separated groups(enclosed in brackets) that may have internal groups inside the groups. It should only separate the outside groups.
I have a function that does this:
function lpeg.commaSplit(arg)
local P,C,V,sep = lpeg.P, lpeg.C, lpeg.V, lpeg.P(",")
local p = P{
"S";
S = lpeg.T_WSpace * C(V"Element") * (lpeg.T_WSpace * sep * lpeg.T_WSpace * C(V"Element"))^0 * lpeg.T_WSpace,
Element = (V"Group")^0 * (1 - lpeg.T_Group - sep)^0 * (V"Group" * (1 - lpeg.T_Group - sep)^0)^0 * (1 - sep)^0,
Group = lpeg.T_LGroup * ((1 - lpeg.T_Group) + V"Group")^0 * lpeg.T_RGroup
}^-1
return lpeg.match(lpeg.Ct(p), arg)
end
But the problem is to remove the extra brackets that may enclose the group.
Here is a test string:
[[a,b,[c,d]],[e,[f,g]]]
should parse to
[a,b,[c,d] & [e,[f,g]]
Notice the internal groups are left alone. A simple removal of the extra brackets on the end does not work since you'll end up with a string like a,b,[c,d]],[e,[f,g].
Any ideas how to modify the lpeg grammar to allow for the outside groups?
As I am not expert in making grammars in LPeg, I found this exercise interesting to do...
I couldn't manage to use your grammar, so I went ahead and made my own, with smaller chunks easier to understand and where I could put the captures I needed.
I think I got a decent empirical result. It works on your test case, I don't know if groups can be more deeply nested, etc. The post-processing of the capture is a bit ad hoc...
require"lpeg"
-- Guesswork...
lpeg.T_WSpace = lpeg.P" "^0
lpeg.T_LGroup = lpeg.P"["
lpeg.T_RGroup = lpeg.P"]"
lpeg.T_Group = lpeg.S"[]"
function lpeg.commaSplit(arg)
local P, C, Ct, V, sep = lpeg.P, lpeg.C, lpeg.Ct, lpeg.V, lpeg.P","
local grammar =
{
"S";
S = lpeg.T_WSpace * V"Group" * lpeg.T_WSpace,
Group = Ct(lpeg.T_LGroup * C(V"Units") * lpeg.T_RGroup),
Units = V"Unit" *
(lpeg.T_WSpace * sep * lpeg.T_WSpace * V"Unit")^0,
Unit = V"Element" + V"Group",
Element = (1 - sep - lpeg.T_Group)^1,
}
return lpeg.match(Ct(P(grammar)^-1), arg)
end
local test = "[[a,b,[c,d]],[e,[f,g]]]"
local res = lpeg.commaSplit(test)
print(dumpObject(res))
print(res[1], res[1][1], res[1][2])
local groups = res[1]
local finalResult = {}
for n, v in ipairs(groups) do
if type(v) == 'table' then
finalResult[#finalResult+1] = "[" .. v[1] .. "]"
end
end
print(dumpObject(finalResult))
dumpObject is just a table dump of my own. The output of this code is as follows:
local T =
{
{
"[a,b,[c,d]],[e,[f,g]]",
{
"a,b,[c,d]",
{
"c,d"
}
},
{
"e,[f,g]",
{
"f,g"
}
}
}
}
table: 0037ED48 [a,b,[c,d]],[e,[f,g]] table: 0037ED70
local T =
{
"[a,b,[c,d]]",
"[e,[f,g]]"
}
Personally, I wouldn't pollute the lpeg table with my stuff, but I kept your style here.
I hope this will be useful (or will be a starting point to make you to advance).

Resources