Michael von Aichberger <[EMAIL PROTECTED]> wrote:

> based on 24 flags that can be set or not set, the user should be able
> to define a logical formula that is used as a filter.
>
> My file names contain the 6-digit hex code and some other numbers
>
> "give me that particular picture if it has either a cat or a dog
> in it and is yellow"
>
> I don't see why I should run through all files with the one
> question and then through all the files again with the other
> question.

Hi Michael,

It seems to me that you need two distinct operations:
* one to formulate the question
* and one to ask that question of each of the files.

Suppose you are working with a simpler set of criteria, with only six
variables, each represented by a bit:

1: TRUE if picture includes a dog
2: TRUE if picture includes a cat
3: TRUE if picture includes a human being
4: TRUE if picture is mostly yellow
5: TRUE if picture is mostly blue
6: TRUE if picture is mostly red

The bits could be called: dog cat human yellow blue green

To formulate your question, you could create a list of all the numbers that
would satisfy the query:

Either 1 or 2 must be set to TRUE
3 can be set to TRUE or FALSE
4 must be TRUE
5 and 6 must be false since they are mutually exclusive with 4

Here are the numbers that satisfy the query:

Binary   Hex   Decimal
010100    14     20         dog      +yellow
011100    1C     28         dog+human+yellow
100100    24     36     cat          +yellow
101100    2C     44     cat    +human+yellow
110100    34     52     cat+dog      +yellow
111100    3C     60     cat+dog+human+yellow


The first operation would therefore be to build the list [20, 28, 36, 44,
52, 60] from the selection criteria.  The second operation would be to test
if the hex number associated with each file is one of the numbers in the
list.

In pseudo-Lingo:

on findMatches(aSetOfCriteria)
  matchingImages = []

  matchingNumberList = buildListOfMatchingNumbers(aSetOfCriteria)

  tCount = the number of images
  repeat with i = 1 to tCount
    tImage = image[i]
    numberPartOfImageName = getNumberPart(tImage.name)
    if matchingNumberList.getPos(numberPartOfImageName) then
      matchingImages.append(tImage)
    end if
  end repeat

  return matchingImages
end


The question then becomes: how do you code the buildListOfMatchingNumbers()
handler?

> I don't see why I should run through all files with the one
> question and then through all the files again with the other
> question.

Using the two operations I described above, you won't need to run through
all the *files* more than once, but you will need a multiple-pass system for
determining all the numbers that match the query.

It is easy to deal queries that are formulated in terms of  MUST, MUST NOT
and IRRELEVANT.  However, your initial query  also includes a condition: if
not dog then cat.  This is much harder to deal with, but it can be broken
down into two queries each of which uses MUST, MUST NOT and IRRELEVANT.  The
items in the two results may overlap:

> "give me that particular picture if it has either a cat or a dog
> in it and is yellow"

1: "give me that particular picture if it has a CAT in it and is YELLOW"
2: "give me that particular picture if it has a DOG in it and is YELLOW"

Combining the results will give you duplicates where there is both a cat and
a dog.  It is easy enough to filter out such duplicates.

Your buildListOfMatchingNumbers() handler could look like this:

on buildListOfMatchingNumbers(aSetOfCriteria, aMatchesList) ----------
  -- INPUT: <aSetOfCriteria> should be a list with the format
  --         [<0 | 1 | 2>, <0 | 1 | 2>, ... <0 | 1 | 2>], where
  --         there are the same number of items as there are criteria
  --         for the user to choose from, and where the values
  --         indicate:
  --           0: MUST NOT
  --           1: MUST
  --           2: IRRELEVANT (either)
  --         It can also be a list of such lists, in which case, each
  --         sub-list is treated recursively and the results
  --         accumulated
  --        <aMatchesList> may be a linear list of numbers
  -- OUTPUT: <aMatchesList>, the linear list of numbers which
  --         match the search criteria
  ---------------------------------------------------------------------
  
  if ilk(aSetOfCriteria) <> #list then
    -- Can't proceed
    exit
  else if not aSetOfCriteria.count then
    -- There are no criteria
    exit
  end if
  
  if ilk(aMatchesList) <> #list then
    aMatchesList = []
    aMatchesList.sort()
  end if
  
  -- Determine whether this is a list of integers or a list of lists
  i = aSetOfCriteria.count
  tItem = aSetOfCriteria[1]
  
  if ilk(tItem, #list) then
    -- Consider aSetOfCriteria to be a list of lists: treat each
    -- each item separately using recursion
    repeat while i
      buildListOfMatchingNumbers(aSetOfCriteria[i], aMatchesList)
      i = i - 1
    end repeat
    
    return aMatchesList
    
  else
    -- Consider aSetOfCriteria to be a list of integers: create the
    -- list of numbers associated with the query.

    tList  = [0]
    tCount = 1
    tPower = 1
    repeat while i
      tValue = aSetOfCriteria[i]
      case tValue of
        0: -- MUST NOT: leave this bit value at 0
        1: -- MUST:     set this bit value to 1
          repeat with j = 1 to tCount
            tList[j] = tList[j] + tPower
          end repeat
        2: -- IRRELEVANT (either): set bit value to 1 and 0
          repeat with j = 1 to tCount
            tList.append(tList[j]) -- add new item with bit at 0
            tList[j] = tList[j] + tPower -- set bit to 1
          end repeat
          tCount = tCount * 2 -- we've doubled the items in the list
      end case
      
      tPower = tPower * 2 -- value of next bit to be set
      i = i - 1
    end repeat
    
    -- Add items in tList to aMatchesList, ignoring any duplicates
    i = tList.count
    repeat while i
      tMatch = tList[i]
      if not aMatchesList.getPos(tMatch) then
        aMatchesList.add(tMatch)
      end if
      i = i - 1
    end repeat
    
    return aMatchesList
  end if
end buildListOfMatchingNumbers


Test this by typing the following into the Message window:

tCatsAndMaybeDogs = [1,2,2,1,0,0] -- maybe humans, must be yellow
tDogsAndMaybeCats = [2,1,2,1,0,0] -- maybe humans, must be yellow
put buildListOfMatchingNumbers([tCatsAndMaybeDogs, tDogsAndMaybeCats])
-- [20, 28, 36, 44, 52, 60]


Is this the sort of answer you were looking for?

Cheers,

James

[To remove yourself from this list, or to change to digest mode, go to 
http://www.penworks.com/lingo-l.cgi  To post messages to the list, email 
[EMAIL PROTECTED]  (Problems, email [EMAIL PROTECTED]). Lingo-L is for 
learning and helping with programming Lingo.  Thanks!]

Reply via email to