Parsing a string formula to an integer result - string

I'm doing some parsing work, too complex to get into details, but there's one simple thing I need to do (at least simple concept, maybe not simple answer). I might have a formula in a string such as the samples below. I need a function that will take a loosly-formatted formula string, parse it out, and calculate the result.
Sample:
(10 / 2)+(10/30)
5+(10/30)
5+3
8
Or:
(12.5 - (0.5 * 5)) / 2
(12.5 - 2.5) / 2
10 / 2
5
Rules:
Spaces are to be ignored
PEMDAS method must entirely apply
Result shall be always a rounded Integer
No variables will exist, already converted to numbers
Decimal numbers might be part of the input
The existing parsing I already have working just gets one of these formula strings - but from there, I have no clue how to perform the actual calculations. What I'm doing specifically is doing a little line deliminated scripter to draw to a canvas, here's some sample script:
Var W 50
Var H 50
Pen Style Clear
Pen Color $000000
Pen Width 3
Brush Style Solid
Brush Color {FORM_COLOR}
Rect 0 0 {WIDTH} {HEIGHT}
Brush Color $501010
Ellipse #W #H 450 450
Brush Color $602020
Ellipse 100 100 400 400
Brush Color $703030
Ellipse 150 150 350 350
Brush Color $804040
Ellipse 200 200 300 300
EllipseG 200 200 300 300 6 2
Pen Style Solid
Pen Width 2
Pen Color {FONT_COLOR}
MoveTo 0 0
LineTo 500 500
MoveTo 0 500
LineTo 500 0
All that already works, but now I want to say for example...
Var W
Var H
Set W 50
Set H 50
Brush Color $602020
Ellipse(#W, #H, 500 - #W, 500 - #H
Set W 100
Set H 100
Brush Color $703030
Ellipse(#W, #H, 500 - #W, 500 - #H
Set W 150
Set H 150
Brush Color $804040
Ellipse(#W, #H, 500 - #W, 500 - #H
So the 500 - #W I already convert it to 500 - 50 but now I need to send the string 500 - 50 into this function to get the result 450.
EDIT: Solved
I'm using the parser10 as recommended, and it works perfectly for what I need to do. Here's a sample snippet of my script code:
Var S 4
Var D #S
Var L 0
Var T 0
Var R {WIDTH}
Var B {HEIGHT}
Pen Style Clear
Pen Color $00000000
Pen Width 3
Brush Style Solid
Brush Color {FORM_COLOR}
Rect 0 0 {WIDTH} {HEIGHT}
Set D #D+#S
Brush Color $00400000
Ellipse #L+#D #T+#D #R-(#D*2) #B-(#D*2)
Set D #D+#S
Brush Color $00501010
Ellipse #L+#D #T+#D #R-(#D*2) #B-(#D*2)
Set D #D+#S
Brush Color $00602020
Ellipse #L+#D #T+#D #R-(#D*2) #B-(#D*2)
Set D #D+#S
Brush Color $00703030
Ellipse #L+#D #T+#D #R-(#D*2) #B-(#D*2)
Set D #D+#S
Brush Color $00804040
Ellipse #L+#D #T+#D #R-(#D*2) #B-(#D*2)
Set D #D+#S
Brush Color $00905050
Ellipse #L+#D #T+#D #R-(#D*2) #B-(#D*2)
Set D #D+#S
Brush Color $00FB6060
Ellipse #L+#D #T+#D #R-(#D*2) #B-(#D*2)
Anything starting with an # is a variable, which I do a StringReplace() to convert all those based on what was declared in the Var section.

Parser10, written originally by Renate Schaaf for Delphi 1 and later upgraded to Delphi2 and 3 by Alin Flaider and Stefan Hoffmeister, is a fairly simple math parser. It will do the job for simple expressions and can serve as a boilerplate for more complex work.
It is not built for speed though.
Update :
Hallvard Vassbotn made an update of Parser10 and added some documentation. Load it from here.

List of Parsers, Mathematical Expression Evaluators, Calculators: here
[Edit]
Or a TBindExpression in Delphi XE2, not sure if its apply PEMDAS

Related

How to define BGR color range? Map color code to color name

I want to create color mapping, define few color names and boundaries in range of which those colors should fall. For example (BGR format),
colors = {
'red': ((0, 0, 255), (125, 125, 255)),
'blue': ((255, 0, 0), (255, 125, 125)),
'yellow' ....
}
So if I receive color, let's say (255, 50, 119) I can call it blue. I want to make such mapping for at least colors of rainbow plus gray, black, white. Using Python and openCV.
The problem is that I don't really understand where to get those values for boundaries, is there kind of lowest / highest value for blue, red and so on?
I would suggest using HSV colourspace for comparing colours because it is less sensitive to variable lighting than RGB, where green in the sunlight might be rgb(20,255,10), but green in a shadow might be rgb(3,45,2), whereas both will have a very similar Hue in HSV colourspace.
So, to get started...
Create a little 10x1 numpy array and make the first pixel red, the second orange, then yellow, green, blue, indigo, violet then black, mid-grey and white. There's a table here.
Then convert to HSV colourspace and note the Hue values.
I have started some code...
#!/usr/local/bin/python3
import numpy as np
import imageio
import cv2
# Create black image 10x1
im = np.zeros([1,10,3], dtype=np.uint8)
# Fill with colours of rainbow and greys
im[0,0,:]=[255,0,0] # red
im[0,1,:]=[255,165,0] # orange
im[0,2,:]=[255,255,0] # yellow
im[0,3,:]=[0,255,0] # green
im[0,4,:]=[0,0,255] # blue
im[0,5,:]=[75,0,130] # indigo
im[0,6,:]=[238,130,238] # violet
im[0,7,:]=[0,0,0] # black
im[0,8,:]=[127,127,127] # grey
im[0,9,:]=[255,255,255] # white
imageio.imwrite("result.png",im)
hsv=cv2.cvtColor(im,cv2.COLOR_RGB2HSV)
print(hsv)
Check image:
Check colours with Imagemagick too:
convert result.png txt:
# ImageMagick pixel enumeration: 10,1,65535,srgb
0,0: (65535,0,0) #FF0000 red
1,0: (65535,42405,0) #FFA500 orange
2,0: (65535,65535,0) #FFFF00 yellow
3,0: (0,65535,0) #00FF00 lime
4,0: (0,0,65535) #0000FF blue
5,0: (19275,0,33410) #4B0082 indigo
6,0: (61166,33410,61166) #EE82EE violet
7,0: (0,0,0) #000000 black
8,0: (32639,32639,32639) #7F7F7F grey50
9,0: (65535,65535,65535) #FFFFFF white
Now look at the HSV array below - specifically the first column (Hue). You can see Red has a Hue=0, Orange is 19, Yellow is 30 and so on. Note too that the Black, Grey and White all have zero Saturation and Black has a low Value, Grey has a medium Value and White has a high Value.
[[[ 0 255 255]
[ 19 255 255]
[ 30 255 255]
[ 60 255 255]
[120 255 255]
[137 255 130]
[150 116 238]
[ 0 0 0]
[ 0 0 127]
[ 0 0 255]]]
Now you can make a data-structure in Python that stores, for each colour:
Lowest included Hue
Highest included Hue
Name
So, you might use:
... see note at bottom for Red
14,23,"Orange"
25,35,"Yellow"
55,65,"Green"
115,125,"Blue"
...
and so on - omit Black, Grey and White from the table.
So, how do you use this?
Well, When you get a colour to check, first convert the R, G and B values to HSV and look at the resulting Saturation - which is a measure of vividness of the colour. Garish colours will have high saturation, whereas lacklustre, greyish colours will have low saturation.
So, see if the Saturation is more than say 10% of the max possible, e.g. more than 25 on a scale of 0-255.
If the Saturation is below the limit, check the Value and assign Black if Value low, Grey if middling and White if Value is high.
If the Saturation is above the limit, check if it is within the lower and upper limits of one of your recorded Hues and name it accordingly.
So the code is something like this:
def ColorNameFromRGB(R,G,B)
# Calculate HSV from R,G,B - something like this
# Make a single pixel from the parameters
onepx=np.reshape(np.array([R,G,B],dtype=np.uint8),(1,1,3))
# Convert it to HSV
onepxHSV=cv2.cvtColor(onepx,cv2.COLOR_RGB2HSV)
...
...
if S<25:
if V<85:
return "black"
elsif V<170:
return "grey"
return "white"
# This is a saturated colour
Iterate through colour names table and return name of entry with matching Hue
There are 2 things to be aware of:
There is a discontinuity in the Hue values for Red, because the HSV colour wheel is a circular wheel and the Hue value for Red is at an angle of 0, so values above 350 and below 10 are all Reds. It so happens that OpenCV scales the 0-360 range by dividing by 2, meaning it comes out as 0-180... which neatly fits in a single unsigned byte. So, for Red, you need to check for Hue greater than 175 and less than 5, say.
Be careful to always generate an 8-bit image when looking up colours, as the Hue values are scaled differently on 16-bit and float images.
Define a distance between two colors. Then find the "closest" color name for the given color. Which definition of distance you will choose has to be guided by your requirements, because there is no "best" definition, as far as I know.
One possibility is distance in RGB space. The distance between two colors can be defined, for example, as the euclidean (L2) distance between the colors as represented by vectors in three dimensional space - distance(a,b) = (a-b).length() Alternatively, try the Manhattan (L1) metric if the result makes sense, because the euclidean distance in RGB space is more of a heuristic than a valid measurement.
Another possibility is to first convert to HSV space. Then the closest color will be the one that has the closest hue to the given color. Unless the given color has insufficient saturation, then the color is either white, gray or black, depending on the color's lightness.

How does ncurses' init_color function translate to traditional rbg colors?

Sorry for the oddly worded title. I'd like to know how the ncurses init_color function maps it's input to colors. Essentially, most developers are used to colors being represented by red, green, and blue on a 0 - 255 scale, but init_color takes an int on a 0 - 1000 scale.
for example:
If I wanted to get the color (75, 0, 130) in ncurses, would I call init_color(COLOR_NAME, 300, 0, 520)?
short:
(n) * 1000 / 256
which is a little different from your numbers:
293 0 508
long: That of course assumes that the terminal description is written to match ncurses' documentation. But the assumption is from X/Open Curses:
The init_color() function redefines colour number color, on terminals that support the redefinition of colours, to have the red, green, and blue intensity components specified by red, green, and blue, respectively. Calling init_color() also changes all occurrences of the specified colour on the screen to the new definition.
The color_content() function identifies the intensity components of colour number color. It stores the red, green, and blue intensity components of this colour in the addresses pointed to by red, green, and blue, respectively.
For both functions, the color argument must be in the range from 0 to and including COLORS-1. Valid intensity values range from 0 (no intensity component) up to and including 1000 (maximum intensity in that component).

Rotate label by variable angle in polar plot

I plotted many points with labels in an polar coordinate system. Now I want to rotate the labels in the tangential direction. So I have to rotate
a point plotted at t=0, r=arbitrary by 0 degrees,
a point plotted at t=pi/2, r=arbitrary by 90 degrees,
a point plotted at t=pi, r=arbitrary by 180 degrees and so on.
I found the 'rotate by' function here: http://gnuplot.sourceforge.net/demo/textrotate.html
But only fixed values for the rotate angle are possible.
I thought about sth. like:
plot 'point-data.dat' using ($1/360*2*pi):($2):($1) with labels rotate by variable font "arial,8"
Is it possible?
I tried to do the same thing and found a "workaround" to do this. It is not perfect but it worked in my case:
You can do many plots in a loop and assign a different text angle for each plot:
data file data.txt:
#alpha r label rotation
0 1 text1 10
.2 1 text2 20
.4 1 text3 30
.6 1 text4 40
.8 1 text5 50
1 1 text6 60
Plotting commands:
isequal(x1,x2,x3)=(x1==x2?x3:1/0)
setonly(x1,x2,x3)=((x1==x2)?roto=x3:1/0)
set polar
plot for [k=0:7] "data.txt" u (isequal(($0),k,($1))):((setonly( ($0),k,($4) )*0.0)+($2)):3 w labels rotate by roto

How to find the tangent to any pixel?

I want to find tangent at each pixel in image.
NOTE: image is having white background and shape border color is block.
What i did is,
Algo
While(true)
take pixel
if pixel color is black
make 3 X 3 matrix => fill the matrix by surrounding pixel color
...means assume white =0 and black=1 then keeping selected pixel
at center for 3 X 3 matrix and finding all other value;
----------------------------here i want to find tangent line to selected pixel;
end if
Move to next pixel.
End while
Please help Exams on head .
What you're looking for is probably a Sobel Operator. It's implemented as a convolution of the neighborhood around a pixel with the matrix:
-1 0 1
-2 0 2
-1 0 1
and again with:
-1 -2 -1
0 0 0
1 2 1
Call the results of the 2 convolutions x and y, respectively. Once you have them, you can get the magnitude of the gradient by taking the square root of the sum of the squares:
mag = sqrt(x * x + y * y);
and the direction of the gradient (which should be tangent to the pixel you're examining) by taking the arctangent of y over x:
tangent = atan2(y / x)

how to calculate gradient color by percent

I have a float score, which is 0 to 1
I need translate this score to color,
0 is green
1 is red
0.5 should at the middle of green to red gradient color
and so on
how to write this? I have no idea.
let gradient colour parameter be t, 0.0 =< t =< 1.0
colour = RGB(255 * t, 255 * (1 - t), 0)
Multiply the float by 255 to get your green value, and multiply (1-float) by 255 to get your red value. If you need to output a css color code, use rgb(x,y,z).

Resources