Maxima:定义一个函数,该函数 returns 一个范围内的随机整数,使得该值不同于另一个值或其他值的列表

Maxima: define a function that returns a random integer in a range, such that the value is distinct from another value or a list of other values

N.B. 标题中的问题在下面的“编辑:更大的问题”部分得到解决


在 Maxima 中是否有一个函数可以 return 变量的类型?

我不确定 type 是否是正确的词(我对此很陌生,但感觉它可能具有特定的技术意义),我正在寻找的是一个函数如果变量 x 是数字或数组,则可以 return truefalse,例如如果 x : 6;

IsArray(x) = false
IsNumber(x) = true

或者,例如如果 y : [1,2,3];

IsArray(y) = true;
IsNumber(y) = false;

我尝试搜索 Maxima 文档,但没有找到任何内容。任何帮助将不胜感激。


编辑:更大的问题。

我编写了一个函数,它将 return 一个范围内的随机值 y,同时确保 y 不同于另一个值 b:

DistinctValue(x,y,LowerLim,UpperLim):= block(
                  [newY:y], 
                  if x = newY 
                  then newY:DistinctValue(x,rand_range(LowerLim,UpperLim),LowerLim,UpperLim) 
                  else newY:y, return(newY));

其中 rand_range(LowerLim,UpperLim) 是另一个选择随机整数的自定义函数 LowerLim ≤ x ≤ UpperLim.

我很快就意识到有时我会需要几个这样的不同值,所以我调整了上面的代码,以便它可以将数组作为参数:

DistinctValue(x,y,LowerLim,UpperLim):= block([newY:y], 
    for i:1 thru length(x)
    do  if x[i] = newY
         then newY:DistinctValue(x,rand_range(LowerLim,UpperLim),LowerLim,UpperLim), 
    return(newY));

虽然我知道后者可用于从范围中排除单个数字的情况,只需将其放在方括号中即可,但我希望学会编写一个可以采用 x作为一个数字一个数组。我认为最简单的方法是使用 if / else 语句来评估变量 x 的类型,例如

DistinctValue(x,y,LowerLim,UpperLim):= block([newY:y], 
/* if it's a list, run the list version of the function */
 if IsList(x) 
 then
    for i:1 thru length(x)
    do  if x[i] = newY
         then  newY : DistinctValue(x, rand_range(LowerLim,UpperLim), LowerLim, UpperLim)
/* otherwise run the number version of the function */
 else  
      if x = newY 
      then newY : DistinctValue(x, rand_range(LowerLim,UpperLim), LowerLim,UpperLim) 
      else newY:y,, 
    return(newY));

虽然这看起来是多余的,但我们正在另一个相当复杂的环境中实现 Maxima,它会被比我经验更少的人使用。此外,我希望遇到在不久的将来,它更有必要而不是一种选择的其他情况。

关于 DistinctValue 函数,以下是我将如何实现一个函数,该函数 returns 一个范围内的随机值,该范围不同于单个值或所有值列表。

DistinctValue(x, LowerLim, UpperLim) :=
    if listp(x)
        then block([y: rand_range(LowerLim, UpperLim)],
                    if member(y, x) /* need to try again */
                        then DistinctValue(x, LowerLim, UpperLim)
                        else y)
        else DistinctValue([x], LowerLim, UpperLim);

这与上面显示的有些不同;这可能意味着我误解了要求。我会让你来判断。

rand_range可以表示为

rand_range(LowerLim, UpperLim) := LowerLim + random(UpperLim - LowerLim + 1);

UpperLim - LowerLim + 1确保可以返回UpperLim,否则rand_range的最大随机值是UpperLim减1,假设LowerLimUpperLim 是整数。

编辑:似乎有效——在这里我已经 load(descriptive); 获得 discrete_freq.

(%i32) makelist (DistinctValue ([13, 15, 17], 12, 18), 100);
(%o32) [18, 18, 14, 16, 18, 16, 12, 12, 18, 18, 12, 14, 12, 12, 
18, 18, 14, 12, 12, 14, 16, 18, 12, 16, 12, 16, 14, 18, 16, 12, 
14, 16, 14, 16, 16, 12, 14, 18, 14, 14, 14, 12, 16, 18, 14, 18, 
18, 14, 14, 18, 12, 16, 18, 12, 16, 16, 12, 14, 16, 18, 16, 14, 
16, 12, 16, 12, 14, 18, 16, 14, 12, 18, 14, 12, 16, 18, 12, 12, 
14, 14, 18, 16, 18, 14, 14, 18, 16, 14, 12, 12, 14, 12, 18, 18, 
12, 18, 12, 18, 18, 18]
(%i33) discrete_freq (%);
(%o33)        [[12, 14, 16, 18], [26, 25, 21, 28]]