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

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).

Related

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();
}
}

little problem on code for finding substring within string scala

I am currently working on a small code that should allow to tell if a given substring is within a string. I checked all the other similar questions but everybody is using predefined functions. I need to build it from scratch… could you please tell me what I did wrong?
def substring(s: String, t: String): Boolean ={
var i = 0 // position on substring
var j = 0 // position on string
var result = false
var isSim = true
var n = s.length // small string size
var m = t.length // BIG string size
// m must always be bigger than n + j
while (m>n+j && isSim == true){
// j grows with i
// stopping the loop at i<n
while (i<n && isSim == true){
// if characters are similar
if (s(i)==t(j)){
// add 1 to i. So j will increase by one as well
// this will run the loop looking for similarities. If not, exit the loop.
i += 1
j = i+1
// exciting the loop if no similarity is found
}
// answer given if no similarity is found
isSim = false
}
}
// printing the output
isSim
}
substring("moth", "ramathaaaaaaa")
The problem consists of two subproblems of same kind. You have to check whether
there exists a start index j such that
for all i <- 0 until n it holds that substring(i) == string(j + i)
Whenever you have to check whether some predicate holds for some / for all elements of a sequence, it can be quite handy if you can short-circuit and exit early by using the return keyword. Therefore, I'd suggest to eliminate all variables and while-loops, and use a nested method instead:
def substring(s: String, t: String): Boolean ={
val n = s.length // small string size
val m = t.length // BIG string size
def substringStartingAt(startIndex: Int): Boolean = {
for (i <- 0 until n) {
if (s(i) != t(startIndex + i)) return false
}
true
}
for (possibleStartIndex <- 0 to m - n) {
if (substringStartingAt(possibleStartIndex)) return true
}
false
}
The inner method checks whether all s(j + i) == t(i) for a given j. The outer for-loop checks whether there exists a suitable offset j.
Example:
for (
(sub, str) <- List(
("moth", "ramathaaaaaaa"),
("moth", "ramothaaaaaaa"),
("moth", "mothraaaaaaaa"),
("moth", "raaaaaaaamoth"),
("moth", "mmoth"),
("moth", "moth"),
)
) {
println(sub + " " + " " + str + ": " + substring(sub, str))
}
output:
moth ramathaaaaaaa: false
moth ramothaaaaaaa: true
moth mothraaaaaaaa: true
moth raaaaaaaamoth: true
moth mmoth: true
moth moth: true
If you were allowed to use built-in methods, you could of course also write
def substring(s: String, t: String): Boolean = {
val n = s.size
val m = t.size
(0 to m-n).exists(j => (0 until n).forall(i => s(i) == t(j + i)))
}
I offer the following slightly more idiomatic Scala code, not because I think it will perform better than Andrey's code--I don't--but simply because it uses recursion and is, perhaps, slightly easier to read:
/**
* Method to determine if "sub" is a substring of "string".
*
* #param sub the candidate substring.
* #param string the full string.
* #return true if "sub" is a substring of "string".
*/
def substring(sub: String, string: String): Boolean = {
val p = sub.toList
/**
* Tail-recursive method to determine if "p" is a subsequence of "s"
*
* #param s the super-sequence to be tested (part of the original "string").
* #return as follows:
* (1) "p" longer than "s" => false;
* (2) "p" elements match the corresponding "s" elements (starting at the start of "s") => true
* (3) recursively invoke substring on "p" and the tail of "s".
*/
#tailrec def substring(s: Seq[Char]): Boolean = p.length <= s.length && (
s.startsWith(p) || (
s match {
case Nil => false
case _ :: z => substring(z)
}
)
)
p.isEmpty || substring(string.toList)
}
If you object to using the built-in method startsWith then we could use something like:
(p zip s forall (t => t._1==t._2))
But we have to draw the line somewhere between creating everything from scratch and using built-in functions.

maximum volume of a box with perimeter and area given

Here's the link to the question..
http://www.codechef.com/problems/J7
I figured out that 2 edges have to be equal in order to give the maximum volume, and then used x, x, a*x as the lengths of the three edges to write the equations -
4*x + 4*x + 4*a*x = P (perimeter) and,
2*x^2 + 4*(a*x *x) = S (total area of the box)
so from the first equation I got x in terms of P and a, and then substituted it in the second equation and then got a quadratic equation with the unknown being a. and then I used the greater root of a and got x.
But this method seems to be giving the wrong answer! :|
I know that there isn't any logical error in this. Maybe some formatting error?
Here's the main code that I've written :
{
public static void main(String[] args)
{
TheBestBox box = new TheBestBox();
reader = box.new InputReader(System.in);
writer = box.new OutputWriter(System.out);
getAttributes();
writer.flush();
reader.close();
writer.close();
}
public static void getAttributes()
{
t = reader.nextInt(); // t is the number of test cases in the question
for (int i = 0; i < t; i++)
{
p = reader.nextInt(); // p is the perimeter given as input
area = reader.nextInt(); // area of the whole sheet, given as input
a = findRoot(); // the fraction by which the third side differs by the first two
side = (double) p / (4 * (2 + a)); // length of the first and the second sides (equal)
height = a * side; // assuming that the base is a square, the height has to be the side which differs from the other two
// writer.println(side * side * height);
// System.out.printf("%.2f\n", (side * side * height));
writer.println(String.format("%.2f", (side * side * height))); // just printing out the final answer
}
}
public static double findRoot() // the method to find the 2 possible fractions by which the height can differ from the other two sides and return the bigger one of them
{
double a32, b, discriminant, root1, root2;
a32 = 32 * area - p * p;
b = 32 * area - 2 * p * p;
discriminant = Math.sqrt(b * b - 4 * 8 * area * a32);
double temp;
temp = 2 * 8 * area;
root1 = (- b + discriminant) / temp;
root2 = (- b - discriminant) / temp;
return Math.max(root1, root2);
}
}
could someone please help me out with this? Thank You. :)
I also got stuck in this question and realized that can be done by making equation of V(volume) in terms of one side say 'l' and using differentiation to find maximum volume in terms of any one side 'l'.
So, equations are like this :-
P = 4(l+b+h);
S = 2(l*b+b*h+l*h);
V = l*b*h;
so equation in l for V = (l^3) - (l^2)P/4 + lS/2 -------equ(1)
After differentiation we get:-
d(V)/d(l) = 3*(l^2) - l*P/2 + S/2;
to get max V we need to equate above equation to zero(0) and get the value of l.
So, solutions to a quadratic equation will be:-
l = ( P + sqrt((P^2)-24S) ) / 24;
so substitute this l in equation(1) to get max volume.

How to use switch with multiple enum values?

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.

How to find position of nth token

We have a string that has a maximum limit of 20 words. If the user enters something that is more than 20 words, we then need to truncate the string at its 20th word. How can we automate this? We are able to find the 20th token with #GetToken(myString, 20, ' ')#, but are unsure on how to find it's position in order to left-trim. Any ideas?
Thanks in advance.
The UDF ListLeft() should do what you want. It takes a list and returns the list with the number of elements you define. "Space" is fine as a delimiter.
/**
* A Left() function for lists. Returns the n leftmost elements from the specified list.
*
* #param list List you want to return the n leftmost elements from.
* #param numElements Number of leftmost elements you want returned.
* #param delimiter Delimiter for the list. Default is the comma.
* #return Returns a string,
* #author Rob Brooks-Bilson (rbils#amkor.com)
* #version 1, April 24, 2002
*/
function ListLeft(list, numElements){
var tempList="";
var i=0;
var delimiter=",";
if (ArrayLen(arguments) gt 2){
delimiter = arguments[3];
}
if (numElements gte ListLen(list, delimiter)){
return list;
}
for (i=1; i LTE numElements; i=i+1){
tempList=ListAppend(tempList, ListGetAt(list, i, delimiter), delimiter);
}
return tempList;
}
p.s. CFLIB.org is an outstanding resource, and is usually my first stop when I'm looking for something like this. I recommend it highly.
Can also use a regular expression (group #1 contains match): ^(?:\w+\s+){19}(\w+)
Maybe you could avoid trimming and instead rebuild the result from scratch, something like (pseudo-code, I don't know ColdFusion):
result = ''
for (i = 0; i < 20; ++i)
{
result = result + GetToken(myString, i, ' ');
}
Would that work?
Not sure if CF provides this, but generally there is a LastIndexOf(string token) method. Use that combined with a substring function. For isntance (psuedocode):
string lastWord = GetToken(myString, 20, ' ');
string output = Substring(mystring, 0, LastIndexOf(mystring, lastWord)+StrLength(lastWord));

Resources