Maxima:如何滚动(或移动)列表

Maxima: how to roll (or shift) a list

滚动列表的最简单方法是什么?

考虑以下列表:

myList : [0,1,4,6,3]

我正在寻找一个 roll() 函数,可以:

(%i0) roll(myList,1)
(%o0) [3,0,1,4,6]


(%i1) roll(myList,-1)
(%o1) [1,4,6,3,0]

我可以通过调用获得相同的结果:

myItem : pop(myList)
myList : append(myList,myItem)

问题是这仅在一个方向上有效(据我所知没有 pop_back() 功能 (?))并且它是两个衬垫。有更好的方法吗?

嗯,没有内置函数。但我认为你可以使用 rest 来获得你想要的效果。

(%i10) rotate (e, n) :=
   if atom(e) then e
   else block ([a : args(e)],
          apply (op(e),
                 append (rest (a, length(a) - n), rest (a, -n)))) $
(%i11) foo : [a, b, c, d, e, f, g];
(%o11)                       [a, b, c, d, e, f, g]
(%i12) rotate (foo, 2);
(%o12)                       [f, g, a, b, c, d, e]
(%i13) rotate (foo, 7);
(%o13)                       [a, b, c, d, e, f, g]

这适用于所有表达式,而不仅仅是列表。

(%i16) rotate (f(1,2,3), 2);
(%o16)                            f(2, 3, 1)

此实现不接受大于参数数量的负数 nn,尽管我认为这很容易处理。

我假设 rotate 将较小索引处的元素移动到较大索引中。同样,如果您希望默认值朝另一个方向移动,我认为这样做很容易。

编辑:实际上没有必要分开op(e)args(e)。当 e 不是列表并且它做正确的事情时,您可以调用 rest(e, ...)。所以更简洁的版本是:

rotate (e, n) :=
   if atom(e) then e
   else append (rest (e, length(e) - n), rest (e, -n)) $