欢迎光临散文网 会员登陆 & 注册

【TIS-100 攻略】TIS-NET 第 21 关:质因数计算器

2022-11-13 21:50 作者:ココアお姉ちゃん  | 我要投稿

本文首发于 B 站《TIS-100》文集(https://www.bilibili.com/read/readlist/rl626023)。原创不易,转载请注明出处。

TIS-NET 第 21 关《质因数计算器》(Prime Factor Calculator)关卡展示

本关要求列出 IN 里提供的数字的所有质因数,将这些质因数依次输出,并以 0 作为结束标记。IN 里的数字一定在 2~99 范围内。

我们首先想到的是将 2~99 中的所有质数列出来,并令原数依次和这些数做除法运算,检查能否被指定的质数整除。但是 2~99 范围内有 25 个质数,一个节点根本写不下。我们必须要想办法缩减这张质数表的大小。

这里先说一个结论:2~99 范围内的数,要么是质数,要么一定能被 2、3、5、7 中的任何一个数整除。因为不含 2、3、5、7 这四个质因子的最小合数为 11×11=121。因此原始数字我们只需要判断是否能被 2、3、5、7 整除即可。2~99 范围内,如果一个数字不能被 2、3、5、7 中的任何一个数整除,那么它要么是 1,要么是质数。我们的质数表里只需要列出 2、3、5、7 这四个质数就 OK 了。

本题的算法如下:

  • 从 in 读入一个数字 a;

  • 检查 a 能否被 2 整除,若能,则将 a 除以 2,并向输出口输出 2 这个因子,然后反复执行此步,直到 a 不能被 2 整除为止;

  • 检查 a 能否被 3 整除。若能,则将 a 除以 3,并向输出口输出 3 这个因子,然后反复执行此步,直到 a 不能被 3 整除为止;

  • 检查 a 能否被 5 整除。若能,则将 a 除以 5,并向输出口输出 5 这个因子,然后反复执行此步,直到 a 不能被 5 整除为止;

  • 检查 a 能否被 7 整除。若能,则将 a 除以 7,并向输出口输出 7 这个因子,然后反复执行此步,直到 a 不能被 7 整除为止;

  • 至此,a 不是 1 就是一个大于 7 的质数。仅当 a 不为 1 时,输出最后的 a。

本关的代码如下:

上方节点首先将本轮的 a 向下传(mov up down),并不断提供 2、3、5、7 的质因子(mov 2 down, mov 3 down, mov 5 down, mov 7 down),用于检查 a 是否能被这些数整除。最后提供一个 0 的结束信号(mov 0 down)。

中央节点依次计算 a 能否被 2、3、5、7 整除:

  1. 它将收到的 a 放入 bak(mov up acc)

  2. (swp)

  3. 并从上方的质数表里读入一个 b,放入 acc(mov up acc)。

  4. 如果从上边收到了 0,说明到达了质数表的末端,跳到第 13 行执行(jez d)。

  5. 尚未收到 0 时,将 b 和 a 依次发给右边的节点(mov acc right)

  6. (swp)

  7. (mov acc right),让右边计算 a 能否被 b 整除,并接收右边的反馈信号:

  8. 当 a 不能被 b 整除时,你会收到 -6 信号,此时向上跳 6 行,从质数表里读入一个新的 b,然后计算 a 能否被新的 b 整除。

  9. 当 a 能被 b 整除时,你会收到 1 信号,同时右边会把 a 除以 b 的商 q 发过来。此时向下跳 1 行,用 q 覆盖 a(mov left acc),

  10. 并将当前的有效质因子 b(swp)

  11. 向下发送(mov acc down)。

  12. 最后跳回第 5 行继续计算新的 a 能否被 b 整除(jmp 5)。

  13. 如此反复,直到所有的质因子 b 都被尝试过了以后,a 会变成 1 或一个大于 7 的质数。此时跳到第 13 行,将最后的 a(swp)

  14. 向下发送(mov acc down)。

右边的两个节点用于配合计算 a 除以 b 的值。其中中间靠右的节点用来计算余数 r,右下角的节点用来反复提供除数 b,以及计算商 q。

  1. 中间靠右的节点将收到的除数 b 发给左下角(mov left down),

  2. 然后将被除数 a 放入 acc,作为 r 的初始值(mov right acc)。

  3. 接下来,每将 r 减去一次 b(sub down),

  4. 就判断 r 的符号。是正号时按顺序执行,是负号时跳到第 12 行(jlz c),

  5. 是 0 时跳到第 8 行(jez 8)。

  6. r 是正号时,向下发送 -4 让下方保留住当前的 b(mov -4 down),

  7. 然后跳回第 3 行继续减(jmp 3);

  8. r 是 0 时,说明 a 能被 b 整除,向下发送 1 令下方将当前的商传上来(mov 1 down),

  9. 向左发送 1 表示当前因子有效(mov 1 left),

  10. 并将得到的商 q 一并发给左边,作为下一轮的 a(mov down left);

  11. (jmp 1)

  12. r 是负号时,说明 a 不能被 b 整除,向左发送 -6 表示当前因子无效(mov -6 left),

  13. 向下发送 3 令下方将本轮的 b 和 q 丢弃(mov 3 down)。

现在来看反复提供除数以及计算商的右下角节点:

  1. 右下角的节点收到 b 后(mov up acc),

  2. 每发送一次 b(mov acc up),

  3. 就令 bak 里的商 q 加上 1(swp)

  4. (add 1)

  5. (swp)

  6. 然后听从上方的指令(jro up):收到 -4 时,说明当前除法尚未计算完成。我们保留住当前的 b 和 q,向上跳 4 行,继续执行发送 b 和 q+1 的任务;

  7. 收到 1 时,说明 a 能被 b 整除。我们向下跳 1 行,将计算好的 q(swp)

  8. 发给上方(mov acc up),作为下一次除法计算的 a 值,然后清除 b 和 q。

  9. 收到 3 时,说明 a 不能被 b 整除。我们向下跳 3 行,直接清除掉本轮的 b(sub acc)

  10. 和 q(swp)

最后是下方居中的输出节点。这个节点会不断收到正中央传来的 1 或质因子。如果收到的是 2、3、5、7 中的一个,说明还有 1 或别的质因子,我们不能输出末端的 0。直到收到最终的 1 或一个大于 7 的质因子时,我们才能输出末端的 0。我们依次检查:

  1. 如果收到的数字是 1(mov -1 acc)

  2. (add 1)

  3. 则不输出该 1,直接跳到第 8 行输出序列末端的 0(jez 8, mov 0 down)。

  4. 收到的数字是大于 1 的数字时,说明这是一个质因子,我们将其输出(add 1)

  5. (mov acc down)

  6. 然后紧接着判断:如果该质因子是 2、3、5、7 中的一个,则尚未到达序列末端。因此,如果该质因子小于 11(sub 11),

  7. 则跳回第 1 行继续等待下一个质因子(jlz 1),

  8. 直到得到了 1 或一个大于等于 11 的质因子后,我们输出序列末端的 0(mov 0 down)。

点击左下角的【RUN】,稍等片刻,便会弹出结算界面:


【TIS-100 攻略】TIS-NET 第 21 关:质因数计算器的评论 (共 条)

分享到微博请遵守国家法律