Showing posts with label Position. Show all posts
Showing posts with label Position. Show all posts

Saturday, March 9, 2013

Introduction to Strings in Mathematica

A format convention in Mathematica is to show quotation marks around strings in input cells, but not in output cells. To show them in output cells, use FullForm.

In[18]:= "I've entered a string by using quotation marks."

Out[18]= I've entered a string by using quotation marks.

In[19]:= Head@%

Out[19]= String

In[20]:= FullForm@%%

Out[20]//FullForm= "I've entered a string by using quotation marks."

In programming languages, "String" is the name for the data type of text expressions. In other words, unlike symbols in a general expression, the symbols in a String, like a, b, c, do not refer to places in memory that store a variable, like a function or value. Symbols in a String do not refer to anything, or you could say they only refer to themselves as "literals", that is, the literal characters or tokens "a", "b", "c". An "a" is just a blank token with nothing behind it; hence the terms "literal" or "token" for a String symbol.

In[21]:= a = 5534.7; a

Out[21]= 5534.7

Trying to use a String as a variable gives an error message.

In[22]:= "a" = "Lookee here."

During evaluation of In[22]:= Set::setraw: Cannot assign to raw object a. >>

Out[22]= "Lookee here."

Consequently, Strings are not evaluated in the usual way that other Expressions are. Wellin et al. in their excellent book suggest that we think of a String as being broken up by Mathematica into a sequence of its characters and then functions are applied to the sequence.

In[8]:= aSentence = "The quick brown fox jumped over the 742 lazy white dogs.";

In[11]:= aSentenceCharacters = aSentence // Characters

Out[11]= {T,h,e, ,q,u,i,c,k, ,b,r,o,w,n, ,f,o,x, ,j,u,m,p,e,d, ,o,v,e,r, ,t,h,e, ,7,4,2, ,l,a,z,y, ,w,h,i,t,e, ,d,o,g,s,.}

Functions, like MatchQ, Cases, Position, etc., that work on non-String expressions do not work on Strings but do work on their sequence of characters.

In[14]:= Position[aSentence, "e"]

Out[14]= {}

So perhaps as Wellin et al suggest, Mathematica first breaks a String into a sequence of characters and applies some of the regular built-in functions as well as some specialized String functions to the sequence.


In[25]:= MatchQ[#, "e"] & /@ aSentenceCharacters

Out[25]= {False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, True, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False}

In[24]:= StringMatchQ[aSentenceCharacters, "e"]

Out[24]= {False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, True, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False}


In[15]:= Position[aSentenceCharacters, "e"]

Out[15]= {{3}, {25}, {30}, {35}, {50}}

In[16]:= StringPosition[aSentence, "e"]

Out[16]= {{3, 3}, {25, 25}, {30, 30}, {35, 35}, {50, 50}}

The position index is repeated in StringPosition since it shows the beginning and ending positions of the matched String.

In[20]:= StringPosition[aSentence, "lazy"]

Out[20]= {{41, 44}}

When working with Strings, you do not need to enclose a String in List brackets:

In[3]:= aString = {"abcd"}

Out[3]= {abcd}

In[4]:= aString2 = "abcd"

Out[4]= abcd

In[5]:= Head@aString2

Out[5]= String

The String is delimited by invisible quotation marks. As usual FullForm and InputForm reveal the way Mathematica sees the String.

In[6]:= FullForm@aString2

Out[6]="abcd"

In[7]:= InputForm@aString2

Out[7]="abcd"

Next we will look at the variety of String functions in Mathematica.

Monday, January 2, 2012

Predicates, Tests, and Test Patterns: How to Build Your Own

Build Your Own: User-defined Examples

Xiangdong Wen of Tech Support noted that the hard part of constructing Predicates is considering all the possible inputs and exceptions. To do a thorough job, we might need to do a Piecewise definition of a Predicate, or define a Predicate with Which, and if desired leave an error message as the final condition at the bottom to catch any exceptions that escaped us.

Limit a Built-in Predicate: lessThanOneQ

lessThanOneQ@x_ := If[ x1 < 1, True, False]

testSet = Range[0, 1.5, .3]

{0., 0.3, 0.6, 0.9, 1.2, 1.5}

lessThanOneQ /@ testSet

{True, True, True, True, False, False}

Test for Specified Length: lengthTwoQ

Clear@lengthTwoQ; lengthTwoQ@x_ := If[Length@x == 2, True, False]

lengthTwoQ /@ {{x, y}, {y, x}, {x, y, z}}

{True, True, False}

Test for Meeting Boolean Combination of Conditions: BinaryQ

By setting the Attributes of our Predicate to Listable, we shortcut the need to use Map over a List.

ClearAll@BinaryQ; SetAttributes[BinaryQ, Listable];
BinaryQ@x_ := If[x === 1 || x === 0, True, False ]

BinaryQ@{0, 3, 1, 1., 2}

{True, False, True, False, False}

One can also use Boolean And (&&) similarly, or any combination of And and Or in a compound Expression.

Test for Membership in a Set: integerLessThan10Q

Here we make a Predicate from a test for an element's membership in a defined set.

integerLessThan10 = Range@10

{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

integerLessThan10Q@x_ := If[MemberQ[integerLessThan10, x], True, False]

integerLessThan10Q /@ {4, 4/5, Pi, 3, 11, 251/25}

{True, False, False, True, False, False}

More Examples: maxEqualQ, maxNearQ, valueAtQ, positionNearQ

Different Predicates can test for a variety of related conditions. These are functions I used to test properties of book bestseller lists but here I use random lists for illustration. The first one tests to see if the maximum value of two lists of numbers are the same.

maxEqualQ[x_List, y_List] := If[Max@x == Max@y, True, False]

list1 = RandomInteger[{0, 25}, 20] // Sort

{0, 2, 2, 4, 5, 6, 8, 8, 9, 9, 9, 11, 15, 16, 16, 17, 17, 19, 19, 19}

list2 = RandomInteger[{0, 25}, 20] // Sort

{1, 2, 5, 6, 6, 6, 9, 12, 13, 14, 17, 17, 18, 18, 23, 23, 24, 24, 25, 25}

maxEqualQ[list1, list2]

False

This tests to see if difference between the maximum of two lists is less than a specified magnitude.

maxNearQ[x_List, y_List, nearness_Integer] :=
 If[Abs[Max@x - Max@y] <= nearness, True, False]

maxNearQ[list1, list2, 10]

True

maxNearQ[list1, list2, 1]

False

This tests to see if the Position of the maxima of two lists is the same.

maxPositionEqualQ[x_List, y_List] :=
 If[Position[list1, Max@x] == Position[list2, Max@y], True, False]

maxPositionEqualQ[list1, list2]

False

Using Predicates in Select, Cases, and Related Filter Functions

As you look at these simple examples realize they are but a glimpse of the power of this type of usage that I mentioned at the start of this section. The Predicates, Conditions and Boolean conjunctions used in these filter functions can be arbitrarily complex, and as Mangone notes we are only restricted to anything that Mathematica can compute.

First we define a Predicate and use pure Function since those are idioms that Select uses, then we just use Condition in Cases, since that is the syntax that Cases uses. Consequently I recommend using the Q suffix when naming a Predicate used in Select. Note in the Cases example the additional restriction to Reals using a Head test.

Consider using Predicates in the related filter functions Count, Position, Tally, Gather, Sort, SortBy, etc.

Clear@lessThanOneQ; lessThanOneQ@x_ := If[ x < 1, True, False]

Select[Range[-0.2, 1.1, 0.2], lessThanOneQ]

{-0.2, 0., 0.2, 0.4, 0.6, 0.8}

Select[Range[-0.2, 1.1, 0.2], # < 1 &]

{-0.2, 0., 0.2, 0.4, 0.6, 0.8}

Function[x, x < 1] /@ Range[-0.2, 1.1, 0.2]

{True, True, True, True, True, True, False}

Cases[Range[-0.2, 1.1, 0.2], x_Real /; x < 1]

{-0.2, 0., 0.2, 0.4, 0.6, 0.8}

lessThanOnePositiveQ@x_ :=
 If[0 < x < 1 , True, False](* version restricted to positive numbers *)

lessThanOnePositiveQv2@x_ :=
 If[x < 1 && Positive@x, True, False] (* alternate version *)

Select[Range[-0.2, 1.1, 0.2], lessThanOnePositiveQ]

{0.2, 0.4, 0.6, 0.8}

Select[Range[-0.2, 1.1, 0.2], lessThanOnePositiveQv2]

{0.2, 0.4, 0.6, 0.8}

Predicate Using a Piecewise Function

Note the usage in the Named Pattern variable of a NumberQ predicate to allow both Reals and Integers. This example is intended to illustrate that a Piecewise-defined Predicate can include an unlimited number of orthogonal conditions.

Clear@pieceWiseElementQ; pieceWiseElementQ@number_?NumberQ :=
 Piecewise[{{False, number < -3}, { True, -3 < number < 0}, {False,
    0 <= number <= 6}, {True, number > 6}, {True, number === 4.5}}]

pieceWiseElementQ /@ {-3.00001, -0.0000000001, -4/5, 0, 0.000000001, 4/5, 4.5,
   6, 6.01, 9}

{False, True, True, False, False, False, False, False, True, True}