Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

KDP_book

.pdf
Скачиваний:
84
Добавлен:
03.01.2021
Размер:
2.46 Mб
Скачать

Mathematica: Functional and procedural programming

sub-lists. On incorrect tuples of actual arguments the procedure call is returned unevaluated. The following fragment represents source code of the procedure and an example of its application.

In[28]:= SubDelStr[x_ /; StringQ[x], t_ /; ListListQ[t]] := Module[{k = 1, a = {}}, If[! t == Select[t, ListQ[#] &&

Length[#] == 2 &]||t[[–1]][[2]] > StringLength[x]||t[[1]][[1]] < 1, Return[Defer[SubDelStr[x, t]]],

For[k, k <= Length[t], k++,AppendTo[a, StringTake[x, t[[k]]] –> ""]]; StringReplace[x, a]]]

In[29]:= SubDelStr["123456789abcdfdh", {{3, 5}, {7, 8}, {10, 12}}]

Out[29]= "1269dfdh"

Replacements and extractions in strings. In a number of problems of strings processing, there is a need of replacement not simply of sub-strings but sub-strings limited by the certain sub-strings. The procedure solves one of such problems, its call StringReplaceS[S, s1, s2] returns the result of substitution into a S string instead of entries into it of sub-strings s1 limited by "x" strings on the left and on the right from the specified lists L and R respectively, by s2 sub-strings (StringLength["x"]=1); in a case of absence of such entries the procedure call returns the S string. The following fragment represents source code of the procedure StringReplaceS with an example of its typical application.

In[3822]:= StringReplaceS[S_ /; StringQ[S], s1_ /; StringQ[s1], s2_ /; StringQ[s2]] := Module[{a = StringLength[S],

L = Characters["`!@#%^&*(){}:\"\\/|<>?~=+[];:'., 1234567890"], R = Characters["`!@#%^&*(){}:\"\\/|<>?~=+[];:'., "], c = {}, k = 1, p, b = StringPosition[S, s1]}, If[b == {}, S, While[k <= Length[b], p = b[[k]];

If[Quiet[(p[[1]] == 1 && p[[2]] == a) || (p[[1]] == 1 && MemberQ[R, StringTake[S, {p[[2]] + 1, p[[2]] + 1}]]) || (MemberQ[L, StringTake[S, {p[[1]] 1, p[[1]] 1}]] && MemberQ[R, StringTake[S, {p[[2]] + 1, p[[2]] + 1}]]) || (p[[2]] == a && MemberQ[L, StringTake[S, {p[[1]] 1, p[[1]] 1}]])], c = Append[c, p]]; k++]; StringReplacePart[S, s2, c]]]

In[3823]:= S = "abc& c + bd6abc[abc] abc77*xyz^abc&78";

StringReplaceS[S, "abc", "xyz"]

Out[3823]= "xyz& c + bd6xyz[xyz] abc77*xyz^xyz&78"

141

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov

The above procedure, in particular, is a rather useful tool at processing of definitions of blocks and modules in respect of the operating with their formal arguments and local variables [14].

In a number of cases at strings processing it is necessary to extract from them the sub-strings limited by the symbol {"}, i.e. "strings in strings". This problem is solved by the procedure, whose call StrFromStr[x] returns the list of such sub-strings that are in a string x; otherwise, the call StrFromStr[x] returns the empty list, i.e. {}. The fragment below represents source code of the procedure along with a typical example of its application.

In[11]:= StrFromStr[x_String] := Module[{a = "\"", b, c = {}, k = 1}, b = DeleteDuplicates[Flatten[StringPosition[x, a]]]; For[k, k <= Length[b] 1, k++,

AppendTo[c, ToExpression[StringTake[x, {b[[k]], b[[k + 1]]}]]];

k = k + 1]; c] In[12]:= StrFromStr["12345\"678abc\"xyz\"50090\"mnph"]

Out[12]= {"678abc", "50090"}

To the above procedure an useful UniformString function adjoins. The strings can contain the sub-strings bounded by "\"" in particular the cdf/nb–files in the string format. To make such strings by uniform, the simple function UniformString is used. The call UniformString[x] returns a string x in the uniform form, whereas the call UniformString[x, y], where y is an expression returns the list of sub-strings of the x string which are bounded by "\"". The following fragment represents source code of the UniformString function with examples of its application.

In[4]:= UniformString[x_ /; StringQ[x], y___] :=

If[{y} == {}, StringReplace[x, "\"" > ""],

Map[StringReplace[#, "\"" > ""] &, StringCases[x, Shortest["\"" ~~ __ ~~ "\""]]]]

In[5]:= UniformString["{\"ClearValues\", \"::\", \"usage\"}"]

Out[5]= "{ClearValues, ::, usage}"

In[6]:= UniformString["{\"ClearValues\", \"::\", \"usage\"}", 7]

Out[6]= {"ClearValues", "::", "usage"}

The above function is a rather useful tool at processing of the string representation of cdf/nbfiles which is based on their

142

Mathematica: Functional and procedural programming

internal formats [14,22]. Unlike standard StringSplit function, the call StringSplit1[x, y] performs semantic splitting of a string x by symbol y onto elements of the returned list. The semantics is reduced to the point that in the returned list only sub-strings of the x string which contain the correct expressions are placed; in a case of lack of such substrings the procedure call returns the empty list. The StringSplit1 procedure appears as a rather useful tool, in particular at programming of tools of processing of the headings of blocks, functions and modules. The comparative analysis of the StringSplit and StringSplit1 tools speaks well for that. Fragment below represents source code of the StringSplit1 procedure along with typical examples of its application.

In[7]:= StringSplit1[x_ /; StringQ[x], y_ /; StringQ[y] ||

StringLength[y] == 1] := Module[{a = StringSplit[x, y], b, c = {}, d, p, k = 1, j = 1}, d = Length[a]; Label[G]; For[k = j, k <= d, k++, p = a[[k]];

If[! SameQ[Quiet[ToExpression[p]], $Failed], AppendTo[c, p], b = a[[k]]; For[j = k, j <= d 1, j++, b = b <> y <> a[[j + 1]]; If[! SameQ[Quiet[ToExpression[b]], $Failed], AppendTo[c, b]; Goto[G], Null]]]]; Map[StringTrim, c]]

In[8]:= StringSplit1["x_String, y_Integer, z_/; FreeQ[{1, 2, 3, 4}, z]

||OddQ[z], h_, s_String, c_ /; StringQ[c]||StringLength[c] == 1", ","]

Out[8]= {"x_String", "y_Integer", "z_/; FreeQ[{1, 2, 3, 4}, z] || OddQ[z]", "h_", "s_String", "c_ /; StringQ[c]||StringLength[c] == 1"}

Sub-strings processing in strings. At sub-strings processing in strings is often need of check of existence fact of sub-strings overlapping that enter to the strings. The call SubStrOverlapQ[x,y] returns True, if a string x contains overlapping sub-strings y or sub-strings from x matching the general string expression y, and False otherwise. While the call SubStrOverlapQ[x, y, z] through optional z argument an indefinite symbol additionally returns the list of consecutive quantities of overlapping of the y sub-list in the x string. The following fragment represents source code of the function with typical examples of its application.

In[7]:= SubStrOverlapQ[x_ /; StringQ[x], y_, z___] :=

MemberQ[{If[{z} != {} && NullQ[z], z = {}, 77],

143

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov

Map[If[Length[#] == 1, True, If[! NullQ[z], Quiet[AppendTo[z, Length[#]]], 78]; False] &, Split[StringPosition[x, y], MemberQ[Range[#1[[1]] + 1, #1[[2]]], #2[[1]]] &]]}[[2]], False]

In[8]:= {SubStrOverlapQ["dd1dd1ddaaaabcdd1d1dd1dd1dd1\ dd1aaaaaadd1", "aa", g1], g1}

Out[8]= {True, {3, 5}}

In[9]:= {SubStrOverlapQ["AAABBBBBAABABBBBCCCBAA\ AAAA", x_ ~~ x_, g2], g2}

Out[9]= {True, {2, 4, 3, 2, 5}}

The procedure SubStrSymbolParity represents undoubted interest at processing of definitions of functions or procedures given in the string format. The call SubStrSymbolParity[x,y,z,d] with four arguments returns the list of sub-strings of a string x that are limited by onecharacter strings y, z (y ≠ z); in addition, search of such substrings in the string x is done from left to right (d = 0), and from right to left (d = 1). Whereas the procedure call

SubStrSymbolParity[x,y,z,d,t] with the 5th optional argument a positive number t>0 – provides search in a substring of x which is limited by a position t and the end of x string at d = 0, and by the beginning of x string and t at d = 1. In a case of receiving of inadmissible arguments the call is returned unevaluated, while at impossibility of extraction of demanded sub-strings the call returns $Failed. This procedure is an useful tool, in particular, at solution of tasks of extraction from definitions of procedures of the list of local variables, headings, etc. The following fragment represents source code of the SubStrSymbolParity procedure with some typical examples of its application.

In[5]:= SubStrSymbolParity[x_ /; StringQ[x], y_ /; CharacterQ[y], z_ /; CharacterQ[z], d_ /; MemberQ[{0, 1}, d], t___ /; t == {} || PosIntQ[{t}[[1]]]] := Module[{a, b = {}, c = {y, z}, k = 1, j, f, m = 1, n = 0, p, h},

If[{t} == {}, f = x, f = StringTake[x, If[d == 0, {t, StringLength[x]}, {1, t}]]];

If[Map10[StringFreeQ, f, c] != {False, False} || y == z, Return[], a = StringPosition[f, If[d == 0, c[[1]], c[[2]]]]]; For[k, k <= Length[a], k++,

144

Mathematica: Functional and procedural programming

j = If[d == 0, a[[k]][[1]] + 1, a[[k]][[2]] 1]; h = If[d == 0, y, z]; While[m != n, p = Quiet[Check[StringTake[f, {j, j}], Return[$Failed]]];

If[p == y, If[d == 0, m++, n++];

If[d == 0, h = h <> p, h = p <> h], If[p == z, If[d == 0, n++, m++]; If[d == 0, h = h <> p, h = p <> h],

If[d == 0, h = h <> p, h = p <> h]]];

If[d == 0, j++, j––]]; AppendTo[b, h]; m = 1; n = 0; h = ""]; b]

In[6]:= SubStrSymbolParity["123{abcdf}7{ran}8{ian}9", "{", "}", 0]

Out[6]= {"{abcdf}", "{ran}", "{ian}"}

In[7]:= SubStrSymbolParity["12{abf}6{ran}8{ian}9", "{", "}", 1, 25]

Out[7]= {"{abf}", "{rans}"}

Meantime, in many cases it is possible to use a simpler and reactive version of the above procedure, whose procedure call SubStrSymbolParity1[x, y, z] with three arguments returns the list of sub-strings of a string x that are limited by one-character strings {y,z} (y≠z); in addition, search of such substrings is done from left to right. In the absence of the required sub-strings the procedure call returns the empty list, i.e. {}. A simple procedure is an useful enough modification of the SubStrSymbolParity1 procedure; its call StrSymbParity[S,s,x,y] returns the list whose elements are sub-strings of a string S which have format s1w on condition of parity of the minimum number of entries into a w substring of symbols x,y (x≠y). In the lack of such substrings or identity of symbols x, y, the call returns the empty list [16]. The

SubStrSymbolParity, SubStrSymbolParity1 and StrSymbParity procedures are rather useful tools, for instance, at processing of definitions of modules and blocks given in string format. These procedures are used by a number of tools of our MathToolBox package [8-12,15,16].

The procedure below is a rather useful tool for ensuring of converting of strings of a certain structure into lists of strings. In particular, such problems arise at processing of arguments and local variables. The problem is solved a rather effectively by the StrToList procedure, providing converting of strings of the "{xxxxxxxxx … x}" format into the list of strings received from a "xxxxx … x" string parted by comma symbols. In absence in an

145

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov

initial string of both limiting symbols {"{", "}"} the string will be converted in list of symbols as a call Characters["xxx…x"]. The next fragment presents source code of the StrToList procedure with examples of its application.

In[8]:= StrToList[x_ /; StringQ[x]] := Module[{a, b = {}, c = {}, d, h, k = 1, j, y = If[StringTake[x, {1}] == "{" &&

StringTake[x, {1}] == "}", StringTake[x, {2, 2}], x]}, a = DeleteDuplicates[Flatten[StringPosition[y, "="]] + 2]; d = StringLength[y]; If[a == {}, Map[StringTrim, StringSplit[y, ","]],

While[k <= Length[a], c = ""; j = a[[k]]; For[j, j <= d, j++, c = c <> StringTake[y, {j}];

If[! SameQ[Quiet[ToExpression[c]], $Failed] && (j == d || StringTake[x, {j + 1}] == ","),

AppendTo[b, c > ToString[Unique[$g$]]]; Break[]]]; k++]; h = Map[StringTrim, StringSplit[StringReplace[y, b], ","]]; Map14[StringReplace, h, RevRules1[b]]]]

In[9]:= StrToList["Kr, a = 90, b = {x, y, z}, c = {n, m, {42, 47, 67}}"]

Out[9]= {"Kr", "a = 90", "b = {x, y, z}", "c = {n, m, {42, 47, 67}}"} In[10]:= StrToList["{a = 500, b = 90, c = {m, n}}"]

Out[10]= {"a = 500", "b = 90", "c = {m, n}"}

The above procedure is intended for converting of strings of format "{x…x}" or "x…x" into the list of strings received from strings of the specified format which are parted by symbols "=" and/or comma. Fragment examples an quite visually illustrate the basic principle of performance of the procedure along with formats of the returned results. At last, the fragment uses quite simple and useful procedure, whose call RevRules[x] returns the rule or list of rules that are reverse to the rules defined by a x argument a rule of form a–>b or their list [16]. The procedure can be also represented in the functional form, namely:

In[3327]:= RevRules1[x_ /; RuleQ[x] || ListQ[x] &&

AllTrue[Map[RuleQ, x], TrueQ]] := Map[Rule[#[[2]], #[[1]]] &, Flatten[{x}]][[If[Length[Flatten[{x}]] > 1, 1 ;; Length[Flatten[{x}]], 1]]]

In[3328]:= RevRules1[{a > b, c > d, n > m}]

Out[3328]= {b > a, d > c, m > n}

146

Mathematica: Functional and procedural programming

Note, that the RevRules1 function is essentially used by the above StrToList procedure.

The following procedure is a rather useful means of strings processing in a case when it is required to identify in a string of occurrence of sub-strings of kind "abc…n" and "abc…np", p – a character. The procedure call SubsInString[x, y, z] returns 0, if substrings y and y<>z where y – a string and z – a character are absent in a string x; 1, if x contains y and not contain y <> z; 2, if x contains y <> z and not contain y, and three otherwise, i.e. the x string contains both y and y <> z [8,9]. Whereas the procedure call CorrSubStrings[x, n, y] returns the list of substrings of string x that contain all formally correct expressions, at the same time, search is done beginning with n–th position of the x string from left to right if the third optional y argument is absent, and from right to left if the y argument any expression exists. Fragment represents source code of the CorrSubStrings procedure and an example of its typical application.

In[7]:= CorrSubStrings[x_ /; StringQ[x], n_ /; PosIntQ[n], y___] := Module[{a = {}, b = StringLength[x], c = ""}, If[{y} != {}, Do[If[SyntaxQ[Set[c, StringTake[x, {j}] <> c]], AppendTo[a, c], 7], {j, n, 1, –1}], Do[If[SyntaxQ[Set[c, c <> StringTake[x, {j}]]],

AppendTo[a, c], 7], {j, n, b}]]; a]

In[8]:= CorrSubStrings["(a+b/x^2)/(c/x^3+d/y^2)+1/z^3", 29, 2]

Out[8]= {"3", "z^3", "1/z^3", "+1/z^3", "(c/x^3+d/y^2)+1/z^3",

"(a+b/x^2)/(c/x^3+d/y^2)+1/z^3"}

In a number of cases there is a necessity of reducing to the set number of the quantity of entries into a string of its adjacent sub-strings. That problem is solved by the ReduceAdjacentStr procedure presented by the following fragment. The procedure call ReduceAdjacentStr[x, y, n] returns the string the result of reducing to an quantity n ≥ 0 of occurrences into a string x of its adjacent y substrings. If a string x not contain y substrings, then the call returns the initial x string; the call ReduceAdjacentStr[x, y, n, h] where h – an arbitrary expression, returns the above result on condition that at search of the y substrings in the x string the

147

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov

lowercase and uppercase letters are identified.

In[41]:= ReduceAdjacentStr[x_ /; StringQ[x], y_ /; StringQ[y], n_ /; IntegerQ[n], z___] := Module[{a = {}, b = {},

c = Append[StringPosition[x <> FromCharacterCode[0], y, IgnoreCase > If[{z} != {}, True, False]], {0, 0}], h, k}, If[c == {}, x, Do[If[c[[k]][[2]] + 1 == c[[k + 1]][[1]], b = Union[b, {c[[k]], c[[k + 1]]}], b = Union[b, {c[[k]]}]; a = Union[a, {b}]; b = {}], {k, 1, Length[c] 1}]; a = Select[a, Length[#] >= n &];

a = Map[Quiet[Check[{#[[1]], #[[1]]}, Nothing]] &,

Map[Flatten, Map[#[[Length[#] + n ;; 1]] &, a]]]; StringReplacePart[x, "", a]]]

In[42]:= ReduceAdjacentStr["abababcdcdxmnabmabab","ab",3]

Out[42]= "abababcdcdxmnabmabab"

In contrast to the LongestCommonSubsequence function the procedure call LongestCommonSubsequence1[x, y, J] in a mode

IgnoreCase>J {True,False} finds the longest contiguous substrings that are common to the strings x and y. Whereas the procedure call LongestCommonSubsequence1[x,y,J,t] additionally through an indefinite t variable returns the list of all common contiguous substrings. The procedure essentially uses the procedure whose call Intersection1[x,y,z,…,J] returns the list of elements common to all lists of strings in the mode IgnoreCase>J {True,False}. The fragment below represents source codes of both procedures and typical examples of their application.

In[6]:= LongestCommonSubsequence1[x_ /; StringQ[x],

y_ /; StringQ[y], Ig_ /; MemberQ[{False, True}, Ig], t___] := Module[{a = Characters[x], b = Characters[y], c, d, f}, f[z_, h_] := Map[If[StringFreeQ[h, #], Nothing, #] &, Map[StringJoin[#] &, Subsets[z]][[2 ;; 1]]];

c = Gather[d = Sort[If[Ig == True, Intersection1[f[a, x], f[b, y], Ig], Intersection[f[a,x], f[b,y]]], StringLength[#1]<=StringLength[#2]&], StringLength[#1] == StringLength[#2] &]; If[{t} != {} && ! HowAct[t], t = d, Null]; c = If[c == {}, {}, c[[1]]]; If[c == {}, {}, If[Length[c] == 1, c[[1]], c]]]

In[7]:= {LongestCommonSubsequence1["AaAaBaCBbBaCaccccC",

148

Mathematica: Functional and procedural programming

"CacCCbbbAaABaBa", False, gs], gs}

Out[7]= {{"AaA", "aBa", "Cac"}, {"a", "A", "b", "B", "c", "C", "aA", "Aa", "aB", "ac", "Ba", "Ca", "cC", "AaA", "aBa", "Cac"}} In[8]:= {LongestCommonSubsequence1["Rans", "Ian", True, j], j}

Out[8]= {"an", {"a", "n", "an"}}

In[9]:= Intersection1[x__ /; AllTrue[Map[ListQ[#] &, {x}], TrueQ], Ig_ /; MemberQ[{False, True}, Ig]] := Module[{b = Length[{x}], c = {}, d = {}},

Do[AppendTo[c, Map[StringQ, {x}[[j]]]], {j, 1, b}]; If[DeleteDuplicates[Flatten[c]] != {True}, $Failed,

If[Ig == False, Intersection[x], Do[AppendTo[d, Map[{j, #, ToUpperCase[ToString[#]]} &, {x}[[j]]]], {j, 1, b}]; c = Map[DeleteDuplicates, Gather[Flatten[Join[d], 1], #1[[3]] == #2[[3]] &]]; c = Flatten[Select[c, Length[#] >= b &], 1];

c = If[DeleteDuplicates[Map[#[[1]] &, c]] != Range[1, b], {},

DeleteDuplicates[Map[#[[2]] &, c]]]]]] In[10]:= Intersection1[{"AB", "XY", "cd", "Mn"}, {"ab", "cD", "MN", "pq", "mN"}, {"90", "mn", "Ag"}, {"500", "mn", "Av"}, True]

Out[10]= {"Mn", "MN", "mN", "mn"}

The LongestCommonSubsequence2 procedure is a certain extension of the LongestCommonSubsequence1 procedure for a case of a finite number of strings in which the search for longest common continuous sub-strings is done [8,11,14-16].

In[317]:= LongestCommonSubsequence2["ABxCDH", "ABxC",

"ABxCDCABCdc", "xyzABXC", "xyzABxC", "mnpABxC", True]

Out[317]= {"ABxC", "ABXC"}

For work with strings the following procedure is a rather useful, whose call InsertN[S, L, n] returns the result of inserting into a string S after its positions from a list n of substrings from a list L; in a case n = {< 1|≥ StringLength[S]} a sub-string will be located before S string or in its end respectively. It is supposed that the actual arguments L and n may contain various number of elements, in such case the excess n elements are ignored. At that, processing of a string S is carried out concerning the list of positions for m insertions defined according to the relation m = DeleteDuplicates[Sort[n]]. The procedure call InsertN[S, L, n]

149

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov

with inadmissible arguments is returned as unevaluated. The procedure was used significantly in programming a number of MathToolBox package tools [16]. The next fragment represents source code of the procedure with examples of its application.

In[2220]:= InsertN[S_String, L_ /; ListQ[L], n_ /; ListQ[n] &&

Length[n] == Length[Select[n, IntegerQ[#] &]]] := Module[{a = Map[ToString, L], d = Characters[S], p, b, k = 1, c = FromCharacterCode[2], m = DeleteDuplicates[Sort[n]]}, b = Map[c <> ToString[#] &, Range[1, Length[d]]]; b = Riffle[d, b]; p = Min[Length[a], Length[m]]; While[k <= p, If[m[[k]] < 1, PrependTo[b, a[[k]]], If[m[[k]] > Length[d], AppendTo[b, a[[k]]],

b = ReplaceAll[b, c <> ToString[m[[k]]] > a[[k]]]]]; k++]; StringJoin[Select[b, ! SuffPref[#, c, 1] &]]]

In[2221]:= InsertN["123456789Rans_Ian", {Ag, Vs, Art, Kr},

{6, 9, 3, 0, 3, 17}]

Out[2221]= "Ag123Vs456Art789KrRans_Ian"

In[2222]:= InsertN["123456789", {a, b, c, d, e, f, g, h, n, m},

{4,2,3,0,17,9,18}]

Out[2222]= "a12b3c4d56789efg"

Contrary to the InsertN procedure the call of the procedure DelSubStr[S, L] provides removal from a string S of substrings, whose positions are set by a list L; the L list has nesting 0 or 1, for example, {{3, 4}, {7}, {9}} or {1, 3, 5, 7, 9}, whereas the function call AddDelPosString[x,y,h,z] returns the result of truncation of a string x to the substring x[[1 ;; y]] if z – an arbitrary expression and x[[y ;; –1]] if {z} == {} with replacing of the deleted substring by a string h. In a case of an incorrect value y the call returns the initial x string or is returned unevaluated [16]. Both these tools are rather useful in a number of problems of strings processing of various structure and appointment.

The following procedure provides extraction from string of continuous substrings of length bigger than 1. The procedure call ContinuousSubs[x] returns the nested list whose elements have format {s, {p11, p12},…,{pn1, pn2}} where s – a substring and {pj1, pj2} (j = 1..n) determine the first and last positions of copies of a continuous s sub-string that compose a string x. The procedure

150

Соседние файлы в предмете Математические пакеты