将“值 1”固定在位置一,通过循环一次生成 24 个组合。
然后,“首先为它腾出空间”,将值 1 放入第 2 列。然后将值 1 放入第 3 列。第 4 列。第 5 列。
或者
取初始结果,即一组,然后“旋转”结果中的所有值(1 = 2、2 = 3、3 = 4、4 = 5、5 = 1)。那是第二个结果集。再做三遍。
使用任何一种方法,您都可以包含一次迭代的“完整结果”以获得 24 个结果的“模式”。
例如,可以将以下内容添加到 Valdis Grinbergs 的代码中:
在工作存储部分:
01 SAVE-SOLUTION.
02 SAVE-IT PIC X.
02 FILLER PIC X(4).
在程序部分:
将第一个 PERFORM 更改为
MOVE 1 TO I
显示每个解决方案后:
PERFORM SOLUTIONS-FOR-REMAINING-VALUES
也就是说,对于“列插入”版本:
SOLUTIONS-FOR-REMAINING-VALUES.
MOVE SOLUTION TO SAVE-SOLUTION
MOVE SOLUTION (2:1) TO SOLUTION (1:1)
MOVE SAVE-IT TO SOLUTION (2:1)
ADD 1 TO SOLUTION-COUNT
DISPLAY SOLUTION
MOVE SAVE-SOLUTION TO SOLUTION
MOVE SOLUTION (3:1) TO SOLUTION (1:1)
MOVE SAVE-IT TO SOLUTION (3:1)
ADD 1 TO SOLUTION-COUNT
DISPLAY SOLUTION
MOVE SAVE-SOLUTION TO SOLUTION
MOVE SOLUTION (4:1) TO SOLUTION (1:1)
MOVE SAVE-IT TO SOLUTION (4:1)
ADD 1 TO SOLUTION-COUNT
DISPLAY SOLUTION
MOVE SAVE-SOLUTION TO SOLUTION
MOVE SOLUTION (5:1) TO SOLUTION (1:1)
MOVE SAVE-IT TO SOLUTION (5:1)
ADD 1 TO SOLUTION-COUNT
DISPLAY SOLUTION
.
对于“重复换位”版本:
SOLUTIONS-FOR-REMAINING-VALUES.
PERFORM 4 TIMES
MOVE SOLUTION (1:1) TO SAVE-IT
MOVE SOLUTION (2:1) TO SOLUTION (1:1)
MOVE SOLUTION (3:1) TO SOLUTION (2:1)
MOVE SOLUTION (4:1) TO SOLUTION (3:1)
MOVE SOLUTION (5:1) TO SOLUTION (4:1)
MOVE SAVE-IT TO SOLUTION (5:1)
ADD 1 TO SOLUTION-COUNT
DISPLAY SOLUTION
END-PERFORM
.
当然,我添加的段落可以作为循环来完成,但我想集中展示正在发生的事情,而不是如何在 COBOL 中编写循环。
这两种不同的“解决方案”实际上是同一事物的两种实现。一旦建立了“模式”,就可以通过简单地改变固定模式内的内容来生成另外 4/5 的输出。
可以处理原始代码中的循环。
如果对于实际应用程序,性能是主要要求,那么只需在编写一行代码之前意识到“模式”是已知的。该代码只是节省了您手动编写 24 个结果的时间。为了性能,并且使用足够小的“模式”,只需将其编码,忘记循环。
而且我自己不会使用所有的“参考修改”,我只是把它从原来的地方留在那里。
现在,两个版本没有循环。基于前 24 个解决方案的“模式”是事先已知的,并且剩余的解决方案(已经知道,但不需要以相同的方式编码)可以很容易地从那。
旋转值。
ID DIVISION.
PROGRAM-ID. PROTATE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 CHAR-SET PIC X(5) VALUE 'ABCDE'.
01 SOLUTION PIC X(5).
01 SOLUTION-COUNT binary PIC 9(4) VALUE ZERO.
01 INDEXES.
02 COLUMN-1 binary PIC 9(4).
02 COLUMN-2 binary PIC 9(4).
02 COLUMN-3 binary PIC 9(4).
02 COLUMN-4 binary PIC 9(4).
02 COLUMN-5 binary PIC 9(4).
02 ICOL-3 binary PIC 9(4).
02 ICOL-4 binary PIC 9(4).
02 ICOL-5 binary PIC 9(4).
01 SAVE-SOLUTION.
02 SAVE-IT PIC X.
02 FILLER PIC X(4).
PROCEDURE DIVISION.
MAIN-para.
MOVE 1 TO COLUMN-1
MOVE 2 TO COLUMN-2
MOVE 3 TO ICOL-3
MOVE 4 TO ICOL-4
MOVE 5 TO ICOL-5
PERFORM SIX-SOLUTIONS
MOVE 3 TO COLUMN-2
MOVE 2 TO ICOL-3
MOVE 4 TO ICOL-4
MOVE 5 TO ICOL-5
PERFORM SIX-SOLUTIONS
MOVE 4 TO COLUMN-2
MOVE 2 TO ICOL-3
MOVE 3 TO ICOL-4
MOVE 5 TO ICOL-5
PERFORM SIX-SOLUTIONS
MOVE 5 TO COLUMN-2
MOVE 2 TO ICOL-3
MOVE 3 TO ICOL-4
MOVE 4 TO ICOL-5
PERFORM SIX-SOLUTIONS
DISPLAY SOLUTION-COUNT
STOP RUN
.
SIX-SOLUTIONS.
MOVE ICOL-3 TO COLUMN-3
MOVE ICOL-4 TO COLUMN-4
MOVE ICOL-5 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-5 TO COLUMN-4
MOVE ICOL-4 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-4 TO COLUMN-3
MOVE ICOL-3 TO COLUMN-4
MOVE ICOL-5 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-5 TO COLUMN-4
MOVE ICOL-3 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-5 TO COLUMN-3
MOVE ICOL-3 TO COLUMN-4
MOVE ICOL-4 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-4 TO COLUMN-4
MOVE ICOL-3 TO COLUMN-5
PERFORM A-SOLUTION
.
A-SOLUTION.
MOVE CHAR-SET ( 1 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE CHAR-SET ( COLUMN-2 : 1 ) TO SOLUTION ( 2 : 1 )
MOVE CHAR-SET ( COLUMN-3 : 1 ) TO SOLUTION ( 3 : 1 )
MOVE CHAR-SET ( COLUMN-4 : 1 ) TO SOLUTION ( 4 : 1 )
MOVE CHAR-SET ( COLUMN-5 : 1 ) TO SOLUTION ( 5 : 1 )
PERFORM SOLUTION-READY
PERFORM SOLUTIONS-FOR-REMAINING-VALUES
.
SOLUTIONS-FOR-REMAINING-VALUES.
MOVE SOLUTION TO SAVE-SOLUTION
MOVE SOLUTION ( 2 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE SAVE-IT TO SOLUTION ( 2 : 1 )
PERFORM SOLUTION-READY
MOVE SAVE-SOLUTION TO SOLUTION
MOVE SOLUTION ( 3 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE SAVE-IT TO SOLUTION ( 3 : 1 )
PERFORM SOLUTION-READY
MOVE SAVE-SOLUTION TO SOLUTION
MOVE SOLUTION ( 4 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE SAVE-IT TO SOLUTION ( 4 : 1 )
PERFORM SOLUTION-READY
MOVE SAVE-SOLUTION TO SOLUTION
MOVE SOLUTION ( 5 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE SAVE-IT TO SOLUTION ( 5 : 1 )
PERFORM SOLUTION-READY
.
SOLUTION-READY.
ADD 1 TO SOLUTION-COUNT
DISPLAY SOLUTION
.
列插入:
ID DIVISION.
PROGRAM-ID. PCOLINS.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 CHAR-SET PIC X(5) VALUE 'ABCDE'.
01 SOLUTION PIC X(5).
01 SOLUTION-COUNT binary PIC 9(4) VALUE ZERO.
01 INDEXES.
02 COLUMN-1 binary PIC 9(4).
02 COLUMN-2 binary PIC 9(4).
02 COLUMN-3 binary PIC 9(4).
02 COLUMN-4 binary PIC 9(4).
02 COLUMN-5 binary PIC 9(4).
02 ICOL-3 binary PIC 9(4).
02 ICOL-4 binary PIC 9(4).
02 ICOL-5 binary PIC 9(4).
01 SAVE-SOLUTION.
02 SAVE-IT PIC X.
02 FILLER PIC X(4).
PROCEDURE DIVISION.
MAIN-para.
MOVE 1 TO COLUMN-1
MOVE 2 TO COLUMN-2
MOVE 3 TO ICOL-3
MOVE 4 TO ICOL-4
MOVE 5 TO ICOL-5
PERFORM SIX-SOLUTIONS
MOVE 3 TO COLUMN-2
MOVE 2 TO ICOL-3
MOVE 4 TO ICOL-4
MOVE 5 TO ICOL-5
PERFORM SIX-SOLUTIONS
MOVE 4 TO COLUMN-2
MOVE 2 TO ICOL-3
MOVE 3 TO ICOL-4
MOVE 5 TO ICOL-5
PERFORM SIX-SOLUTIONS
MOVE 5 TO COLUMN-2
MOVE 2 TO ICOL-3
MOVE 3 TO ICOL-4
MOVE 4 TO ICOL-5
PERFORM SIX-SOLUTIONS
DISPLAY SOLUTION-COUNT
STOP RUN
.
SIX-SOLUTIONS.
MOVE ICOL-3 TO COLUMN-3
MOVE ICOL-4 TO COLUMN-4
MOVE ICOL-5 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-5 TO COLUMN-4
MOVE ICOL-4 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-4 TO COLUMN-3
MOVE ICOL-3 TO COLUMN-4
MOVE ICOL-5 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-5 TO COLUMN-4
MOVE ICOL-3 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-5 TO COLUMN-3
MOVE ICOL-3 TO COLUMN-4
MOVE ICOL-4 TO COLUMN-5
PERFORM A-SOLUTION
MOVE ICOL-4 TO COLUMN-4
MOVE ICOL-3 TO COLUMN-5
PERFORM A-SOLUTION
.
A-SOLUTION.
MOVE CHAR-SET ( 1 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE CHAR-SET ( COLUMN-2 : 1 ) TO SOLUTION ( 2 : 1 )
MOVE CHAR-SET ( COLUMN-3 : 1 ) TO SOLUTION ( 3 : 1 )
MOVE CHAR-SET ( COLUMN-4 : 1 ) TO SOLUTION ( 4 : 1 )
MOVE CHAR-SET ( COLUMN-5 : 1 ) TO SOLUTION ( 5 : 1 )
PERFORM SOLUTION-READY
PERFORM SOLUTIONS-FOR-REMAINING-VALUES
.
SOLUTIONS-FOR-REMAINING-VALUES.
MOVE SOLUTION TO SAVE-SOLUTION
MOVE SOLUTION ( 2 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE SAVE-IT TO SOLUTION ( 2 : 1 )
PERFORM SOLUTION-READY
MOVE SAVE-SOLUTION TO SOLUTION
MOVE SOLUTION ( 3 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE SAVE-IT TO SOLUTION ( 3 : 1 )
PERFORM SOLUTION-READY
MOVE SAVE-SOLUTION TO SOLUTION
MOVE SOLUTION ( 4 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE SAVE-IT TO SOLUTION ( 4 : 1 )
PERFORM SOLUTION-READY
MOVE SAVE-SOLUTION TO SOLUTION
MOVE SOLUTION ( 5 : 1 ) TO SOLUTION ( 1 : 1 )
MOVE SAVE-IT TO SOLUTION ( 5 : 1 )
PERFORM SOLUTION-READY
.
SOLUTION-READY.
ADD 1 TO SOLUTION-COUNT
DISPLAY SOLUTION
.
好的。问题的具体程序。有点。预期的答案可能是 Ingo/Valdis Grinbergs 的答案,用于学习如何“嵌套”循环。
程序在做什么?好吧,它得到了 1/5 的排列,然后依靠这些结果中的对称性来生成剩余的 4/5 排列,除了重新排列之外没有进一步的处理。
为什么没有循环?因为,既然是预先知道的,那么答案是预先知道的。与总是产生相同结果的循环不同,结果是“硬编码”的。
程序可以通用化吗?是的。算法是什么?
好吧,您可以描述代码,并弄清楚如何扩展它。或者你可以看看数据。
六对二的产生是做什么的?好吧,两个对只是两个值的排列。六、三个值的排列。做六四次是四个值的排列。
因此,要对五个值进行烫发,请将五个单独的值中的每一个应用于四个值的排列模式。要允许四个值,请将四个单独的值中的每一个应用于三个值的排列模式。要允许三个值,请将三个单独的值中的每一个应用于两个值的排列模式。要 perm 两个值,请将两个单独的值中的每一个应用于一个值的排列模式(!)。
因此,要 perm N 个值,请将 N 个单独的值中的每一个应用于 (N-1) 个值的排列模式。
在一般解决方案中,N = 1 需要零次迭代。N = 2 需要一次迭代。N = 3 需要两次迭代。N = 4 需要六次迭代。N = 5 需要 24 次迭代。N = N 需要 (N - 1)!迭代,其中 N = 1 是一种特殊情况。
要生成所有数据,而不是硬编码初始解决方案,需要求和。N = 5,从没有可用的较小排列的起点开始,需要 24 + 6 + 2 + 1 = 33 次迭代。
是的,这很容易用于递归解决方案。它还适用于完全没有循环的解决方案。这不是 COBOL 特定的,但对于任何语言都是一样的。
当然,对于每个不同的 N 值,您永远不需要每个程序多次调用。再说一次,使用递归没问题。
COBOL 中的递归问题是 COBOL 程序员普遍不熟悉如何做到这一点。
“光滑”版本的明显用途是如果必须处理“大”尺寸的 N(涉及阶乘,因此“大”会很快到达)。
另一件事是“清晰”。下一个人能否理解代码在做什么。
如果我能找到时间,我会做一个“不错”的版本..,