Loading ...
Sorry, an error occurred while loading the content.

VanWeerthuizenian Expressions

Expand Messages
  • flo.gehrke
    It has been discussed several times that NT doesn t master Boolean Expressions (cf message #21773). And we considered tools like DOS Findstr, Agent Ransack etc
    Message 1 of 12 , Sep 10, 2013
    • 0 Attachment
      It has been discussed several times that NT doesn't master Boolean Expressions (cf message #21773). And we considered tools like DOS Findstr, Agent Ransack etc to be used in this case. It should also be mentioned that, to some extent, we could simulate Boolean Expressions with RegEx.

      Some years ago, Wayne VanWeerthuizen described another approach in his 'NoteTab Tutorial Control Structures v003.OTL' (see the 'File' section of this group).

      I picked up another topic (#22762) and tried to find a solution for that job based on instructions given by Wayne in his tutorial.

      Example: We've got five lines...

      tR4hGGUK
      2UJeiy9m
      WbNDSk9e
      Mytrip12
      My.tip12

      The task is to select lines which fulfill five criteria:

      (A) 8 characters
      (B) at least 2 upper characters
      (C) at least 2 lower characters
      (D) at least one digit
      (E) no punctuation characters or spaces

      According with Wayne's tutorial, I tried to translate his instructions to the following clip:

      ^!Set %Lines%=^$GetTextLineCount$
      ^!Set %Row%=1
      :Loop
      ^!Set %A%=0; %B%=0; %C%=0; %D%=0; %E%=0
      ^!Jump ^%Row%
      ; Condition #1: a string of 8 characters
      ^!If ^$StrPos("\b.{8}\b";"^$GetLine$";R)$>0 ^!Set %A%=1
      ; Condition #2: at least 2 upper characters in line
      ^!If ^$StrPos("[[:upper:]][[:alnum:]]*[[:upper:]]";"^$GetLine$";R)$>0 ^!Set %B%=1
      ; Condition #3: at least 2 lower letters in line
      ^!If ^$StrPos("[[:lower:]][[:alnum:]]*[[:lower:]]";"^$GetLine$";R)$>0 ^!Set %C%=1
      ; Condition #4: at least one digit in line
      ^!If ^$StrPos("[0-9]";"^$GetLine$";R)$>0 ^!Set %D%=1
      ; Condition #5: No punctuation characters or spaces in line
      ^!If ^$StrPos("[\x20\pP]";"^$GetLine$";R)$>0 ^!Set %E%=1
      ; Logical test of all criteria
      ^!If ^$Calc(MIN(^%A%;MIN(^%B;MIN(^%C%;MIN(^%D%;1-^%E%)))))$=1 Next Else Skip
      ; If whole expression is true then append line to %Hits%
      ^!Set %Hits%=^%Hits%^$GetLine$^P
      ^!Inc %Row%
      ^!If ^$GetRow$ < ^%Lines% Loop
      ; Output hits
      ^!Info [L]^%Hits%
      ^!ClearVariables

      Actually, this clip leads to the intended result and outputs line #1, #2, and #3 only, exactly matching those criteria. That is, the clip simulates a Boolean query like 'A and B and C and D and E and not E' reproduced with '^$Calc$'.

      Of course, this particular task might be resolved in easier ways. However, what matters here is this specific approach which - as Wayne explained - could apply to much more complex queries (with AND, OR, XOR, NOT etc). In cases like that, it would be difficult to use RegEx, and compound loops would end in extremely long "IF, ELSE IF, ELSE IF Chains" (Wayne).

      What I would like to know:

      Is anyone (also Wayne himself) still using such expressions and could give us more examples. Regrettably, Wayne's Tutorial was never finished and has remained a highly instructive fragment only. Also, it's lacking complete working examples.

      Regards,
      Flo
    • joy8388608
      I sometimes do things like this but never heard of the tutorial you mentioned. Where would I find it? I m not clear what kind of examples you are looking for
      Message 2 of 12 , Sep 11, 2013
      • 0 Attachment

        I sometimes do things like this but never heard of the tutorial you mentioned. Where would I find it?


        I'm not clear what kind of examples you are looking for but maybe seeing the tutorial would make it clearer..


        As to your example, I would write two lines slightly differently since it seems much clearer to the way I think.


        ^!Set %Lines%=^$GetTextLineCount$

        ^!Set %Row%=1

        :Loop

        ^!Set %A%=0; %B%=0; %C%=0; %D%=0; %E%=0

        ^!Jump ^%Row%

        ; Condition #1: a string of 8 characters

        ^!If ^$StrPos("\b.{8}\b";"^$GetLine$";R)$>0 ^!Set %A%=1

        ; Condition #2: at least 2 upper characters in line

        ^!If ^$StrPos("[[:upper:]][[:alnum:]]*[[:upper:]]";"^$GetLine$";R)$>0 ^!Set %B%=1

        ; Condition #3: at least 2 lower letters in line

        ^!If ^$StrPos("[[:lower:]][[:alnum:]]*[[:lower:]]";"^$GetLine$";R)$>0 ^!Set %C%=1

        ; Condition #4: at least one digit in line

        ^!If ^$StrPos("[0-9]";"^$GetLine$";R)$>0 ^!Set %D%=1


        ; Condition #5: No punctuation characters or spaces in line

        ;^!If ^$StrPos("[\x20&#92;pP]";"^$GetLine$";R)$>0 ^!Set %E%=1

        ^!If ^$StrPos("[\x20\pP]";"^$GetLine$";R)$=0 ^!Set %E%=1


        ; Logical test of all criteria

        ^!Prompt ^%A% + ^%B + ^%C% + ^%D% + ^%E%


        ;^!If ^$Calc(MIN(^%A%;MIN(^%B;MIN(^%C%;MIN(^%D%;1-^%E%)))))$=1 Next Else Skip

        ^!If ^$Calc(^%A% + ^%B + ^%C% + ^%D% + ^%E%)$ = 5 Next Else Skip

        ; If whole expression is true then append line to %Hits%

        ^!Set %Hits%=^%Hits%^$GetLine$^P

        ^!Inc %Row%

        ^!If ^$GetRow$ < ^%Lines% Loop

        ; Output hits

        ^!Info [L]^%Hits%

        ^!ClearVariables


        Joy



        --- In ntb-clips@yahoogroups.com, <flo.gehrke@...> wrote:

        It has been discussed several times that NT doesn't master Boolean Expressions (cf message #21773). And we considered tools like DOS Findstr, Agent Ransack etc to be used in this case. It should also be mentioned that, to some extent, we could simulate Boolean Expressions with RegEx.

        Some years ago, Wayne VanWeerthuizen described another approach in his 'NoteTab Tutorial Control Structures v003.OTL' (see the 'File' section of this group).

        I picked up another topic (#22762) and tried to find a solution for that job based on instructions given by Wayne in his tutorial.

        Example: We've got five lines...

        tR4hGGUK
        2UJeiy9m
        WbNDSk9e
        Mytrip12
        My.tip12

        The task is to select lines which fulfill five criteria:

        (A) 8 characters
        (B) at least 2 upper characters
        (C) at least 2 lower characters
        (D) at least one digit
        (E) no punctuation characters or spaces

        According with Wayne's tutorial, I tried to translate his instructions to the following clip:

        ^!Set %Lines%=^$GetTextLineCount$
        ^!Set %Row%=1
        :Loop
        ^!Set %A%=0; %B%=0; %C%=0; %D%=0; %E%=0
        ^!Jump ^%Row%
        ; Condition #1: a string of 8 characters
        ^!If ^$StrPos("\b.{8}\b";"^$GetLine$";R)$>0 ^!Set %A%=1
        ; Condition #2: at least 2 upper characters in line
        ^!If ^$StrPos("[[:upper:]][[:alnum:]]*[[:upper:]]";"^$GetLine$";R)$>0 ^!Set %B%=1
        ; Condition #3: at least 2 lower letters in line
        ^!If ^$StrPos("[[:lower:]][[:alnum:]]*[[:lower:]]";"^$GetLine$";R)$>0 ^!Set %C%=1
        ; Condition #4: at least one digit in line
        ^!If ^$StrPos("[0-9]";"^$GetLine$";R)$>0 ^!Set %D%=1
        ; Condition #5: No punctuation characters or spaces in line
        ^!If ^$StrPos("[\x20\pP]";"^$GetLine$";R)$>0 ^!Set %E%=1
        ; Logical test of all criteria
        ^!If ^$Calc(MIN(^%A%;MIN(^%B;MIN(^%C%;MIN(^%D%;1-^%E%)))))$=1 Next Else Skip
        ; If whole expression is true then append line to %Hits%
        ^!Set %Hits%=^%Hits%^$GetLine$^P
        ^!Inc %Row%
        ^!If ^$GetRow$ < ^%Lines% Loop
        ; Output hits
        ^!Info [L]^%Hits%
        ^!ClearVariables

        Actually, this clip leads to the intended result and outputs line #1, #2, and #3 only, exactly matching those criteria. That is, the clip simulates a Boolean query like 'A and B and C and D and E and not E' reproduced with '^$Calc$'.

        Of course, this particular task might be resolved in easier ways. However, what matters here is this specific approach which - as Wayne explained - could apply to much more complex queries (with AND, OR, XOR, NOT etc). In cases like that, it would be difficult to use RegEx, and compound loops would end in extremely long "IF, ELSE IF, ELSE IF Chains" (Wayne).

        What I would like to know:

        Is anyone (also Wayne himself) still using such expressions and could give us more examples. Regrettably, Wayne's Tutorial was never finished and has remained a highly instructive fragment only. Also, it's lacking complete working examples.

        Regards,
        Flo
      • joy8388608
        Some more thoughts... I have seen some reasons to do things similar to this, but it s often better to do it another way to save processing time (if that
        Message 3 of 12 , Sep 11, 2013
        • 0 Attachment

          Some more thoughts...


          I have seen some reasons to do things similar to this, but it's often better to do it another way to save processing time (if that matters any more :) )


          The code could have used one variable set to zero and incremented each time a test passed and the line accepted if the var = 5. I do like the original way since it lets you see which tests passed and which failed.


          For this example, a line is not accepted when any test fails so it is a waste to continue testing. Instead of setting a flag, a failure for any test could just move on to the next line to be tested.


          The only example I can think of right now where something kinda sorta like this would be useful is come code I have that acts on different combinations of choices such as Case Sens, RegEx on/off, etc. For something like this, I usually do something (usually in a wizard) like 


          If case sens off, set Flag1 to 0 else set it to 1.

          If regexp off, set Flag2 to 0 else set it to 2.

          If don't wantx, set Flag3 to 0 else set it to 4.

          etc


          The sum then tells what combination you have... 2 means want regexp on with the other two off, 5 means case sens on, wantx but regexp off and so on.


          Joy







          --- In ntb-clips@yahoogroups.com, <mycroftj@...> wrote:

          I sometimes do things like this but never heard of the tutorial you mentioned. Where would I find it?


          I'm not clear what kind of examples you are looking for but maybe seeing the tutorial would make it clearer..


          As to your example, I would write two lines slightly differently since it seems much clearer to the way I think.


          ^!Set %Lines%=^$GetTextLineCount$

          ^!Set %Row%=1

          :Loop

          ^!Set %A%=0; %B%=0; %C%=0; %D%=0; %E%=0

          ^!Jump ^%Row%

          ; Condition #1: a string of 8 characters

          ^!If ^$StrPos("\b.{8}\b";"^$GetLine$";R)$>0 ^!Set %A%=1

          ; Condition #2: at least 2 upper characters in line

          ^!If ^$StrPos("[[:upper:]][[:alnum:]]*[[:upper:]]";"^$GetLine$";R)$>0 ^!Set %B%=1

          ; Condition #3: at least 2 lower letters in line

          ^!If ^$StrPos("[[:lower:]][[:alnum:]]*[[:lower:]]";"^$GetLine$";R)$>0 ^!Set %C%=1

          ; Condition #4: at least one digit in line

          ^!If ^$StrPos("[0-9]";"^$GetLine$";R)$>0 ^!Set %D%=1


          ; Condition #5: No punctuation characters or spaces in line

          ;^!If ^$StrPos("[\x20&#92;pP]";"^$GetLine$";R)$>0 ^!Set %E%=1

          ^!If ^$StrPos("[\x20\pP]";"^$GetLine$";R)$=0 ^!Set %E%=1


          ; Logical test of all criteria

          ^!Prompt ^%A% + ^%B + ^%C% + ^%D% + ^%E%


          ;^!If ^$Calc(MIN(^%A%;MIN(^%B;MIN(^%C%;MIN(^%D%;1-^%E%)))))$=1 Next Else Skip

          ^!If ^$Calc(^%A% + ^%B + ^%C% + ^%D% + ^%E%)$ = 5 Next Else Skip

          ; If whole expression is true then append line to %Hits%

          ^!Set %Hits%=^%Hits%^$GetLine$^P

          ^!Inc %Row%

          ^!If ^$GetRow$ < ^%Lines% Loop

          ; Output hits

          ^!Info [L]^%Hits%

          ^!ClearVariables


          Joy



          --- In ntb-clips@yahoogroups.com, <flo.gehrke@...> wrote:

          It has been discussed several times that NT doesn't master Boolean Expressions (cf message #21773). And we considered tools like DOS Findstr, Agent Ransack etc to be used in this case. It should also be mentioned that, to some extent, we could simulate Boolean Expressions with RegEx.

          Some years ago, Wayne VanWeerthuizen described another approach in his 'NoteTab Tutorial Control Structures v003.OTL' (see the 'File' section of this group).

          I picked up another topic (#22762) and tried to find a solution for that job based on instructions given by Wayne in his tutorial.

          Example: We've got five lines...

          tR4hGGUK
          2UJeiy9m
          WbNDSk9e
          Mytrip12
          My.tip12

          The task is to select lines which fulfill five criteria:

          (A) 8 characters
          (B) at least 2 upper characters
          (C) at least 2 lower characters
          (D) at least one digit
          (E) no punctuation characters or spaces

          According with Wayne's tutorial, I tried to translate his instructions to the following clip:

          ^!Set %Lines%=^$GetTextLineCount$
          ^!Set %Row%=1
          :Loop
          ^!Set %A%=0; %B%=0; %C%=0; %D%=0; %E%=0
          ^!Jump ^%Row%
          ; Condition #1: a string of 8 characters
          ^!If ^$StrPos("\b.{8}\b";"^$GetLine$";R)$>0 ^!Set %A%=1
          ; Condition #2: at least 2 upper characters in line
          ^!If ^$StrPos("[[:upper:]][[:alnum:]]*[[:upper:]]";"^$GetLine$";R)$>0 ^!Set %B%=1
          ; Condition #3: at least 2 lower letters in line
          ^!If ^$StrPos("[[:lower:]][[:alnum:]]*[[:lower:]]";"^$GetLine$";R)$>0 ^!Set %C%=1
          ; Condition #4: at least one digit in line
          ^!If ^$StrPos("[0-9]";"^$GetLine$";R)$>0 ^!Set %D%=1
          ; Condition #5: No punctuation characters or spaces in line
          ^!If ^$StrPos("[\x20\pP]";"^$GetLine$";R)$>0 ^!Set %E%=1
          ; Logical test of all criteria
          ^!If ^$Calc(MIN(^%A%;MIN(^%B;MIN(^%C%;MIN(^%D%;1-^%E%)))))$=1 Next Else Skip
          ; If whole expression is true then append line to %Hits%
          ^!Set %Hits%=^%Hits%^$GetLine$^P
          ^!Inc %Row%
          ^!If ^$GetRow$ < ^%Lines% Loop
          ; Output hits
          ^!Info [L]^%Hits%
          ^!ClearVariables

          Actually, this clip leads to the intended result and outputs line #1, #2, and #3 only, exactly matching those criteria. That is, the clip simulates a Boolean query like 'A and B and C and D and E and not E' reproduced with '^$Calc$'.

          Of course, this particular task might be resolved in easier ways. However, what matters here is this specific approach which - as Wayne explained - could apply to much more complex queries (with AND, OR, XOR, NOT etc). In cases like that, it would be difficult to use RegEx, and compound loops would end in extremely long "IF, ELSE IF, ELSE IF Chains" (Wayne).

          What I would like to know:

          Is anyone (also Wayne himself) still using such expressions and could give us more examples. Regrettably, Wayne's Tutorial was never finished and has remained a highly instructive fragment only. Also, it's lacking complete working examples.

          Regards,
          Flo
        • flo.gehrke
          ... Joy, It s the... ... http://tech.groups.yahoo.com/group/ntb-clips/files The chapter: Appendixes , Performing Boolean Calculations . Note that Wayne
          Message 4 of 12 , Sep 11, 2013
          • 0 Attachment
            > I sometimes do things like this but never heard of the tutorial
            > you mentioned. Where would I find it?
            > I'm not clear what kind of examples you are looking for but maybe
            > seeing the tutorial would make it clearer..

            Joy,

            It's the...

            >> ...'NoteTab Tutorial Control Structures v003.OTL' (see the
            >> 'File' section of this group).

            http://tech.groups.yahoo.com/group/ntb-clips/files

            The chapter: "Appendixes", "Performing Boolean Calculations".

            Note that Wayne always uses a comma like 'MIN(A,B)' where a semicolon is needed!

            It would be nice to see some examples of the way you are using solutions like that ;-)

            Regards,
            Flo
          • Art Kocsis
            ... Flo, If I can jump in here. [Sorry for the length. This was meant to be a quicky but it grew!] In testing boolean expressions I prefer converting them to
            Message 5 of 12 , Sep 13, 2013
            • 0 Attachment
              At 9/10/2013 05:11 PM, Flo wrote:
              >It has been discussed several times that NT doesn't master Boolean Expressions (cf message #21773). And we considered tools like DOS Findstr, Agent Ransack etc to be used in this case. It should also be mentioned that, to some extent, we could simulate Boolean Expressions with RegEx.
              >
              >Some years ago, Wayne VanWeerthuizen described another approach in his 'NoteTab Tutorial Control Structures v003.OTL' (see the 'File' section of this group).
              >
              >I picked up another topic (#22762) and tried to find a solution for that job based on instructions given by Wayne in his tutorial.
              >
              >Example: We've got five lines...
              >
              >tR4hGGUK
              >2UJeiy9m
              >WbNDSk9e
              >Mytrip12
              >My.tip12
              >
              >The task is to select lines which fulfill five criteria:
              >
              >(A) 8 characters
              >(B) at least 2 upper characters
              >(C) at least 2 lower characters
              >(D) at least one digit
              >(E) no punctuation characters or spaces

              Flo, If I can jump in here. [Sorry for the length. This was meant to be a quicky but it grew!]

              In testing boolean expressions I prefer converting them to simple arithmetic expression rather than a series of IF - Than - Else trees. If you restrict the values of your logical variables to either zero or one you can take advantage of the common properties between arithmetic and logic systems and use arithmetic instead of if tests to evaluate logical expressions.

              Since zero is the identity element for addition and one is the identity element for multiplication and letting one equal true and zero equal false, one can map all logical operations and expressions onto equivalent arithmetic operations and expressions.

              Basic properties:
              =================
              Identity Elements: 0, 1 (Add, Mult) <==> False, True (OR, AND)
              Operators: Negation, Mult, Add, MOD <==> NOT, AND, OR, XOR
              Precedence: Negation=>Mult=>Add <==> NOT=>AND=>OR
              Distributive: I AND (J OR K) == (I AND J) OR (I AND K)
              Commutative: (I • J) == (J • I)
              Associative: (I • J • K) == (I • J) • K == I • (J • K)
              Where • = either OR or AND; Optional parentheses added for clarity

              Logical Identities († De Morgan's Laws)
              ========================================
              A OR False = A
              A AND TRUE = A
              NOT (A AND B) = (NOT A) OR (NOT B) †
              NOT (A OR B) = (NOT A) AND (NOT B) †
              (A XOR B) = (A AND NOT B) OR (NOT A AND B)

              Logical - Arithmetic Equivalents
              ================================
              A OR FALSE <==> A + 0 = A
              A AND TRUE <==> A * 1 = A
              A OR B <==> MAX (A, B)
              A AND B <==> A * B
              NOT A <==> (A + 1) MOD 2
              A XOR B <==> (A + B) MOD 2
              NOT A AND B <==> (MIN (A, B) + 1) MOD 2
              NOT A OR B <==> (MAX (A, B) + 1) MOD 2
              NOT A XOR B <==> ((A + B) Mod 2 + 1) MOD 2 == (A + B + 1) Mod 2

              [Hopefully Yahoo's reformatting doesn't bastardize those tables too much. See separate post and uploaded file for clips implementing each of the above seven non-trivial operations. These tables and more info is included in the uploaded cliplib.]

              Now, getting back to your original example, your simple conjunction:

              ^!If ^$Calc(MIN(^%A%;MIN(^%B;MIN(^%C%;MIN(^%D%;1-^%E%)))))$=1 Next Else Skip

              reduces to just the product of the variables:

              ^!If ^$Calc(^%A%*^%B*^%C%*^%D%*^%E%)$=1 Next Else Skip

              The analogous test for unions would simply be the sum of the variables compared to zero. However, for more complex expressions that doesn't work since using a sum operation for unions can result in values not contained in the set {0,1}. However, by using the above identities it is possible to transform any expression into a pure product expression (or other form), which might or might not simplify your code. For example:

              (A AND B AND C) OR (B AND NOT D)

              is equivalent to

              NOT (A AND B AND C) AND NOT (B AND NOT D)

              Note also that since the operations are commutative, associative and distributive, B may be "factored" out to make an equivalent expression (from the original):

              B AND ((A AND C) OR (NOT D))

              As you can see, you can play around with logical expressions just like we did with trig equations in HS to simplify (or to make them more complex).

              For specific applications you can write down and optimize the truth table (I forget what the name for the process is). This is done quite frequently for logic circuits as the optimization pays off in reduced components and gate delays. That may not be as beneficial for software. There is a formal process that guarantees an optimum result but is has been too many years to remember. Short of that just eye balling the truth table could reveal some useful reductions. For four input conditions it is only a 16 by 16 table. Or you could use the logic functions I will post later.

              All this is a perfect example for the need for Notetab to fully support custom functions. By fully support I mean supporting Far Functions and being usable in clipbar clips. Custom functions are very useful and handy tools. They can make the code easier to write and program flow much more transparent. They greatly reduce code size (at least by 50% where you can use them). Thanks to Ian Ntnerd's post last August there is a workaround for FarFunctions. However, custom functions still have one fatal deal-breaking (for me), drawback: They CANNOT be reliably used for any clipbar clips!

              •In Notetab, all variables are global but the clipbar uses a
              separate storage area
              •Variable values set in clipbook panel are not seen by clip
              bar clips & vice versa
              •Clipbar clip variables are not global across different clipbooks

              Perhaps if we make enough noise and we can get the no clipbar restriction removed. It would greatly enhance the clip functionality and ease coding efforts.

              Namaste', Art

              OK, this was bugging me so I had to look it up. Geesh. it's only been 40+ years. One shouldn't forget so soon!!!

              The process of optimizing a truth table is called a Karnaugh map
              http://en.wikipedia.org/wiki/Karnaugh_map
              The formal name for the Boolean identities above is De Morgan's laws
              http://en.wikipedia.org/wiki/De_Morgan%27s_laws

              Two other terms that you may want to look up are "Disjunctive Normal Form (DNF)" and its dual, the "Conjunctive Normal Form (CNF)".
              http://en.wikipedia.org/wiki/Disjunctive_normal_form
              http://en.wikipedia.org/wiki/Conjunctive_normal_form

              These are canonical forms for describing the truth table for a system. A DNF is a disjunction of conjunctive clauses, also known as an "OR of ANDs" or a "sum of products". A CNF is a conjunction of a disjunction of literals, also known as an "AND of ORs" or a "product of sums". Basically they are fully expanded forms that involve only one level of parentheses.
            • flo.gehrke
              ... Thanks for your explanations, Art! This is certainly a great help for users trying to go further into that topic. However, I would like to get back to my
              Message 6 of 12 , Sep 18, 2013
              • 0 Attachment
                --- In ntb-clips@yahoogroups.com, Art Kocsis <artkns@...> wrote:
                >
                > At 9/10/2013 05:11 PM, Flo wrote:
                >> It has been discussed several times that NT doesn't master Boolean
                >> Expressions (cf message #21773)...
                > Flo, If I can jump in here.(...)
                > In testing boolean expressions...

                Thanks for your explanations, Art!

                This is certainly a great help for users trying to go further into that topic.

                However, I would like to get back to my question concerning the specific concept that was introduced by Wayne VanWeerthuizen (where is he?) with his abovementioned 'NoteTab Tutorial Control Structures v003.OTL'...

                > Is anyone (also Wayne himself) still using such expressions and
                > could give us more examples. Regrettably, Wayne's Tutorial was
                > never finished and has remained a highly instructive fragment
                > only. Also, it's lacking complete working examples

                So far, Wayne gave us the solution for only five conditions.

                Given a simple list...

                A B
                A B C
                A C D
                B
                D E F

                we could test Wayne's five expressions against that list with the following clip...

                ^!Set %Lines%=^$GetTextLineCount$
                ^!Set %Row%=1
                ^!Goto ^?{(H=5)Find lines matching...==A AND B|A OR B|A NOT B|A XOR B|NOT A}

                :A AND B
                :Loop_1
                ^!Set %A%=0; %B%=0
                ^!Jump ^%Row%
                ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1
                ^!If ^$Calc(MIN(^%A%;^%B%))$=1 Next Else Skip
                ^!Set %Hits%=^%Hits%^$GetLine$^P
                ^!Inc %Row%
                ^!If ^$GetRow$ < ^%Lines% Loop_1
                ^!Info [L]Expression: A AND B^P^PMatches:^P^%Hits%
                ^!Goto Out

                :A OR B
                :Loop_2
                ^!Set %A%=0; %B%=0
                ^!Jump ^%Row%
                ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1
                ^!If ^$Calc(MAX(^%A%;^%B%))$=1 Next Else Skip
                ^!Set %Hits%=^%Hits%^$GetLine$^P
                ^!Inc %Row%
                ^!If ^$GetRow$ < ^%Lines% Loop_2
                ^!Info [L]Expression: A OR B^P^PMatches:^P^%Hits%
                ^!Goto Out

                :A NOT B
                :Loop_3
                ^!Set %A%=0; %B%=0
                ^!Jump ^%Row%
                ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1
                ^!If ^$Calc(MIN(^%A%;1-^%B%))$=1 Next Else Skip
                ^!Set %Hits%=^%Hits%^$GetLine$^P
                ^!Inc %Row%
                ^!If ^$GetRow$ < ^%Lines% Loop_3
                ^!Info [L]Expression: A NOT B^P^PMatches:^P^%Hits%
                ^!Goto Out

                :A XOR B
                :Loop_4
                ^!Set %A%=0; %B%=0
                ^!Jump ^%Row%
                ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1
                ^!If ^$Calc(ABS(^%A%-^%B%))$=1 Next Else Skip
                ^!Set %Hits%=^%Hits%^$GetLine$^P
                ^!Inc %Row%
                ^!If ^$GetRow$ < ^%Lines% Loop_4
                ^!Info [L]Expression: A XOR B^P^PMatches:^P^%Hits%
                ^!Goto Out

                :NOT A
                :Loop_5
                ^!Set %A%=0
                ^!Jump ^%Row%
                ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                ^!If ^$Calc(1-^%A%)$=1 Next Else Skip
                ^!Set %Hits%=^%Hits%^$GetLine$^P
                ^!Inc %Row%
                ^!If ^$GetRow$ < ^%Lines% Loop_5
                ^!Info [L]Expression: NOT A^P^PMatches:^P^%Hits%
                ^!Goto Out

                :Out
                ^!ClearVariables

                As far as I can see, the clip gets to correct results.

                Nevertheless, for me the question remains: Is there any way to enlarge Wayne's concept to conditions like 'A AND B AND NOT (E OR D)', for example? Or is there no way to get beyond the borders of those five conditions?


                Regards,
                Flo

                P.S. Regarding...

                > Too often help is solicited and answers posted with nary a word
                > of feedback or thanks. That is not a motivator for continuing
                > to offer help.

                How right you are.... :-(
              • joy8388608
                ... Thanks for your explanations, Art! This is certainly a great help for users trying to go further into that topic. However, I would like to get back to my
                Message 7 of 12 , Sep 19, 2013
                • 0 Attachment
                  >Nevertheless, for me the question remains: Is there any way to enlarge Wayne's concept to conditions like 'A AND B AND NOT (E OR D)', for example? Or is there no way to get beyond the borders of those five conditions?


                  I'm still not quite sure exactly what the desired end results of this topic is (subroutines? other way to write this type of code?) but here are my thoughts which might help. Sorry if I repeat what has been said before. You will find that I would try to avoid functions like MAX and MIN except for simply cases simply because the syntax gets messy so quickly.


                  Assume five vars A,B,C,D,E which have each been set to 0 (false) or 1 (true).

                  We want to manipulate the values to give an answer of 0 or 1.


                  A OR B OR C OR D OR E

                    MAX(A:B:C:D:E)

                    also equivalent to NOT( (NOT A) AND (NOT B) AND (NOT C) AND (NOT D) AND (NOT E)  )

                    which is equivalent to 1 - ( (1 - A) * (1 - B) * (1 - C) * (1 - D) * (1 - E) )


                    also equivalent to IfTrue (A+B+C+D+E) > 0


                  A AND B AND C AND D AND E

                    MIN(A;B;C;D;E)

                    also equivalent to A*B*C*D*E


                  NOT A

                    1-A


                  So, if I were to calculate A AND B AND NOT (E OR D), I would do

                    A * B * (1 - MAX(D:E)) since it is really ANDing three values.


                  It often (but not always) helps to create an equivalent logical statement.

                  For Example, A AND B AND NOT (D OR E) is the same as A AND B AND (NOT D) AND (NOT E) which equates to A * B * (1 - D) * (1 - E) which I like even better since it does away with the MAX and MIN functions with the error prone function syntax (all the dollar signs and nested parens).


                  I double checked this all on paper. Hope I didn't make any mistakes and that it is useful.


                  Joy




                   



                  --- In ntb-clips@yahoogroups.com, <flo.gehrke@...> wrote:

                  --- In ntb-clips@yahoogroups.com, Art Kocsis <artkns@...> wrote:
                  >
                  > At 9/10/2013 05:11 PM, Flo wrote:
                  >> It has been discussed several times that NT doesn't master Boolean
                  >> Expressions (cf message #21773)...
                  > Flo, If I can jump in here.(...)
                  > In testing boolean expressions...

                  Thanks for your explanations, Art!

                  This is certainly a great help for users trying to go further into that topic.

                  However, I would like to get back to my question concerning the specific concept that was introduced by Wayne VanWeerthuizen (where is he?) with his abovementioned 'NoteTab Tutorial Control Structures v003.OTL'...

                  > Is anyone (also Wayne himself) still using such expressions and
                  > could give us more examples. Regrettably, Wayne's Tutorial was
                  > never finished and has remained a highly instructive fragment
                  > only. Also, it's lacking complete working examples

                  So far, Wayne gave us the solution for only five conditions.

                  Given a simple list...

                  A B
                  A B C
                  A C D
                  B
                  D E F

                  we could test Wayne's five expressions against that list with the following clip...

                  ^!Set %Lines%=^$GetTextLineCount$
                  ^!Set %Row%=1
                  ^!Goto ^?{(H=5)Find lines matching...==A AND B|A OR B|A NOT B|A XOR B|NOT A}

                  :A AND B
                  :Loop_1
                  ^!Set %A%=0; %B%=0
                  ^!Jump ^%Row%
                  ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                  ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1
                  ^!If ^$Calc(MIN(^%A%;^%B%))$=1 Next Else Skip
                  ^!Set %Hits%=^%Hits%^$GetLine$^P
                  ^!Inc %Row%
                  ^!If ^$GetRow$ < ^%Lines% Loop_1
                  ^!Info [L]Expression: A AND B^P^PMatches:^P^%Hits%
                  ^!Goto Out

                  :A OR B
                  :Loop_2
                  ^!Set %A%=0; %B%=0
                  ^!Jump ^%Row%
                  ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                  ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1
                  ^!If ^$Calc(MAX(^%A%;^%B%))$=1 Next Else Skip
                  ^!Set %Hits%=^%Hits%^$GetLine$^P
                  ^!Inc %Row%
                  ^!If ^$GetRow$ < ^%Lines% Loop_2
                  ^!Info [L]Expression: A OR B^P^PMatches:^P^%Hits%
                  ^!Goto Out

                  :A NOT B
                  :Loop_3
                  ^!Set %A%=0; %B%=0
                  ^!Jump ^%Row%
                  ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                  ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1
                  ^!If ^$Calc(MIN(^%A%;1-^%B%))$=1 Next Else Skip
                  ^!Set %Hits%=^%Hits%^$GetLine$^P
                  ^!Inc %Row%
                  ^!If ^$GetRow$ < ^%Lines% Loop_3
                  ^!Info [L]Expression: A NOT B^P^PMatches:^P^%Hits%
                  ^!Goto Out

                  :A XOR B
                  :Loop_4
                  ^!Set %A%=0; %B%=0
                  ^!Jump ^%Row%
                  ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                  ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1
                  ^!If ^$Calc(ABS(^%A%-^%B%))$=1 Next Else Skip
                  ^!Set %Hits%=^%Hits%^$GetLine$^P
                  ^!Inc %Row%
                  ^!If ^$GetRow$ < ^%Lines% Loop_4
                  ^!Info [L]Expression: A XOR B^P^PMatches:^P^%Hits%
                  ^!Goto Out

                  :NOT A
                  :Loop_5
                  ^!Set %A%=0
                  ^!Jump ^%Row%
                  ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                  ^!If ^$Calc(1-^%A%)$=1 Next Else Skip
                  ^!Set %Hits%=^%Hits%^$GetLine$^P
                  ^!Inc %Row%
                  ^!If ^$GetRow$ < ^%Lines% Loop_5
                  ^!Info [L]Expression: NOT A^P^PMatches:^P^%Hits%
                  ^!Goto Out

                  :Out
                  ^!ClearVariables

                  As far as I can see, the clip gets to correct results.

                  Nevertheless, for me the question remains: Is there any way to enlarge Wayne's concept to conditions like 'A AND B AND NOT (E OR D)', for example? Or is there no way to get beyond the borders of those five conditions?


                  Regards,
                  Flo

                  P.S. Regarding...

                  > Too often help is solicited and answers posted with nary a word
                  > of feedback or thanks. That is not a motivator for continuing
                  > to offer help.

                  How right you are.... :-(
                • flo.gehrke
                  Joy, ... As I wrote, so far, Wayne gave us five expressions... Boolean -- Wayne s equivalent ... A AND B -- ^$Calc(MIN(A;B))$=1 A OR B --
                  Message 8 of 12 , Sep 19, 2013
                  • 0 Attachment
                    Joy,

                    > I'm still not quite sure exactly what the desired end results of
                    > this topic is (subroutines? other way to write this type of code?)

                    As I wrote, so far, Wayne gave us five expressions...

                    Boolean --> Wayne's equivalent
                    -------------------------------
                    A AND B --> ^$Calc(MIN(A;B))$=1
                    A OR B --> ^$Calc(MAX(A;B))$=1
                    A NOT B --> ^$Calc(MIN(A;1-B))$=1
                    A XOR B --> ^$Calc(ABS(A-B))$=1
                    NOT A --> ^$Calc(1-A)$=1

                    See my clip as an example how to make use of these expressions -- if I understand Wayne's concept correctly.

                    So my simple question is: Could anyone give me, say, four or five more "Waynean expressions" like that for executing even more complicated Boolean expressions? And best show us how to test them against the list...

                    A B
                    A B C
                    A C D
                    B
                    D E F

                    For example: What is the "Waynean expression" to be used with my clip in order to match lines where 'A NOT (B OR C)' is true? Or '(C OR D) AND NOT A' etc...

                    > You will find that I would try to avoid functions like MAX and
                    > MIN except for simply cases simply because the syntax gets
                    > messy so quickly.

                    Are we free to "avoid" these functions here? I think they are a basic element of Wayne's concept. 'A NOT B', for example, says: If A is true and if B is true then 'A NOT B' is true if ^$Calc(MIN(A;1-B))$=1. So I can't see how your calculations like...

                    > IfTrue (A+B+C+D+E) > 0
                    > MIN(A;B;C;D;E)
                    > also equivalent to A*B*C*D*E

                    could conform with Wayne's concept. I think ^$Calc is just used for sequentially testing for 0 or 1 (true or false) here.

                    Regards,
                    Flo
                  • Art Kocsis
                    Sorry, another long post. But there s a lot to cover. On Wed 11 Sep 2013 08:10:08 -0700 Flo said: ...what matters here is this specific approach which - as
                    Message 9 of 12 , Sep 19, 2013
                    • 0 Attachment
                      Sorry, another long post. But there's a lot to cover.

                      On Wed 11 Sep 2013 08:10:08 -0700 Flo said:
                      "...what matters here is this specific approach which - as Wayne explained -
                      could apply to much more complex queries (with AND, OR, XOR, NOT etc). In
                      cases like that, it would be difficult to use RegEx, and compound loops
                      would end in extremely long "IF, ELSE IF, ELSE IF Chains" (Wayne)."

                      On Thu, 19 Sep 2013 03:52:04 -0000 Flo said:
                      "Nevertheless, for me the question remains: Is there any way to enlarge Wayne's
                      concept to conditions like 'A AND B AND NOT (E OR D)', for example? Or is there
                      no way to get beyond the borders of those five conditions?"

                      BTW Five???  I only see four: NOT, OR, AND, XOR. And those are operators,
                      not conditions. What am I missing>
                      #############################################

                      Flo, I think what you are asking is: given the absence of logical operators
                      in Notetab Clip Code, how can I generalize the use of arithmetic operators
                      to apply them to complex logical expressions without obtuse and lengthy
                      If - Then - Else trees.

                      The answer has two parts:
                        1: The mapping of the logical operations to arithmetical operations
                        2: The transformation of complex logical expressions into canonical form

                      Regarding #1, there are a number of different mapping of logical to arithmetical
                      operations as Wayne and I have discussed and with no major standouts among them.
                      They all suffer from the inherent limitation of being strictly binary operations
                      in Notetab, (i.e., MAX (A,B,C,D...) is not allowed). To recap two mappings:

                      Operation             Addition only            Allowing Subtraction
                      ============          ======================   =====================
                        NOT A        <==>   (A + 1) MOD 2             (1 - A)
                      A AND B        <==>   A * B                     MIN (A, B)
                      A OR  B        <==>   MAX (A, B)                MAX (A, B)
                      A XOR B        <==>   (A + B) MOD 2             ABS (A-B)
                      NOT A AND B    <==>   (MIN (A, B) + 1) MOD 2    1 - MIN (A,B)
                      NOT A OR  B    <==>   (MAX (A, B) + 1) MOD 2    1 - MAX (A,B)
                      NOT A XOR B    <==>   (A + B + 1) MOD 2         1 - ABS (A-B)

                      Regarding #2 as Joy and I discussed, any logical expression can be transformed
                      into an equivalent DNF (an OR of ANDs), or CNF (an AND of ORs), expression. These
                      canonical expressions use only the three logical operators: NOT, AND and OR.

                      You can do that transform either by a series of transformations using
                      DeMorgan's laws or - easier for very complicated expressions - by using truth tables. Each row in a truth table is a conjunction (AND) of the state of the columns (conditions). The disjunction (OR) of all the rows resulting in a true (=1) state is the DNF (Disjunctive Normal Form) of the system. For example:

                          ##  A B C D E   X     Y1  Y2  Y3    Y     DNF Term
                          ==  = = = = =   =     ==  ==  ==    =     ======================
                          01  0 0 x 0 0   0     0   0   0     0    
                          02  0 0 x 0 1   0     0   0   0     0    
                          03  0 0 x 1 0   0     0   0   1     1     ¬A AND ¬B AND D AND ¬E
                          04  0 0 x 1 1   0     0   0   0     0
                          05  0 1 x 0 0   0     0   0   1     1     ¬A AND B AND ¬D AND ¬E
                          06  0 1 x 0 1   0     0   1   0     1     ¬A AND B AND ¬D AND E
                          07  0 1 x 1 0   0     0   1   1     1     ¬A AND B AND D AND ¬E
                          08  0 1 x 1 1   0     0   0   0     0    
                          09  1 0 x 0 0   0     0   0   0     0    
                          10  1 0 x 0 1   0     0   0   0     0    
                          11  1 0 x 1 0   0     0   0   0     0    
                          12  1 0 x 1 1   0     0   0   0     0    
                          13  1 1 x 0 0   1     1   0   0     1     A AND B AND ¬D AND ¬E
                          14  1 1 x 0 1   0     0   0   0     0    
                          15  1 1 x 1 0   0     0   0   0     0    
                          16  1 1 x 1 1   0     0   0   0     0    

                      For instance, taking your example, A AND B AND NOT (E OR D), (Col X),
                      the DNF form for X is simply row 13: X = A AND B AND ¬D AND ¬E
                      (where ¬ is the NOT operator). That seems like a lot of work compared
                      to the trivial DeMorgan transformation but this is meant to illustrate
                      a process so let's add some complication:

                      Let Y = [A AND B AND NOT (E OR D)]
                                 OR {¬A AND [B AND (¬D OR E) OR B AND (D OR ¬E)]}
                                 OR [(¬A AND ¬E AND (B OR D)]
                            = Y1 OR Y2 OR Y3

                      Where Y1 = A AND B AND NOT (E OR D)
                            Y2 = ¬A AND [B AND (¬D OR E) OR B AND (D OR ¬E)]
                            Y3 = (¬A AND ¬E AND (B OR D)

                      The Y column is the conjunction of the Y1, Y2 and Y3 columns and the final DNF
                      expression is just the OR (Sum), of the Y rows with true values:

                      Y = R3 OR R5 OR R6 OR R7 OR R13
                        = (¬A AND ¬B AND D AND ¬E) OR (¬A AND B AND ¬D AND ¬E) OR (¬A AND B AND ¬D AND E)
                               OR (¬A AND B AND D AND ¬E) OR (A AND B AND ¬D AND ¬E)

                      This logical expression can now be evaluated in six clear and easily followed steps,
                      none of which involve an If test:
                         Evaluate each of the five row expressions using the canonical AND operations
                         Evaluate the final result using the canonical OR operation on those five results.

                      Alternatively, the expression could be coded directly using my functions. I did find
                      it necessary to first transform the expression from embedded binary notation to prefix
                      notation. Even then I had to be very careful not to introduce an error. I could then
                      use NTB's replace dialog to convert to Clip syntax. Without a parser to analyze and
                      convert an arbitrary expression with nested parentheses to Notetab format it still is
                      a bit tricky. The functions work well for short or medium complexity expressions but
                      a truth table is easier and more reliable for anything more complex.

                      Y1 = and(A,B,¬or(E,D))
                      Y2 = and(¬A,¬E,or(B,D))
                      Y3 = and(¬A,or(and(B,or(¬D,E)),and(B,or(D,¬E))))

                      ^!Set %Y1%^$AND(^%A%,^%B%,^$NOR(^%E%,^%D%)$)$
                      ^!Set %Y2%^$AND(^$NOT(^%A%)$$,^$NOT(^%E%)$$,^$OR(^%B%,^%D%)$)$
                      ^!Set %Y3%^$AND(^$NOT(^%A%)$$,^$OR(^$AND(^%B%,^$OR(^$NOT(^%D%)$$,^%E%)$)$,^$AND(^%B%,^$OR(^%D%,^$NOT(^%E%)$$)$)$
                      ^!Set %Y%=^$OR(^%Y1%;^%Y2%;^%Y3%)$


                      Some things to notice/consider:
                      • The astute reader will notice that Y2 is equivalent to ¬A AND B AND (D XOR E)
                           However, remember we are limiting ourselves to NOT, AND and OR operators.
                      • Separating the terms into partial result columns makes it easier and less
                           error prone to generate the truth table.
                      • There can be some overlap in the partial results (e.g., row 7, col Y2 and Y3)
                      • The growth of terms (and complexity) is linear, not exponential
                      • Changes to the system criteria (truth table), are easily and fairly reliably
                           propagated to the DNF expression terms (this is much, much less error prone
                           than If - Then - Else logic trees.
                      • Additional columns can easily be added to record the results of alternate
                           logical expressions using the same worksheet and input parameters states.
                      • The truth table is independent and external to any program language or code.
                           It is simply prep work prior to program implementation.
                      • A truth table is easy to generate, easy to understand and concise in execution
                      • Most important, using a truth table to analyze and code logic expressions is
                           the most reliable and least error prone method available.

                      OTOH, Trying to implement complex expressions by means of If - Then - Else
                      trees is a recipe for frustration and errors. Clear computation and  program
                      flow is a basic requirement for generating error free code as well for
                      downstream maintainability. The VanWeerthuizenian Expressions get very messy
                      very, very quickly once you go beyond the trivial two parameter, binary
                      condition unless you restrict yourself to canonical forms. This is primarily
                      due to the restriction of the MAX and MIN functions to two operands. That is
                      why I removed that restriction from my AND and OR functions. However, in
                      canonical form the benefit of my functions is much less dramatic than I expected.

                      For example for R3 = ¬A AND ¬B AND D AND ¬E

                      ^!Set %R3%=^$Calc(min((1-^%A%),min((1-^%B%),min(^%D%,(1-^%E%))));0)$
                      vs
                      ^!Set %R3%=^$AND(^$NOT(^%A%)$;^$NOT(^%B%)$;^%D%;^$NOT(^%E%)$)$

                      I think the functions are clearer and less error prone than all the nested
                      parentheses and remembering the correct mappings but not earth shakingly so.

                      However, the major point and lesson here is the transformation to DNF
                      form. Whether you use the VanWeerthuizenian constructs or my functions,
                      the best path to error free coding and ease of maintenance is to transform
                      your test criteria into canonical form using a single variable for each
                      criteria, generate the DNF expression (by either Boolean transformations
                      or via a truth table), and then evaluate the resulting products and sums.
                      Do not use an If test until the final result.


                      Applying this paradigm to your example:

                      {A AND B|A OR B|A NOT B|A XOR B|NOT A}

                      Let Y1 = A AND B; Y2 = A OR B; Y3 = A NOT B; Y4 = A XOR B; Y5 = NOT A

                      The truth table is:

                      #  A  B  Y1  Y2  Y3  Y4  Y5
                      =  =  =  ==  ==  ==  ==  ==
                      1  0  0  0   0   0   0   1
                      2  0  1  0   1   0   1   1
                      3  1  0  0   1   1   1   0
                      4  1  1  1   1   0   0   0

                      And the DNFs for the five cases are:

                      Y1 = A AND B
                      Y2 = A OR B
                      Y3 = A AND ¬B
                      Y4 = ¬A AND B OR A AND ¬B
                      Y5 = ¬A

                      It doesn't seem like we gained much but yours is a fairly trivial test and
                      remember, I am illustrating a generalized process, not content.
                      Implementing this in a clip:
                      ;######################### Start of Clip Code ###############################
                      ;^!SetDebug On
                      ^!Set %Lines%=^$GetTextLineCount$
                      ^!Set %Row%=1; %Hits%=^%Empty%
                      ^!Set %Case%=^?{(H=5)Find lines matching...==_A AND B|A OR B|A NOT B|A XOR B|NOT A}

                      :Loop
                      ^!Jump ^%Row%
                      ^!Set %A%=0; %B%=0; %Y%=0
                      ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                      ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1

                      ^!Set %Y1%=^$Calc(MIN(^%A%;^%B%))$
                      ^!Set %Y2%=^$Calc(MAX(^%A%;^%B%))$
                      ^!Set %Y3%=^$Calc(MIN(^%A%;1-^%B%))$
                      ^!Set %Y41%=^$Calc(MIN(1-^%A%;^%B%))$
                      ^!Set %Y42%=^$Calc(MIN(^%A%;1-^%B%))$
                      ^!Set %Y4%=^$Calc(MAX(^%Y41%;^%Y42%))$
                      ^!Set %Y5%=^$Calc(1-^%A%)$

                      ^!IfMatch "^%Case%" "A AND B" ^!Set %Y%=^%Y1%
                      ^!IfMatch "^%Case%" "A OR B" ^!Set %Y%=^%Y2%
                      ^!IfMatch "^%Case%" "A NOT B" ^!Set %Y%=^%Y3%
                      ^!IfMatch "^%Case%" "A XOR B" ^!Set %Y%=^%Y4%
                      ^!IfMatch "^%Case%" "NOT A" ^!Set %Y%=^%Y5%

                      ^!IfTrue ^%Y% ^!Set %Hits%=^%Hits%^$GetLine$^P
                      ^!Inc %Row%
                      ^!If ^$GetRow$ < ^%Lines% Loop
                      ^!Info [L]Expression: ^%Case%^P^PMatches:^P^%Hits%

                      ^!GoTo End

                      ;Alternate set of logic expression calculations
                      ^!Set %Y1%=^$AND(^%A%;^%B%)$
                      ^!Set %Y2%=^$OR(%A%;^%B%)$
                      ^!Set %Y3%=^$AND(^%A%;^$NOT(^%B%)$)$
                      ^!Set %Y41%=^$AND(^$NOT(^%A%);^%B%)$;)$
                      ^!Set %Y42%=^$AND(^%A%;^$NOT(^%B%)$)$
                      ^!Set %Y4%=^$OR(^%Y41%;^%Y42%)$
                      ^!Set %Y5%=^$NOT(^%A%)$
                      ;######################### End of Clip Code ###############################

                      This, of course, could be rearranged to use your computed GoTos, the DNF
                      computations could be moved to the %case% tests with only %Y41% and %Y42%
                      pre-computed or other optimizations which might or might not be significant
                      depending on the application but would probably be at the cost of clarity
                      and generalization. Remember, the emphasis here is on clarity of program
                      flow (primarily linear), to minimize coding errors and to ease maintenance.
                      The various sections are segregated, similar operations are consolidated, and
                      program branches are minimized. A flow chart of this clip would not have any
                      crossed lines.

                      I hope this answers your questions.  Art
                    • joy8388608
                      Hi Art. Uh, wow. Just... wow. I wish I had time to look through your post in detail to see if it covers what I just logged on to post. But I don t so, again,
                      Message 10 of 12 , Sep 20, 2013
                      • 0 Attachment

                        Hi Art. 


                        Uh, wow. Just... wow. I wish I had time to look through your post in detail to see if it covers what I just logged on to post. But I don't so, again, sorry if I repeat.


                        I did notice something that seems to me to be incorrect but I did not have time to see if it was a one time thing or was repeated.


                        In your first table, you have

                        NOT A AND B    <==>   (MIN (A, B) + 1) MOD 2    1 - MIN (A,B)   and

                        NOT A OR  B    <==>   (MAX (A, B) + 1) MOD 2    1 - MAX (A,B)


                        Order of operations are NOT then AND then OR 

                        http://en.wikipedia.org/wiki/Logical_connective#Order_of_precedence

                        so NOT A AND B is really (NOT A)  AND B but your third column interprets it as NOT (A AND B).

                        Anyway, what I was going to say to Flo is this...

                        I think I now see what you are really asking and I think not quite understanding. You want to find out how to do this Wayne's way and I'm saying this is a big mistake except for the simplest of cases. The second thing I'm not sure you see is that the way I'm showing is equivalent and simpler for complicated cases - easier to read, write and understand. The third point is that it seems like you are looking for a step by step method of converting logic into code. I say every case is different and sometimes Wayne's way is fine, sometimes my way is better and sometimes a combination of both is the best way. The key is to learn how to convert logical statements into the easiest form to work with and do away with MAX and MIN when possible. In other words, use my way. :)  Example. A OR NOT(C AND D) is the same as A OR NOT C OR NOT D.

                        Here are real clips to show your simple case of A NOT B which I am interpreting as A AND NOT B which is really A AND (NOT B). In this one, Wayne's way is fine since it is simple enough.

                        The second clip is for A NOT (B OR C) which I'm reading as A AND NOT (B OR C). It took me a few tries to get the parens matched up with the MINs and MAXs for even this simple case. Add a few conditions or more variables and it's a mess.

                        Note my use of an actual test for If A=1 AND B=1 AND C=1 AND D=1 AND E=1 in both clips. I also designed the clips for up to 5 vars so the output has extra lines for simpler cases. Just ignore them.

                        I think you will see the results are the same and why I like my way better.

                        You can modify these clips to test your own stuff. I'd be happy to try to help if you want to see the way I would code a specific case. Every test is different and people see things in different ways. Obviously, if it's code that only you see and you see it one way better than another and it works... no problem.

                        Joy

                        ^!InsertText Testing A AND NOT B^%NL%^%NL%

                        ^!Set %A%=0;%B%=0;%C%=0;%D%=0;%E%=0
                        ^!Set %Meth1%="Calc(MIN(A;(1 - B)))"
                        ^!Set %Meth2%="Calc(A * (1 - B))"
                        ;^!Set %Meth3%="Calc(A * (1 - B) * (1 - C))"
                        ^!InsertText Method 1 is ^%Meth1%^%NL%Method 2 is ^%Meth2%^%NL%Method 3 is ^%Meth3%^%NL%^%NL%

                        :AGAIN
                        ^!Set %M1%=^$Calc(MIN(^%A%;(1 - ^%B%)))$
                        ^!Set %M2%=^$Calc(^%A% * (1 - ^%B%))$
                        ;^!Set %M3%=^$Calc()$
                        ^!InsertText A B C D E = ^%A% ^%B% ^%C% ^%D% ^%E%  Method1,2,3 gives ^%M1%  ^%M2%  ^%M3%^%NL%

                        ; Note the test of If A=1 AND B=1 AND C=1 AND D=1 AND E=1
                        ^!IfTrue ^$Calc(^%A%*^%B%*^%C%*^%D%*^%E%)$ ^!Goto DONE
                        ^!Inc %A%
                        ^!If ^%A%=1 AGAIN
                        ^!Set %A%=0
                        ^!Inc %B%
                        ^!If ^%B%=1 AGAIN
                        ^!Set %B%=0
                        ^!Inc %C%
                        ^!If ^%C%=1 AGAIN
                        ^!Set %C%=0
                        ^!Inc %D%
                        ^!If ^%D%=1 AGAIN
                        ^!Set %D%=0
                        ^!Inc %E%
                        ^!If ^%E%=1 AGAIN

                        :DONE
                        ^!Jump TEXT_START
                        ^!ClearVariable %A%
                        ^!ClearVariable %B%
                        ^!ClearVariable %C%
                        ^!ClearVariable %D%
                        ^!ClearVariable %E%
                        ^!ClearVariable %M1%
                        ^!ClearVariable %M2%
                        ^!ClearVariable %M3%
                        ^!ClearVariable %METH1%
                        ^!ClearVariable %METH2%
                        ^!ClearVariable %METH3%


                        <--->

                        Testing A AND NOT B

                        Method 1 is Calc(MIN(A;(1 - B)))
                        Method 2 is Calc(A * (1 - B))
                        Method 3 is 

                        A B C D E = 0 0 0 0 0  Method1,2,3 gives 0  0  
                        A B C D E = 1 0 0 0 0  Method1,2,3 gives 1  1  
                        A B C D E = 0 1 0 0 0  Method1,2,3 gives 0  0  
                        A B C D E = 1 1 0 0 0  Method1,2,3 gives 0  0  
                        A B C D E = 0 0 1 0 0  Method1,2,3 gives 0  0  
                        A B C D E = 1 0 1 0 0  Method1,2,3 gives 1  1  
                        A B C D E = 0 1 1 0 0  Method1,2,3 gives 0  0  
                        A B C D E = 1 1 1 0 0  Method1,2,3 gives 0  0  
                        A B C D E = 0 0 0 1 0  Method1,2,3 gives 0  0  
                        A B C D E = 1 0 0 1 0  Method1,2,3 gives 1  1  
                        A B C D E = 0 1 0 1 0  Method1,2,3 gives 0  0  
                        A B C D E = 1 1 0 1 0  Method1,2,3 gives 0  0  
                        A B C D E = 0 0 1 1 0  Method1,2,3 gives 0  0  
                        A B C D E = 1 0 1 1 0  Method1,2,3 gives 1  1  
                        A B C D E = 0 1 1 1 0  Method1,2,3 gives 0  0  
                        A B C D E = 1 1 1 1 0  Method1,2,3 gives 0  0  
                        A B C D E = 0 0 0 0 1  Method1,2,3 gives 0  0  
                        A B C D E = 1 0 0 0 1  Method1,2,3 gives 1  1  
                        A B C D E = 0 1 0 0 1  Method1,2,3 gives 0  0  
                        A B C D E = 1 1 0 0 1  Method1,2,3 gives 0  0  
                        A B C D E = 0 0 1 0 1  Method1,2,3 gives 0  0  
                        A B C D E = 1 0 1 0 1  Method1,2,3 gives 1  1  
                        A B C D E = 0 1 1 0 1  Method1,2,3 gives 0  0  
                        A B C D E = 1 1 1 0 1  Method1,2,3 gives 0  0  
                        A B C D E = 0 0 0 1 1  Method1,2,3 gives 0  0  
                        A B C D E = 1 0 0 1 1  Method1,2,3 gives 1  1  
                        A B C D E = 0 1 0 1 1  Method1,2,3 gives 0  0  
                        A B C D E = 1 1 0 1 1  Method1,2,3 gives 0  0  
                        A B C D E = 0 0 1 1 1  Method1,2,3 gives 0  0  
                        A B C D E = 1 0 1 1 1  Method1,2,3 gives 1  1  
                        A B C D E = 0 1 1 1 1  Method1,2,3 gives 0  0  
                        A B C D E = 1 1 1 1 1  Method1,2,3 gives 0  0  


                        <--->

                        ^!InsertText Testing A AND NOT (B OR C)^%NL%^%NL%

                        ^!Set %A%=0;%B%=0;%C%=0;%D%=0;%E%=0
                        ^!Set %Meth1%="Calc(MIN(A;(1 - MAX(B;C))))"
                        ^!Set %Meth2%="Calc(A * (1 - MAX(B;C)))"
                        ^!Set %Meth3%="Calc(A * (1 - B) * (1 - C))"
                        ^!InsertText Method 1 is ^%Meth1%^%NL%Method 2 is ^%Meth2%^%NL%Method 3 is ^%Meth3%^%NL%^%NL%

                        :AGAIN
                        ^!Set %M1%=^$Calc(MIN(^%A%;(1 - MAX(^%B%;^%C%))))$
                        ^!Set %M2%=^$Calc(^%A% * (1 - MAX(^%B%;^%C%)))$
                        ^!Set %M3%=^$Calc(^%A% * (1 - ^%B%) * (1 - ^%C%))$
                        ^!InsertText A B C D E = ^%A% ^%B% ^%C% ^%D% ^%E%  Method1,2,3 gives ^%M1%  ^%M2%  ^%M3%^%NL%

                        ; Note the test of If A=1 AND B=1 AND C=1 AND D=1 AND E=1
                        ^!IfTrue ^$Calc(^%A%*^%B%*^%C%*^%D%*^%E%)$ ^!Goto DONE
                        ^!Inc %A%
                        ^!If ^%A%=1 AGAIN
                        ^!Set %A%=0
                        ^!Inc %B%
                        ^!If ^%B%=1 AGAIN
                        ^!Set %B%=0
                        ^!Inc %C%
                        ^!If ^%C%=1 AGAIN
                        ^!Set %C%=0
                        ^!Inc %D%
                        ^!If ^%D%=1 AGAIN
                        ^!Set %D%=0
                        ^!Inc %E%
                        ^!If ^%E%=1 AGAIN

                        :DONE
                        ^!Jump TEXT_START
                        ^!ClearVariable %A%
                        ^!ClearVariable %B%
                        ^!ClearVariable %C%
                        ^!ClearVariable %D%
                        ^!ClearVariable %E%
                        ^!ClearVariable %M1%
                        ^!ClearVariable %M2%
                        ^!ClearVariable %M3%
                        ^!ClearVariable %METH1%
                        ^!ClearVariable %METH2%
                        ^!ClearVariable %METH3%


                        <--->

                        Testing A AND NOT(B OR C)

                        Method 1 is Calc(MIN(A;(1 - MAX(B;C))))
                        Method 2 is Calc(A * (1 - MAX(B;C)))
                        Method 3 is Calc(A * (1 - B) * (1 - C))

                        A B C D E = 0 0 0 0 0  Method1,2,3 gives 0  0  0
                        A B C D E = 1 0 0 0 0  Method1,2,3 gives 1  1  1
                        A B C D E = 0 1 0 0 0  Method1,2,3 gives 0  0  0
                        A B C D E = 1 1 0 0 0  Method1,2,3 gives 0  0  0
                        A B C D E = 0 0 1 0 0  Method1,2,3 gives 0  0  0
                        A B C D E = 1 0 1 0 0  Method1,2,3 gives 0  0  0
                        A B C D E = 0 1 1 0 0  Method1,2,3 gives 0  0  0
                        A B C D E = 1 1 1 0 0  Method1,2,3 gives 0  0  0
                        A B C D E = 0 0 0 1 0  Method1,2,3 gives 0  0  0
                        A B C D E = 1 0 0 1 0  Method1,2,3 gives 1  1  1
                        A B C D E = 0 1 0 1 0  Method1,2,3 gives 0  0  0
                        A B C D E = 1 1 0 1 0  Method1,2,3 gives 0  0  0
                        A B C D E = 0 0 1 1 0  Method1,2,3 gives 0  0  0
                        A B C D E = 1 0 1 1 0  Method1,2,3 gives 0  0  0
                        A B C D E = 0 1 1 1 0  Method1,2,3 gives 0  0  0
                        A B C D E = 1 1 1 1 0  Method1,2,3 gives 0  0  0
                        A B C D E = 0 0 0 0 1  Method1,2,3 gives 0  0  0
                        A B C D E = 1 0 0 0 1  Method1,2,3 gives 1  1  1
                        A B C D E = 0 1 0 0 1  Method1,2,3 gives 0  0  0
                        A B C D E = 1 1 0 0 1  Method1,2,3 gives 0  0  0
                        A B C D E = 0 0 1 0 1  Method1,2,3 gives 0  0  0
                        A B C D E = 1 0 1 0 1  Method1,2,3 gives 0  0  0
                        A B C D E = 0 1 1 0 1  Method1,2,3 gives 0  0  0
                        A B C D E = 1 1 1 0 1  Method1,2,3 gives 0  0  0
                        A B C D E = 0 0 0 1 1  Method1,2,3 gives 0  0  0
                        A B C D E = 1 0 0 1 1  Method1,2,3 gives 1  1  1
                        A B C D E = 0 1 0 1 1  Method1,2,3 gives 0  0  0
                        A B C D E = 1 1 0 1 1  Method1,2,3 gives 0  0  0
                        A B C D E = 0 0 1 1 1  Method1,2,3 gives 0  0  0
                        A B C D E = 1 0 1 1 1  Method1,2,3 gives 0  0  0
                        A B C D E = 0 1 1 1 1  Method1,2,3 gives 0  0  0
                        A B C D E = 1 1 1 1 1  Method1,2,3 gives 0  0  0

                        Joy


                        --- In ntb-clips@yahoogroups.com, <artkns@...> wrote:

                        Sorry, another long post. But there's a lot to cover.

                        On Wed 11 Sep 2013 08:10:08 -0700 Flo said:
                        "...what matters here is this specific approach which - as Wayne explained -
                        could apply to much more complex queries (with AND, OR, XOR, NOT etc). In
                        cases like that, it would be difficult to use RegEx, and compound loops
                        would end in extremely long "IF, ELSE IF, ELSE IF Chains" (Wayne)."

                        On Thu, 19 Sep 2013 03:52:04 -0000 Flo said:
                        "Nevertheless, for me the question remains: Is there any way to enlarge Wayne's
                        concept to conditions like 'A AND B AND NOT (E OR D)', for example? Or is there
                        no way to get beyond the borders of those five conditions?"

                        BTW Five???  I only see four: NOT, OR, AND, XOR. And those are operators,
                        not conditions. What am I missing>
                        #############################################

                        Flo, I think what you are asking is: given the absence of logical operators
                        in Notetab Clip Code, how can I generalize the use of arithmetic operators
                        to apply them to complex logical expressions without obtuse and lengthy
                        If - Then - Else trees.

                        The answer has two parts:
                          1: The mapping of the logical operations to arithmetical operations
                          2: The transformation of complex logical expressions into canonical form

                        Regarding #1, there are a number of different mapping of logical to arithmetical
                        operations as Wayne and I have discussed and with no major standouts among them.
                        They all suffer from the inherent limitation of being strictly binary operations
                        in Notetab, (i.e., MAX (A,B,C,D...) is not allowed). To recap two mappings:

                        Operation             Addition only            Allowing Subtraction
                        ============          ======================   =====================
                          NOT A        <==>   (A + 1) MOD 2             (1 - A)
                        A AND B        <==>   A * B                     MIN (A, B)
                        A OR  B        <==>   MAX (A, B)                MAX (A, B)
                        A XOR B        <==>   (A + B) MOD 2             ABS (A-B)
                        NOT A AND B    <==>   (MIN (A, B) + 1) MOD 2    1 - MIN (A,B)
                        NOT A OR  B    <==>   (MAX (A, B) + 1) MOD 2    1 - MAX (A,B)
                        NOT A XOR B    <==>   (A + B + 1) MOD 2         1 - ABS (A-B)

                        Regarding #2 as Joy and I discussed, any logical expression can be transformed
                        into an equivalent DNF (an OR of ANDs), or CNF (an AND of ORs), expression. These
                        canonical expressions use only the three logical operators: NOT, AND and OR.

                        You can do that transform either by a series of transformations using
                        DeMorgan's laws or - easier for very complicated expressions - by using truth tables. Each row in a truth table is a conjunction (AND) of the state of the columns (conditions). The disjunction (OR) of all the rows resulting in a true (=1) state is the DNF (Disjunctive Normal Form) of the system. For example:

                            ##  A B C D E   X     Y1  Y2  Y3    Y     DNF Term
                            ==  = = = = =   =     ==  ==  ==    =     ======================
                            01  0 0 x 0 0   0     0   0   0     0    
                            02  0 0 x 0 1   0     0   0   0     0    
                            03  0 0 x 1 0   0     0   0   1     1     ¬A AND ¬B AND D AND ¬E
                            04  0 0 x 1 1   0     0   0   0     0
                            05  0 1 x 0 0   0     0   0   1     1     ¬A AND B AND ¬D AND ¬E
                            06  0 1 x 0 1   0     0   1   0     1     ¬A AND B AND ¬D AND E
                            07  0 1 x 1 0   0     0   1   1     1     ¬A AND B AND D AND ¬E
                            08  0 1 x 1 1   0     0   0   0     0    
                            09  1 0 x 0 0   0     0   0   0     0    
                            10  1 0 x 0 1   0     0   0   0     0    
                            11  1 0 x 1 0   0     0   0   0     0    
                            12  1 0 x 1 1   0     0   0   0     0    
                            13  1 1 x 0 0   1     1   0   0     1     A AND B AND ¬D AND ¬E
                            14  1 1 x 0 1   0     0   0   0     0    
                            15  1 1 x 1 0   0     0   0   0     0    
                            16  1 1 x 1 1   0     0   0   0     0    

                        For instance, taking your example, A AND B AND NOT (E OR D), (Col X),
                        the DNF form for X is simply row 13: X = A AND B AND ¬D AND ¬E
                        (where ¬ is the NOT operator). That seems like a lot of work compared
                        to the trivial DeMorgan transformation but this is meant to illustrate
                        a process so let's add some complication:

                        Let Y = [A AND B AND NOT (E OR D)]
                                   OR {¬A AND [B AND (¬D OR E) OR B AND (D OR ¬E)]}
                                   OR [(¬A AND ¬E AND (B OR D)]
                              = Y1 OR Y2 OR Y3

                        Where Y1 = A AND B AND NOT (E OR D)
                              Y2 = ¬A AND [B AND (¬D OR E) OR B AND (D OR ¬E)]
                              Y3 = (¬A AND ¬E AND (B OR D)

                        The Y column is the conjunction of the Y1, Y2 and Y3 columns and the final DNF
                        expression is just the OR (Sum), of the Y rows with true values:

                        Y = R3 OR R5 OR R6 OR R7 OR R13
                          = (¬A AND ¬B AND D AND ¬E) OR (¬A AND B AND ¬D AND ¬E) OR (¬A AND B AND ¬D AND E)
                                 OR (¬A AND B AND D AND ¬E) OR (A AND B AND ¬D AND ¬E)

                        This logical expression can now be evaluated in six clear and easily followed steps,
                        none of which involve an If test:
                           Evaluate each of the five row expressions using the canonical AND operations
                           Evaluate the final result using the canonical OR operation on those five results.

                        Alternatively, the expression could be coded directly using my functions. I did find
                        it necessary to first transform the expression from embedded binary notation to prefix
                        notation. Even then I had to be very careful not to introduce an error. I could then
                        use NTB's replace dialog to convert to Clip syntax. Without a parser to analyze and
                        convert an arbitrary expression with nested parentheses to Notetab format it still is
                        a bit tricky. The functions work well for short or medium complexity expressions but
                        a truth table is easier and more reliable for anything more complex.

                        Y1 = and(A,B,¬or(E,D))
                        Y2 = and(¬A,¬E,or(B,D))
                        Y3 = and(¬A,or(and(B,or(¬D,E)),and(B,or(D,¬E))))

                        ^!Set %Y1%^$AND(^%A%,^%B%,^$NOR(^%E%,^%D%)$)$
                        ^!Set %Y2%^$AND(^$NOT(^%A%)$$,^$NOT(^%E%)$$,^$OR(^%B%,^%D%)$)$
                        ^!Set %Y3%^$AND(^$NOT(^%A%)$$,^$OR(^$AND(^%B%,^$OR(^$NOT(^%D%)$$,^%E%)$)$,^$AND(^%B%,^$OR(^%D%,^$NOT(^%E%)$$)$)$
                        ^!Set %Y%=^$OR(^%Y1%;^%Y2%;^%Y3%)$


                        Some things to notice/consider:
                        • The astute reader will notice that Y2 is equivalent to ¬A AND B AND (D XOR E)
                             However, remember we are limiting ourselves to NOT, AND and OR operators.
                        • Separating the terms into partial result columns makes it easier and less
                             error prone to generate the truth table.
                        • There can be some overlap in the partial results (e.g., row 7, col Y2 and Y3)
                        • The growth of terms (and complexity) is linear, not exponential
                        • Changes to the system criteria (truth table), are easily and fairly reliably
                             propagated to the DNF expression terms (this is much, much less error prone
                             than If - Then - Else logic trees.
                        • Additional columns can easily be added to record the results of alternate
                             logical expressions using the same worksheet and input parameters states.
                        • The truth table is independent and external to any program language or code.
                             It is simply prep work prior to program implementation.
                        • A truth table is easy to generate, easy to understand and concise in execution
                        • Most important, using a truth table to analyze and code logic expressions is
                             the most reliable and least error prone method available.

                        OTOH, Trying to implement complex expressions by means of If - Then - Else
                        trees is a recipe for frustration and errors. Clear computation and  program
                        flow is a basic requirement for generating error free code as well for
                        downstream maintainability. The VanWeerthuizenian Expressions get very messy
                        very, very quickly once you go beyond the trivial two parameter, binary
                        condition unless you restrict yourself to canonical forms. This is primarily
                        due to the restriction of the MAX and MIN functions to two operands. That is
                        why I removed that restriction from my AND and OR functions. However, in
                        canonical form the benefit of my functions is much less dramatic than I expected.

                        For example for R3 = ¬A AND ¬B AND D AND ¬E

                        ^!Set %R3%=^$Calc(min((1-^%A%),min((1-^%B%),min(^%D%,(1-^%E%))));0)$
                        vs
                        ^!Set %R3%=^$AND(^$NOT(^%A%)$;^$NOT(^%B%)$;^%D%;^$NOT(^%E%)$)$

                        I think the functions are clearer and less error prone than all the nested
                        parentheses and remembering the correct mappings but not earth shakingly so.

                        However, the major point and lesson here is the transformation to DNF
                        form. Whether you use the VanWeerthuizenian constructs or my functions,
                        the best path to error free coding and ease of maintenance is to transform
                        your test criteria into canonical form using a single variable for each
                        criteria, generate the DNF expression (by either Boolean transformations
                        or via a truth table), and then evaluate the resulting products and sums.
                        Do not use an If test until the final result.


                        Applying this paradigm to your example:

                        {A AND B|A OR B|A NOT B|A XOR B|NOT A}

                        Let Y1 = A AND B; Y2 = A OR B; Y3 = A NOT B; Y4 = A XOR B; Y5 = NOT A

                        The truth table is:

                        #  A  B  Y1  Y2  Y3  Y4  Y5
                        =  =  =  ==  ==  ==  ==  ==
                        1  0  0  0   0   0   0   1
                        2  0  1  0   1   0   1   1
                        3  1  0  0   1   1   1   0
                        4  1  1  1   1   0   0   0

                        And the DNFs for the five cases are:

                        Y1 = A AND B
                        Y2 = A OR B
                        Y3 = A AND ¬B
                        Y4 = ¬A AND B OR A AND ¬B
                        Y5 = ¬A

                        It doesn't seem like we gained much but yours is a fairly trivial test and
                        remember, I am illustrating a generalized process, not content.
                        Implementing this in a clip:
                        ;######################### Start of Clip Code ###############################
                        ;^!SetDebug On
                        ^!Set %Lines%=^$GetTextLineCount$
                        ^!Set %Row%=1; %Hits%=^%Empty%
                        ^!Set %Case%=^?{(H=5)Find lines matching...==_A AND B|A OR B|A NOT B|A XOR B|NOT A}

                        :Loop
                        ^!Jump ^%Row%
                        ^!Set %A%=0; %B%=0; %Y%=0
                        ^!IfMatch "^.*A.*$" "^$GetLine$" ^!Set %A%=1
                        ^!IfMatch ".*B.*$" "^$GetLine$" ^!Set %B%=1

                        ^!Set %Y1%=^$Calc(MIN(^%A%;^%B%))$
                        ^!Set %Y2%=^$Calc(MAX(^%A%;^%B%))$
                        ^!Set %Y3%=^$Calc(MIN(^%A%;1-^%B%))$
                        ^!Set %Y41%=^$Calc(MIN(1-^%A%;^%B%))$
                        ^!Set %Y42%=^$Calc(MIN(^%A%;1-^%B%))$
                        ^!Set %Y4%=^$Calc(MAX(^%Y41%;^%Y42%))$
                        ^!Set %Y5%=^$Calc(1-^%A%)$

                        ^!IfMatch "^%Case%" "A AND B" ^!Set %Y%=^%Y1%
                        ^!IfMatch "^%Case%" "A OR B" ^!Set %Y%=^%Y2%
                        ^!IfMatch "^%Case%" "A NOT B" ^!Set %Y%=^%Y3%
                        ^!IfMatch "^%Case%" "A XOR B" ^!Set %Y%=^%Y4%
                        ^!IfMatch "^%Case%" "NOT A" ^!Set %Y%=^%Y5%

                        ^!IfTrue ^%Y% ^!Set %Hits%=^%Hits%^$GetLine$^P
                        ^!Inc %Row%
                        ^!If ^$GetRow$ < ^%Lines% Loop
                        ^!Info [L]Expression: ^%Case%^P^PMatches:^P^%Hits%

                        ^!GoTo End

                        ;Alternate set of logic expression calculations
                        ^!Set %Y1%=^$AND(^%A%;^%B%)$
                        ^!Set %Y2%=^$OR(%A%;^%B%)$
                        ^!Set %Y3%=^$AND(^%A%;^$NOT(^%B%)$)$
                        ^!Set %Y41%=^$AND(^$NOT(^%A%);^%B%)$;)$
                        ^!Set %Y42%=^$AND(^%A%;^$NOT(^%B%)$)$
                        ^!Set %Y4%=^$OR(^%Y41%;^%Y42%)$
                        ^!Set %Y5%=^$NOT(^%A%)$
                        ;######################### End of Clip Code ###############################

                        This, of course, could be rearranged to use your computed GoTos, the DNF
                        computations could be moved to the %case% tests with only %Y41% and %Y42%
                        pre-computed or other optimizations which might or might not be significant
                        depending on the application but would probably be at the cost of clarity
                        and generalization. Remember, the emphasis here is on clarity of program
                        flow (primarily linear), to minimize coding errors and to ease maintenance.
                        The various sections are segregated, similar operations are consolidated, and
                        program branches are minimized. A flow chart of this clip would not have any
                        crossed lines.

                        I hope this answers your questions.  Art
                      • flo.gehrke
                        ... Art & Joy, Many thanks again for your contributions to this topic! Obviously, I ve been on the wrong track when looking for more complex expressions based
                        Message 11 of 12 , Sep 20, 2013
                        • 0 Attachment
                          > You want to find out how to do this Wayne's way and I'm saying
                          > this is a big mistake except for the simplest of cases.

                          Art & Joy,

                          Many thanks again for your contributions to this topic!

                          Obviously, I've been on the wrong track when looking for more complex expressions based on Wayne's concept. As Art put it...

                          > The VanWeerthuizenian Expressions get very messy
                          > very, very quickly once you go beyond the trivial
                          > two parameter, ...

                          Your alternatives will provide a helpful basis for creating better solutions in a this field.

                          Regards,
                          Flo
                        • joy8388608
                          What is obvious to some may not be to others so here are a few more of my 3 AM thoughts... It may simplify things to break up the logical test into parts. We
                          Message 12 of 12 , Sep 21, 2013
                          • 0 Attachment

                            What is obvious to some may not be to others so here are a few more of my 3 AM thoughts...


                            It may simplify things to break up the logical test into parts. We have already seen that the AND operation is easy to work with so it's good to convert to all ANDs if possible. So if you are testing A AND B AND C AND (D OR E OR F), you could first create a temp variable

                            If (D+E+F) > 0 set T=1 else set T=0. Then you can do IfTrue(A*B*C*T) 


                            I see no need to limit things to 0 and 1 as long as you remember to use comparisons instead of IfTrue\IfFalse.. The above could also be done as If (A*B*C*(D+E+F)) > 0 then it is True.


                            Also, to try to avoid NOTs, you just have to plan ahead a little. Here is a very simple example.

                            If you wanted to accept lines with at least 2 letters and 0 digits, you could do:

                            If <at least 2 letters> L=1 else L=0

                            If <digits exist> D=1 else D=0

                            Then you would have to test for L AND NOT D


                            BUT if you think in terms of what you want to accept and do

                            If <at least 2 letters> L=1 else L=0

                            If <digits exist> D=0 else D=1

                            Then you would only have to test for L AND D.


                            Unless you have some reason for doing so, I still say it's better to do one test at a time and skip as soon as a test fails.


                            I'm sure you have a good grip on this now and plenty to think about.


                            Joy



                            --- In ntb-clips@yahoogroups.com, <flo.gehrke@...> wrote:

                            > You want to find out how to do this Wayne's way and I'm saying
                            > this is a big mistake except for the simplest of cases.

                            Art & Joy,

                            Many thanks again for your contributions to this topic!

                            Obviously, I've been on the wrong track when looking for more complex expressions based on Wayne's concept. As Art put it...

                            > The VanWeerthuizenian Expressions get very messy
                            > very, very quickly once you go beyond the trivial
                            > two parameter, ...

                            Your alternatives will provide a helpful basis for creating better solutions in a this field.

                            Regards,
                            Flo
                          Your message has been successfully submitted and would be delivered to recipients shortly.