Mathematica 中的 While 循环:多个输出
我在 Mathematica 中研究了一个随机数生成器,但受到许多条件的抑制。现在我的代码如下所示:
list = RandomSample[Range[36], 7];
f := If[1 <= Count[Select[list, # <= 12 &], _Integer] <= 2,
If[Count[Select[list, # > 31 &], _Integer] >= 1,
If[Count[Select[list, Divisible[#, {2, 7}] &], _Integer] <= 3,
Sort[list], False], False], False]
While[f == False,
list = RandomSample[Range[36], 7];
If[list == f, f]];
f
它是这样构建的: 生成
- 1-36 区间内 7 个整数的随机列表
- f 定义了一些必须满足的条件:该范围内至少有一个且最多有两个元素1-12。至少有一个大于 31 的元素。最多 3 个元素可以被 2-7 范围内的整数整除。
- 如果满足条件,f 等于列表,否则为 False。
- 接下来是“While”循环。如果 f 为 False,则生成一个新列表,并且此循环继续,直到 fi 不再为 False。
- 调用存储在 f 中的结果。
现在的情况是:这只产生一行输出。我对获得多个输出感兴趣,例如 5-10。我尝试使用 Table 命令以某种方式执行此操作,但问题是没有任何东西可以同时定义函数 f 和 while 循环。因此,通过在 f 上运行 table,我只能多次得到相同的结果。
关于如何继续这里的任何意见?
I have worked on a random number generator in Mathematica, suppressed by a number of conditions. Right now my code looks like this:
list = RandomSample[Range[36], 7];
f := If[1 <= Count[Select[list, # <= 12 &], _Integer] <= 2,
If[Count[Select[list, # > 31 &], _Integer] >= 1,
If[Count[Select[list, Divisible[#, {2, 7}] &], _Integer] <= 3,
Sort[list], False], False], False]
While[f == False,
list = RandomSample[Range[36], 7];
If[list == f, f]];
f
It is build up like this:
- A random list of 7 integers of the interval 1-36 is made
- f defines some conditions that have to be met: at least one and at most two elements in the range 1-12. At least one element greater than 31. At most 3 elements can be divisible be the integers in the range 2-7.
- If the conditions are met, f equals the list, False otherwise.
- Next thing is the "While" loop. If f is False, then a new list i generated, and this loop continues until f i no longer False.
- The result stored in f is called.
The thing is now: this only produces one line of output. I am interested in getting multiple outputs, e.g. 5-10. I have tried to do it in some way with the Table command, but the thing is that nothing defines both the function f and the while loop at the same time. So, by running table on f, I only get the same result a lot of times.
Any input on how to proceed here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我不认为您的
f
定义中的第三行正在做您认为它正在做的事情。例如,考虑返回
{True, False}
,而不是True
或False
。这意味着Select[list, Divisible[#, {2, 7}] &]
将始终返回空列表,并且计数[选择[列表,可除[#, {2, 7}] &],_Integer]
将始终返回
0
。如果我正确解释了列表的条件,您可以使用类似的内容
,并且 Alexy 建议使用
Sow
和Reap
,您可以执行类似的操作I don't think the third line in your definition of
f
is doing what you think it's doing. Consider for examplewhich returns
{True, False}
, not eitherTrue
orFalse
. This means thatSelect[list, Divisible[#, {2, 7}] &]
will always return an empty list andCount[Select[list, Divisible[#, {2, 7}] &], _Integer]
will always return
0
.If I interpret the conditions for the lists correctly, you could instead use something like
With this and Alexy's suggestion to use
Sow
andReap
, you could do something like函数
f
将list
引用为自由变量而不是参数。虽然这不是一个不可克服的障碍,但它确实使打包此功能以便在Table
中使用变得很尴尬。让我们重新设计这些定义并应用一些简化。首先,让我们测试一个样本是否可接受:
与原始版本相比,主要的简化是嵌套的
If
语句已被扁平化为And
条件。新定义还利用了Count
可以测试列表值而无需调用嵌套Select
的事实。此外,存在性检查已使用MemberQ[...]
表示。引入了辅助函数来执行整除性检查,以减少主测试表达式的视觉复杂性。请注意,原始的整除性检查错误地返回了需要布尔值的列表。_Integer
头部测试已被删除,但如果认为需要,可以通过将每个n_
更改为n_Integer
来重新引入它们。现在我们只需要一种方法来循环生成样本,直到找到可接受的样本:
generateSample[]
现在可用于生成包含所需数量的结果的表格:概括模式
generateSample
中体现的模式可以参数化以接受任意生成器和过滤器函数:generator
参数保持未计算的形式,以便可以在每个通过循环。这个新函数可以这样使用:新函数的优点是它可以与任何生成器和过滤器函数一起使用。在这里,我们生成三个整数的元组,总和为七。
作为风格问题,除非绝对必要,否则有些人倾向于避免使用
Hold
属性定义函数。generatorSelect2
反映了该设计选择:它与
generatorSelect
之间的唯一区别是第一个参数现在预计计算为函数:The function
f
referenceslist
as a free variable instead of as a parameter. While this is not an insurmountable obstacle, it does make it awkward to package up this functionality so that it can be used in aTable
. Let's rework these definitions and apply some simplifications along the way.First, let's tackle the test as to whether a sample is acceptable:
The main simplification from the original is that the nested
If
statements have been flattened into anAnd
condition. The new definition also exploits the fact thatCount
can test list values without having to invoke a nestedSelect
. In addition, existence checks have been expressed usingMemberQ[...]
. A helper function has been introduced to perform the divisibility check in an effort to reduce the visual complexity of the main test expression. Note that the original divisibility check was incorrectly returning a list where a boolean value was expected. The_Integer
head tests were removed, but if they are deemed desirable they can be re-introduced by changing eachn_
ton_Integer
.Now we just need a way to generate samples in a loop until an acceptable one is found:
generateSample[]
can now be used to generate a table of as many results as needed:Generalizing the Pattern
The pattern embodied in
generateSample
could be parameterized to accept arbitrary generator and filter functions:The
generator
argument is kept in unevaluated form so that can be evaluated afresh on each pass through the loop. This new function can be used thus:The advantage of the new function is that it can be used with any generator and filter functions. Here we generate tuples of three integers that sum to seven.
As a matter of style, some prefer to avoid defining functions with
Hold
attributes unless absolutely necessary.generatorSelect2
reflects that design choice:The only difference between this and
generatorSelect
is that the first argument is now expected to evaluate to a function:为此,您可以使用
Reap
和Sow
:我还建议查看
NestWhileList
:可能会发现它非常适合您的需求。You can use
Reap
andSow
for this:I recommend also to look at the
NestWhileList
: it may be found very appropriate for your needs.这工作正常。请注意使用 SameQ (===) 来比较可能的混合类型、列表和布尔值。例如
{4, 7, 17, 22, 25, 27, 34} == False
不会计算。This works ok. Note the use of SameQ (===) for comparing possibly mixed types, lists and booleans. E.g.
{4, 7, 17, 22, 25, 27, 34} == False
does not evaluate.