nexts := proc(S::{string, symbol}, A::{posint, string, symbol}, B::{string, symbol}) local a b s k t n, , , , , ; if map(member, {S A B, , }, {``, ""}) = {false} then try assign(s = cat "",( S), b = [ ], n = `if`(type(A, 'posint'), ,1 length(A))); `if`(type(A, {'symbol', 'string'}), assign(a = Search2(s, {A})), assign( `if`(A ≤ length( )s , assign(a = [A]), ERROR "2nd argument must be <=%1",( length( )s )))) catch : ERROR("wrong type of arguments in nexts call - %1"[args], ) end try else ERROR("arguments cannot be empty", [S, A, B]) end if; if a = [ ] then false elif nargs = 3 then for k in a do `if` search(( s[k + n .. -1], B, ' 't ), assign('b' = [op(b), [k, t + k + n − 1]]), assign('b' = [op(b), [k]])) end do; `if`(nops(b) = 1, op(b), b) else for k in a do assign(' 'a = Search2(s[1 .. k − 1], {B})), `if`(a = [ ], assign('b' = [op(b), [k]]), assign('b' = [op(b), [k, a[-1]]])) end do; `if`(nops( )b = 1, op( )b , b) end if end proc > S:= "aaaccccacaaaccaaacaacddddccrtdrtbbaaabaaabaaahtyrebaaa": nexts(S, 29, b), nexts(S, 29, b, 8); ⇒ [29, 33], [29] > nexts(S, "", b); Error, (in nexts) arguments cannot be empty, [aaaccccacaaaccaaacaacddddccrtdrtbbaaabaaabaaahtyrebaaa, , b] > nexts(S, aaa, b), nexts(S, aaa, bb); [[1,33], [10,33], [15,33], [35,38], [39,42], [43,51], [52]], [[1,33], [10,33], [15,33], [35], [39], [43],[52]] > nexts(S, aaa, ba); ⇒ [[1, 34], [10, 34], [15, 34], [35, 42], [39, 51], [43, 51], [52]] > nexts(S, xyz, ba); ⇒ false > nexts(S, "cr", rt); ⇒ [27, 31] > nexts(S, aaa, b, 1), nexts(S, aaa, bb, 2); [[1], [10], [15], [35, 34], [39, 38], [43, 42], [52,51]], [[1], [10], [15], [35,33], [39,33], [43,33], [52,33]] > nexts(S, ccc, t, 1), nexts(S, crt, bb, 2), nexts(S, crt, bb); ⇒ [[4], [5]], [27], [27, 33] |
Наконец, вызов следующей процедуры SUB_S(L, S) возвращает результат выполнения подстановок, определенных аргументом L (список уравнений-подстановок), в строку либо символ S; при этом, очередная подстановка из L выполняется до ее полного исчерпания в строке S. Тип возвращаемого результата соответствует типу исходного аргумента S. В случае неприменимости подстановок L второй аргумент S возвращается без обработки.
SUB_S := proc(L::list(equation ), S::{string, symbol}) local k d G h P R l, , , , , , ; if L = [ ] then S elif seq `if`( ("" || lhs k( ) = "" || rhs k( ), ERROR("substitution <%1> initiates infinite process", k), NULL), k = L) = NULL then assign(l = [seq(convert(lhs(L k[ ]), 'string') = convert(rhs(L k[ ]), 'string'), k = 1 .. nops(L))], R = "" || S), `if`(nargs = 3 and args 3[ ] = 'sensitive', assign(P = 'SearchText'), assign(P = 'searchtext')); for k to nops(L) do assign('d' = P(lhs(l[k]), R), 'h' = lhs(l[k]), 'G' = rhs(l[k])); if d ≠ 0 then R := cat substring( ,( R 1 .. d − 1), G, substring(R, d + length( )h .. length(R))); k := k − 1 end if end do; convert(R, whattype( )S ) end if end proc > SUB_S([ab=cdgh,aa=hhsg,cd=cprhkt],"aaababccabaacdcdaaasvrhcdabaa"); "hhsgcprhktghcprhktghcccprhktghhhsgcprhktcprhkthhsgasvrhcprhktcprhktghhhsg" > SUB_S([42=64,47=59,67=39],"aaab4242ccaba4747daaasv6767abaa"); "aaab6464ccaba5959daaasv3939abaa" |
В главе 5 [103] рассматриваются программные средства, расширяющие возможности пакета Maple релизов 6 - 10 при работе с выражениями типов {string, symbol}. Представленные в ней средства включены и в нашу Библиотеку [108,109], и обеспечивают множество полезных процедур таких как специальные виды преобразования, сравнение строк или символов, различные виды поиска в строках, обращение символов, строк или списков, исчерпывающие замены в строках или символах, сведение кратности вхождения символа в строку, определение вхождения специальных символов в строку и целый ряд иных. Во многих случаев данные средства существенно упрощают программирование с использованием объектов Maple типов {string, symbol, name} в среде пакета. Это актуально, в первую очередь потому, что символьные выражения составляют как основу важнейших структур пакета, так и основной объект символьных вычислений и обработки. Переходим теперь к рассмотрению средств обеспечения работы со структурами и данными списочного и множественного типов {list, set}, весьма широко используемых Maple-языком.
Списочные и множественные структуры и данные (или для краткости просто списки и множества) имеют следующий чрезвычайно простой вид кодирования:
List:= [X1, X2, X3, ..., Xn] и Set:= {X1, X2, X3, ..., Xn}
где в качестве Xj-элемента (j=1, 2, 3, ..., n) могут выступать любые допустимые Maple-выражения, включая и сами структуры типов {list, set}, т.е. такие структуры допускают различные уровни вложенности, глубина которых ограничивается только доступным объемом оперативной памяти ПК. Пустой список (множество) обозначается как “[]” (“{}”). Следующий простой фрагмент иллюстрирует типичные структуры типов {list, set}, допускаемые Maple-языком пакета:
> SL:= [`Example`, array(1..2, 1..2, [[V, G], [S, A]]), F(k)$k=1..3, Int(G(x), x = a..b)]; SL Example, VS GA, F 1( ), F(2), F 3( ), ⌠⌡abG( )x dx := > SS:= {`Example`, array(1..2, 1..2, [[V, G], [S, A]]), F(k)$k=1..3, Int(G(x), x = a..b)}; SS := {Example, ⌠abG( )x dx, F 3( ), F(1), F 2( ), VS GA} ⌡ |
Результатом вычисления List-структуры (Set-структуры), как правило, является выражение list-типа (set-типа), тестируемое функциями type, typematch и whattype-процедурой, рассмотренными выше: по тестирующим функциям {type|typematch}(L, 'list') и whattype(L) возвращается соответственно значение true и list, если L – списочная структура. Аналогично обстоит дело и со структурами set-типа. Например, многие встроенные, библиотечные и модульные функции Maple-языка пакета возвращают результат типа {list, set}, как это весьма хорошо иллюстрирует следующий простой фрагмент:
> L:= [64, [sqrt(25), 2006], [a, b], {x, y}, 10.17\2006];
L := [64, [5, 2006], [a, b], {x, y}, 10.172006]
> type(L, 'list'), typematch(L, 'list'), whattype(L); ⇒ true, true, list
> Art:= "IAN 7 april 2006": sscanf(Art, "%a%d%a%d"); ⇒ [IAN, 7, april, 2006] > convert(G*sin(x)+S*sin(y)-ln(a+b)*TRG, 'list'); ⇒ [G sin(x), S sin(y), -ln(a+b) TRG]
> S:= "123456789": map(F, map(parse, [S[k]$k=1..9]));
[F(1), F(2), F(3), F(4), F(5), F(6), F(7), F(8), F(9)]
> fsolve({10*x^2 + 64*y - 59, 17*y^2 + 64*x -59}, { x, y});
{x = 0.7356456027, y = 0.8373164917}
> type(%, 'set'), typematch(%, 'set'), whattype(%); ⇒ true, true, set
> H:= "awertewasderaryretuur": Search2(H, {a, r, t}); ⇒ [1, 4, 5, 8, 12, 13, 14, 16, 18, 21]
В частном случае результатом вычисления или данными может быть и пустой []-список. По функции convert(B, 'list') можно конвертировать в списочную структуру вектор, таблицу или произвольное В-выражение, операнды которого будут элементами списка, как это иллюстрирует четвертый пример предыдущего фрагмента. Это же имеет место и в случае конвертации в set-структуру. С особенностями структур типов {list,set} можно ознакомиться в [39]. Структуры list-типа и set-типа во многих отношениях подобны, используя один и тот же базовый набор средств для их обработки. Ниже для удобства мы будем говорить о списочных структурах, везде (если не оговорено противного) предполагая и структуры set-типа. Наиболее существенная разница обоих типов структур состоит в следующем: