xrjf 230 Posting Whiz

If you're looking for concision, you may code something like:

        static void Main(string[] args)
        {
            string str = "abc,123.xyz;praise;end,file,clear";
            Console.WriteLine(String.Join("\r\n", 
                Regex.Split(str, @"(\,|\.|\;)+")));
            Console.ReadLine();
        }
ddanbe commented: Hey, nice tip! +15
xrjf 230 Posting Whiz

If ever you change your mind and go for the open source solution find attached a VStudio 2010 project. Need to say I did no charting. The .vb file names ending in "pdf" invoke pdfsharp.dll. The ones ending in "xls" correspond to the "pdf" ones with same sufix and the output format is an Excel Workbook. Note there are two font files (.ttf) to ensure the .pdf file contains embedded the required font. If you do so, you'll need to change the paths, the web reference, fields and anything else required to your needs.

savedlema commented: Thanks xrj, but I sorry, I can't see any attachment. Did you forget to attach? +2
xrjf 230 Posting Whiz

It depends, from my point of view and experience, on your taste and skills. I did an accounting project which employed Crystal Reports. Reading a good book or tutorial for Crystal Reports will save you many hours. The big advantage is that adding fields or totals in a report is easy and WYSIWYG, although I personally had some trouble during ClickOnce deployments. But after several tries all went smooth. Usually, new updates also reported new problems. The same as when upgrading Visual Studio or when having a new PC. Time after, as new reports were needed, I opted for PdfSharp -an Open Source Library-. All the previous problems dissapeared, but instead there was no WYSIWYG, so you I had to parametrize the fields, do subtotals, totals, page breaks and so on by code. This may be a hard task for some not used to this kind of work.

savedlema commented: Thanks very much xrj. +2
xrjf 230 Posting Whiz

Long time ago, by means of Bussiness Basic, I had this problem as "homework". It did was a headache and there was no Wikipedia nor Internet, just some colleagues comments that really did their best. Allow me to contribute with the following code:

        static void Main(string[] args)
        {
           System.Globalization.CultureInfo ci = 
               new System.Globalization.CultureInfo("en-US");
           System.Globalization.CultureInfo.DefaultThreadCurrentCulture = 
               ci;
           Int32 initYear = 1990;
           Int32 curYear = initYear;
           DateTime dt = new DateTime(curYear, 1, 1);
           DateTime dtStop = DateTime.Today;
           Int32 nErr1, nErr2, nDates;
            Int32 code0, code1, code2;
            do
            {
                Console.Write(dt.ToString("yyyy/MM/dd"));
                code0 = (Int32)dt.DayOfWeek;
                code1 = dateDaycode(dt.Year, dt.Month, dt.Day);
                if (code0 != code1)
                    nErr1++;
                code2 = dateDaycodeWiki(dt.Year, dt.Month, dt.Day);
                if (code0 != code2)
                    nErr2++;
                Console.WriteLine();
                dt = dt.AddDays(1);
                if (dt.Year != curYear)
                {
                    curYear++;
                    dt = new DateTime(curYear, 1, 1);
                }
                nDates++;
            } while (dt <= dtStop);
            if (nErr1 != 0)
                Console.WriteLine(nErr1.ToString() + " code 1 errors found ");
            if (nErr2 != 0)
                Console.WriteLine(nErr2.ToString() + " code 2 errors found ");
                   Console.WriteLine(nDates.ToString() + " total days between dates 01/01/" + 
                   initYear.ToString() + " and " + dtStop.ToShortDateString());
           Console.WriteLine("Press Enter to exit");
           Console.ReadLine();

        }
        public int dateDaycode(int year, int month, int day)
        {
            //Using Zeller's formula
            int d1, d2, d3, d4, code;
            if (month == 1)
            {
                month = 13; year--;
            }
            if (month == 2)
            {
                month = 14; year--;
            }
            d1 = year / 4;
            d2 = year / 100;
            d3 = year / 400;
            d4 = day + 2 * month + 3 * (month + 1) / 5 + year; …
ddanbe commented: Allow me to upvote, albeit a bit late I guess. :) +15
xrjf 230 Posting Whiz

Most probably, version 8.4.7 will be the last of the 8.4.x sequence. With respect to the previous version it has incorporated the roots' finding function for polynomials. This is achived by passing a complex array to the Eval() method:

     Dim cplxRoots() As Complex = Nothing
     '  Evaluate:
     If Not eP.Eval(result, vNames, vValues, cplxRoots) Then
         Exit Try
     End If

If, on the return, 'cplxRoots' is not 'Nothing' the array contents will be the polynomial's roots. Each entry of the array will be one of the roots. Let's say the polynomial is x^3-1 and we need to know the roots. So, we enter roots(x^3-1) to call the 'roots' function, and click on Calculate:
fae319cc1570fcca7b6b74c2f01d4274

Because a third degree polynomial has three roots, the output shows us the three roots. Polynomial x^3-1 has one real root and two complex roots, conjugates.

Note: don't forget to clear the variables' box under the label 'Variable = value'. Otherwise if 'x' has been set to a value, x^3-1 won't be treated as a polynomial, but as a value, and therefore no roots will be found!:

db813fa59098677be649451fe2c8a3f7

xrjf 230 Posting Whiz

As you may see in the images about Mates8 (version 8.4.6), it can manage polynomials, although finds no roots yet. Multiplication and division of polynomials can be detailed.

d1c2484283ce1433f4b0cc8eccea7856

fd3e1a082288edc1e0a9bf8cd2894acb

c7f56423e675e2dfa5e7ade7da60c291

xrjf 230 Posting Whiz

Today's release Mates8v8.4.3 is composed a zip file containing the source code (the executable is in folder ...\testMates8\testMates8\bin\Debug\testMates8.exe) and a .pdf document.

xrjf 230 Posting Whiz

16dfea3fc52b71aa61803657eb9c7cf24d08b66c8f2e9dd9c45ff169a44fe198
Hoping you take advantage out of this tutorial, best regards.
Xavier.

xrjf 230 Posting Whiz

Here is the next Mates8 version (8.4.2). I have tried to give more explanations but perhaps not so much as it would be convinient. So, I beg your pardon for this and for my lack of good english, although you may be sure I strive hard -or that's what I believe.
If you are interested in Mates8v8.4.2 you may take a look to the images here or download the .pdf tutorial (contents should be the same) and the .zip file of the source code.
b58000387eec862d0f89351d9c1e21eba4fcc9cfbd92d7ba4a82d1d4df7ace71707103716af8fd61e23bf50ed8c0f58dcf0c6da11157616f69084394f5b9a176df74e9a6e5401fad652186f426e2d812

xrjf 230 Posting Whiz

The mentioned modifications.

xrjf 230 Posting Whiz

Finally, the other 3 classes are:

Public Class m8Response
    Public sExpression As String
    Public retDouble As Double
    Public rpn As RPN_Stack
    Public Overrides Function ToString() As String
        Return retDouble.ToString(MathGlobal8.us)
    End Function
End Class




Public Class msg8
    Inherits ApplicationException

    Dim eP As exprParser
    Dim msg As String
    Public Sub New()
    End Sub
    Public Sub New(exprP As exprParser)
        eP = exprP
    End Sub
    Private Function msgN(n As Int32) As String
        Dim e1 As String = String.Empty
        Try
            Select Case n
                Case 1 : e1 = "Empty expression."
                Case 2 : e1 = "Token sequence ""{0} {1}"" is not valid."
                Case 3 : e1 = "Ending token ""{0}"" is not valid."
                Case 4 : e1 = "Starting token is not valid."
                Case 5 : e1 = "n/a: the expression is incomplete/unintelligible."
                Case 6 : e1 = "n/a, token ""{0}"" is unknown/not allowed."
                Case 7 : e1 = "Argument out of bounds."
                Case 8 : e1 = "n/a: stack is empty."
                Case 9 : e1 = "n/a: missing one or more matching left parenthesis."
                Case 10 : e1 = "n/a: missing one or more matching right parenthesis."
            End Select
        Catch ex As Exception
            Throw ex
        End Try
        Return e1
    End Function
    Public ReadOnly Property num(ByVal i As Int32, ParamArray Arr() As Object) As Exception
        Get
            Try
                If i < 1 Then
                    msg = "n/a"
                ElseIf Arr IsNot Nothing Then
                    Dim e1 As String = msgN(i)
                    msg = String.Format(e1, Arr)
                Else
                    msg = msgN(i)
                End If
            Catch ex As Exception
                Throw ex
            End Try …
xrjf 230 Posting Whiz

"reNum" stands for a Regex instance defined in class MathGlobal8. The purpose of "reNum" is to parse a number out from input string:

Imports System.Reflection
Imports System.Text.RegularExpressions
Imports System.Runtime.Serialization

<Serializable()> _
Public Class MathGlobal8

    Public Shared us As New Globalization.CultureInfo("en-US")
    Public Shared sNum = "(?<num>(([0-9]{1,3},[0-9]{3}(?![0-9])|[0-9])+\.?[0-9]*|[0-9]*\.?[0-9]+)([eE][-+]?[0-9]+)?)"
    Public Shared reNum As New Regex(sNum)

    Shared Function NameAndVersion() As String
        Dim sNV As String = String.Empty
        Try
            Dim asmbly As Assembly = System.Reflection.Assembly.GetAssembly(GetType(MathGlobal8))
            Dim name As AssemblyName = asmbly.GetName()
            sNV = name.Version.ToString
            sNV = name.Name + " -- " + Left(sNV, Len(sNV) - 2)
        Catch ex As Exception

        End Try
        Return sNV
    End Function

End Class
xrjf 230 Posting Whiz

If you have understood the above "Module1" example, you'll also see that class exprParser follows similar mechanics: nextExpr() calls nextTerm() which, in turn, calls nextPow(), that calls nextToken(). Here, nextToken() grabs the next number and operator (unless it's the last token) before returning.

Imports System.Text.RegularExpressions
Imports System.Text

<Serializable()> _
Public Class exprParser

    Dim bGetRPN As Boolean
    Dim cnt As Int32
    Dim iRe, curOp As Int32
    Dim curNum As Double
    Dim sExpr As String
    Dim vByte() As Byte
    Dim ln As Int32
    Friend err As Exception
    Public ret As m8Response
    Dim rpn As RPN_Stack
    Dim mode As modeType
    Dim reNum As Regex = MathGlobal8.reNum
    Public Sub New(mode As modeType, Optional strToParse As String = "")
        Try
            InitStr(strToParse)
            Me.mode = mode
            Init()
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Sub Init()
        Try
            ret = New m8Response
            If (mode And modeType.PrepareForEval) Then
                bGetRPN = True
            Else
                bGetRPN = False
            End If
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Sub InitStr(strToParse As String)
        Me.sExpr = strToParse
        vByte = Text.ASCIIEncoding.ASCII.GetBytes(sExpr)
        ln = vByte.Length
    End Sub
    Public Function Parse(strToParse As String, ByRef Result As Double) As Boolean
        Dim bRet As Boolean
        Try
            InitStr(strToParse)
            bRet = Parse(Result)
        Catch ex As Exception
            err = ex
            bRet = False
        End Try
        Return bRet
    End Function
    Public Function Parse(ByRef Result As Double) As Boolean
        Try

            cnt = 0 : iRe = 0 : curNum = 0.0 : err = Nothing

            If Not rpn.bInitialized Then
                rpn = New RPN_Stack(Me, ln * 3 / 2) …
xrjf 230 Posting Whiz

Present explanation is about version 8.4.1. There have been many changes, so the code is differs slightly from 8.4.0: I am sorry for the inconvients it may cause.
But, now, the code seems to me pretty fast, considering we are talking about VBasic. In a desktop (Pc @3GHz-64bits Windows 8.1) the average time for an expression like 1600/((1-(1+1/4)^30)/(1-(1+1/4))) it can take about 10/20 ns to process the arithmetic:
29039bd20b59281c29c45331ceb85121
Lets enumerate the classes. These are:
exprParser
m8Response
MathGlobal8
msg8
RPN_Stack

At the moment, a Mates8 client just needs to be employ exprParser and m8Response classes.
Imports Mates8

Public Class Form1
    Dim eP As exprParser
    Dim nIter As Int32 = 1000
    Const ticks_second = 10 ^ 7
    Const ms_second = 1000

#Region "Calculate"
    Sub Calculate()
        Try
            Dim t1 As Int64 = Now.Ticks
            Dim db As Double
            tbOutput.Text = ""
            lblStack.Text = ""

            eP = New exprParser(modeType.Calculate, tbInput.Text)

            For i = 1 To nIter
                If Not eP.Parse(db) Then
                    ' Show error message:
                    lblMessage.Text = eP.retErr.ToString
                    Exit Sub
                End If
            Next
            Dim t2 As Int64 = Now.Ticks - t1
            ' Show the result:
            tbOutput.Text = eP.ret.ToString
            lblMessage.Text = String.Format("exprParse.Parse()" + vbCrLf +               "Average Time: {0} ms " +
                   vbCrLf + "({1} iterations)", ((t2 / ticks_second / nIter _
                   ) * ms_second).ToString(MathGlobal8.us), nIter)
        Catch ex As Exception
            MessageBox.Show("Unexpected error:" + vbCrLf + ex.Message)
        End Try
    End Sub
#End Region

Evaluating the stack is much faster, once the stack has been …

xrjf 230 Posting Whiz

Here is the explanation, along with a VB.Net module.
There are four consecutive functions. Each one invokes the next and, on exit, returns back to the previous function the result. Namely:
1. expression() performs "+" and "-" operations
2. term() performs "" and "/" operations
3. pow() performs "^","%" and "!" operations
function expression() calls term()
function term() calls pow()
function pow() calls token()
Then token() returns back the first operand, after setting the current caracter behind the operand, so pointing to the first operator. In case of a "+" or "-" operator (as in "2+3"), the execution will return back to expression, receiving the first operand value and then calling back to term() for the second operand. In a similar way, term() will call pow(), pow() will call token() and, then return, all the way up, to expression. There, operation "+" or "-" will take place.
In case there is another operator after the second operator, for instance a "
" in "2+34", in the middle of the way up, from token() to expression(), function term() will find that must perform current operator "". So before the addition, term() will call pow() asking for the second operand. This will be a "4", "3*4" will be calculated and return back to expression() his second operand equal to 12 and add to the first 2.
When token() founds a "(" calls, recursively, to expression(). Expression() will return back to token() the result …

xrjf 230 Posting Whiz

Instead of drawing the box, another approach would be to load 2 images: one with the box and the other without (or whatever images you decide). Then in the OnDrawItem() just call e.Graphics.DrawImage() method to draw the box image or the no-box-image.

xrjf 230 Posting Whiz

I see, in a short term, I'll provide Daniweb an extense explanation.

xrjf 230 Posting Whiz

Let's say it works from left to right.
If eax contains a 5, then:
cmp eax, 6 ; eax < 6
jb label ; will jump to label

pbj.codez commented: Exactly what I needed to see. Thank you again =D +0
xrjf 230 Posting Whiz

Long time since I wrote my last asm code, but I'll try to answer your questions:

69. mov dword [Guess], 5 states that a 5 will be moved to position pointed by Guess and value will occupy a double word length (32 bits). This is equivalent to 'guess = 5' in C, though in C you move always 32 bits: you don't just move 16 bits as in

mov word [guess], 5

79. The comment is right, it's eax * eax = 9
82. Line 81 compares eax and the value 'pointed' by 'Guess', this updates the status registers, so in #82 'jump if not below' jnb will jump if factor*factor >= Guess. This jump will avoid adding 2 in line 89 (Think that the 1st condition of line 28 is failing so it jumps to line 30, whose equivalent is line 91)
85 64-bit contents of EDX-EAX are divided by the operand (ebx), leaving a 32-bit quotient in eax and a 32-bit remainder in edx.
87 if edx was equal to 0 (#86) it will jump to end_while_factor, because now the 2nd condition (see line 28) is failing and addition in line #89 needs to be omitted.
92 'je' is a mnemonic for 'jump if equal' in the last 'cmp' executed.
pbj.codez commented: Thank you for the help. +0