Максима: индивидуальные takewhile
Я не смог найти никакой документации для takewhile в Maxima. Итак, я попытался написать свою собственную, в которой указаны как элементы, так и их позиция. Он начинает получать данные из любой точки списка, как только критерии удовлетворены. Я получил две функции с тонкой разницей,
takewhile(x,p):=block([s:1,temp:[],temp1:[],count:1,xx:create_list([x[i],i],i,makelist(i,i,length(x)))],
for i in xx do if apply(p,[first(i)]) then temp:cons(i,temp) ,temp:reverse(temp),
if(length(temp)>=2 and flatten(temp)#[]) then
(while(count<length(temp) and last(temp[s])+1=last(temp[s+1]) ) do
(temp1:cons(temp[s],temp1),count:count+1,s:s+1),
if(s<=length(temp)) then (temp1:cons(temp[s],temp1)) else print("Exceeded")) else temp1:temp,reverse(temp1))$
Использование::
takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x>3));
ВЫХОД::
[[4,5],[5,6],[7,7],[4,8]]
а во вторых как,
takewhile1(x,p):=block([s:1,temp:[],temp1:[],count:1,xx:create_list([x[i],i],i,makelist(i,i,length(x)))],
for i in xx do (if parse_string(concat(first(i),p)) then temp:cons(i,temp)) ,temp:reverse(temp),
if(length(temp)>=2 and flatten(temp)#[]) then
(while(last(temp[s])+1=last(temp[s+1]) and count<length(temp)) do
(temp1:cons(temp[s],temp1),count:count+1,s:s+1),
if(s<length(temp)) then temp1:cons(temp[s],temp1)) else temp1:temp,reverse(temp1))$
Использование::
takewhile1([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],\<5);
ВЫХОД::
[[2,1],[1,2],[2,3],[3,4],[4,5]]
Тонкая разница заключается в использовании parse_string
создать лямбда-функцию вместо применения лямбда-функции, взятой в качестве параметра из функции.
Problem
:Я могу сделать,
takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x^2+3*x>6));
ВЫХОД::
[[2,1]]
Но я не понимаю, как мне этого добиться, если я использую takewhile1
как он вернется,
concat: argument must be an atom; found ^2>5
2 ответа
Я думаю, что императивная версия была бы намного более читабельной
load("basic");
takewhile(lst, pr):= block([l: [], c: []],
for el in reverse(lst) do if pr(el) then push(el, c)
else (push(c, l), c: []),
push(c, l),
delete([], l));
тесты:
(%i3) takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x>10));
(%o3) []
(%i4) takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x>0));
(%o4) [[2, 1, 2, 3, 4, 5, 7, 4, 1, 4, 5, 2, 1, 7, 8]]
(%i5) takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x>3));
(%o5) [[4, 5, 7, 4], [4, 5], [7, 8]]
(%i6) takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x^2+3*x>6));
(%o6) [[2], [2, 3, 4, 5, 7, 4], [4, 5, 2], [7, 8]]
Обновление: я неправильно понял ваше определение takewhile
, Вот моя очередная попытка
takewhile(lst, pr):= block([c: [], n: length(lst)], local(pr),
reverse(catch(for idx thru n do block([el: part(lst, idx)],
if not pr(el) and not emptyp(c) then throw(c)
else if pr(el) then push([el, idx], c)),
c)));
тесты:
(%i25) takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x>10));
(%o25) []
(%i26) takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x>0));
(%o26) [[2, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [7, 7], [4, 8],
[1, 9], [4, 10], [5, 11], [2, 12], [1, 13], [7, 14], [8, 15]]
(%i27) takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x>3));
(%o27) [[4, 5], [5, 6], [7, 7], [4, 8]]
(%i28) takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x^2+3*x>6));
(%o28) [[2, 1]]
(%i29) takewhile([2,1,2,3,4,5,7,4,1,4,5,2,1,7,8],lambda([x],x<5));
(%o29) [[2, 1], [1, 2], [2, 3], [3, 4], [4, 5]]
Построение выражений с помощью concat и оценка их с помощью parse_string почти наверняка не является хорошим способом решения проблемы. Мой совет не пытайтесь выяснить, почему takewhile1 не работает, это не стоит хлопот.
О встроенных функциях для этой проблемы, sublist
возвращает элементы, удовлетворяющие предикату и sublist_indices
возвращает свои позиции в списке, а join
склеивает два списка. Так что, возможно, вы можете написать:
take_while (x, p) := join (sublist (x, p), sublist_indices (x, p));