调查流程的算法
Algorithm for survey flow
我必须编写一个允许业务用户创建调查的工具。
如果填写调查的人以特定方式回答了前面的问题,则只应询问一些问题。但是无论选择什么答案,都应该显示一些问题。
到目前为止,我想出了一个图形结构,这里是它的外观的理论示例:
(本人只有图论基础知识,用词不准确请见谅)
A、B、C等轮次代表问题,链接上的值代表访问问题的前提条件。
NULL 表示没有前提条件,像“0”或“1”这样的值表示前一个问题必须有值为“0”或“1”的答案才能显示该问题。
具体例子:
我在 A 轮。我有两个可能的答案。第一个的值为“0”。第二个,值为“1”。如果我选择值为“0”的答案,那么我将转到问题 B。
我现在在B轮,不管答案是什么,我都会去E轮,因为没有前提条件。
E是叶子节点,所以我回到B。B有另一个没有前提条件的子节点F,所以我转到问题F。让我们在那里结束流程。
我也可以有一个有多个前提条件的问题。这由问题 N 表示。只有当问题 F 的答案为“5”且问题 I 的答案为 "DE" 时才能访问。在这种情况下,在回答问题 F 之后,因为在此状态下只有一个前提条件有效,我们将在图表中返回,只有在回答问题 I 的 "DE" 之后,我们才能转到问题 N。
我的问题是关于用于此类调查的算法。是否有涵盖此用例的现有算法?我认为这看起来像 DFS 图遍历,但条件让我怀疑。
另外,我是不是把事情复杂化了,可以用更简单的方式表达吗?
在这个阶段我真的很想得到一些建议。
感谢您的帮助!
这是我解决您的问题的大致思路。
根据您提供的图表,我假设对于每个问题(节点),您可以根据给定的答案判断哪些问题(节点)可能会被解锁。 "may get unlocked" 我的意思是他们实际上被解锁了或者你刚刚满足解锁问题的条件之一。
另一方面,您可以为每个问题存储解锁它所需满足的条件数(我们将其命名为计数器)。然后,每当你得到答案时,你检查可能被这个答案解锁的问题列表,并减少他们的计数器。
当任何计数器递减到零时,您将解锁的问题添加到队列或堆栈中(您可以选择您喜欢 FIFO 还是 LIFO 顺序)。当然,您从包含无条件问题的队列开始(在您的情况下只有 "A")。
使用 FIFO(队列),您将获得 BFS-like 遍历图形的顺序。使用 LIFO(堆栈),您将获得 DFS-like 订单。随便你。
根据您的描述,我将对您提出的图表的概念稍作修改如下:
- 做成有向图(即每条弧都有源和目标的图)。
- 每个问题有一个节点并且每个答案有一个节点(每个问题的每个答案都是一个不同的节点)。每个问题节点需要有一个标志来判断它是"question type"还是"answer type"和一个标志来标记它是否被访问过
- 每个问题节点都将连接到它的每个答案(方向 [问题] -> [答案])。
- 每个答案前提条件 ("to reach question B you need to answer 0 in question A") 将由从一个答案(节点 [问题 A 的答案 0])到问题 "unlocks"(节点 [问题 B])的弧表示.如果一个问题需要多个答案,它就会有多个传入弧。
- 每个问题前提条件 ("to reach question D you need to answer to question A, no matter the choice") 将由从一个问题(节点 [问题 A])到另一个问题(节点 [问题 D])的弧表示。
那么算法将遵循以下几行:
- 有一堆待定节点P,最初包含与调查的第一个问题对应的节点。
- 弹出P、Q的第一个元素,该元素应该始终是一个问题节点,并将其标记为已访问。
- 获取Q的后继列表(通过出弧与当前节点相连的节点)拆分为"answer successors",QtoA、"question successors"、QtoQ.
- 将 QtoQ 中的所有元素添加到 P(如果有任何方法可以对这些元素进行排序,例如通过一些 "question id",确保它们的添加方式是第一个元素在堆栈顶部结束)。
- 提出问题(您甚至可以将问题存储在图表中并从中检索您需要的所有信息)。
- 从 QtoA 中获取所选答案 A 的节点,将其标记为已访问并收集其所有后继者的列表转,AtoQ.
- 对于AtoQ中的每个节点R(同样,如果有的话考虑在这里排序),如果R(即通过传入弧连接到R的节点)标记为已访问,然后添加R至 P.
- 如果P中有任何节点,则转到步骤2。
这应该重现您描述的顺序。如果你想有几个可能的解锁答案的能力(例如 "from A you would go to B if you answer 1 or 2"),你需要做一些更多的调整(即,在第 6 步中你需要替换 "visited" 检查 "answer type" R 的前辈到类似“R 可以通过 R[ 的前辈的前辈的已访问节点到达=57=]"),但它应该仍然可以正常工作。
也许您已经知道了,但是如果您有兴趣使用图形作为唯一的数据源(可能是也可能不是这种情况),您可能会发现有趣的 graph-oriented 数据库,例如 Neo4j.
我必须编写一个允许业务用户创建调查的工具。 如果填写调查的人以特定方式回答了前面的问题,则只应询问一些问题。但是无论选择什么答案,都应该显示一些问题。
到目前为止,我想出了一个图形结构,这里是它的外观的理论示例:
(本人只有图论基础知识,用词不准确请见谅)
A、B、C等轮次代表问题,链接上的值代表访问问题的前提条件。
NULL 表示没有前提条件,像“0”或“1”这样的值表示前一个问题必须有值为“0”或“1”的答案才能显示该问题。
具体例子: 我在 A 轮。我有两个可能的答案。第一个的值为“0”。第二个,值为“1”。如果我选择值为“0”的答案,那么我将转到问题 B。
我现在在B轮,不管答案是什么,我都会去E轮,因为没有前提条件。
E是叶子节点,所以我回到B。B有另一个没有前提条件的子节点F,所以我转到问题F。让我们在那里结束流程。
我也可以有一个有多个前提条件的问题。这由问题 N 表示。只有当问题 F 的答案为“5”且问题 I 的答案为 "DE" 时才能访问。在这种情况下,在回答问题 F 之后,因为在此状态下只有一个前提条件有效,我们将在图表中返回,只有在回答问题 I 的 "DE" 之后,我们才能转到问题 N。
我的问题是关于用于此类调查的算法。是否有涵盖此用例的现有算法?我认为这看起来像 DFS 图遍历,但条件让我怀疑。
另外,我是不是把事情复杂化了,可以用更简单的方式表达吗? 在这个阶段我真的很想得到一些建议。
感谢您的帮助!
这是我解决您的问题的大致思路。
根据您提供的图表,我假设对于每个问题(节点),您可以根据给定的答案判断哪些问题(节点)可能会被解锁。 "may get unlocked" 我的意思是他们实际上被解锁了或者你刚刚满足解锁问题的条件之一。
另一方面,您可以为每个问题存储解锁它所需满足的条件数(我们将其命名为计数器)。然后,每当你得到答案时,你检查可能被这个答案解锁的问题列表,并减少他们的计数器。
当任何计数器递减到零时,您将解锁的问题添加到队列或堆栈中(您可以选择您喜欢 FIFO 还是 LIFO 顺序)。当然,您从包含无条件问题的队列开始(在您的情况下只有 "A")。
使用 FIFO(队列),您将获得 BFS-like 遍历图形的顺序。使用 LIFO(堆栈),您将获得 DFS-like 订单。随便你。
根据您的描述,我将对您提出的图表的概念稍作修改如下:
- 做成有向图(即每条弧都有源和目标的图)。
- 每个问题有一个节点并且每个答案有一个节点(每个问题的每个答案都是一个不同的节点)。每个问题节点需要有一个标志来判断它是"question type"还是"answer type"和一个标志来标记它是否被访问过
- 每个问题节点都将连接到它的每个答案(方向 [问题] -> [答案])。
- 每个答案前提条件 ("to reach question B you need to answer 0 in question A") 将由从一个答案(节点 [问题 A 的答案 0])到问题 "unlocks"(节点 [问题 B])的弧表示.如果一个问题需要多个答案,它就会有多个传入弧。
- 每个问题前提条件 ("to reach question D you need to answer to question A, no matter the choice") 将由从一个问题(节点 [问题 A])到另一个问题(节点 [问题 D])的弧表示。
那么算法将遵循以下几行:
- 有一堆待定节点P,最初包含与调查的第一个问题对应的节点。
- 弹出P、Q的第一个元素,该元素应该始终是一个问题节点,并将其标记为已访问。
- 获取Q的后继列表(通过出弧与当前节点相连的节点)拆分为"answer successors",QtoA、"question successors"、QtoQ.
- 将 QtoQ 中的所有元素添加到 P(如果有任何方法可以对这些元素进行排序,例如通过一些 "question id",确保它们的添加方式是第一个元素在堆栈顶部结束)。
- 提出问题(您甚至可以将问题存储在图表中并从中检索您需要的所有信息)。
- 从 QtoA 中获取所选答案 A 的节点,将其标记为已访问并收集其所有后继者的列表转,AtoQ.
- 对于AtoQ中的每个节点R(同样,如果有的话考虑在这里排序),如果R(即通过传入弧连接到R的节点)标记为已访问,然后添加R至 P.
- 如果P中有任何节点,则转到步骤2。
这应该重现您描述的顺序。如果你想有几个可能的解锁答案的能力(例如 "from A you would go to B if you answer 1 or 2"),你需要做一些更多的调整(即,在第 6 步中你需要替换 "visited" 检查 "answer type" R 的前辈到类似“R 可以通过 R[ 的前辈的前辈的已访问节点到达=57=]"),但它应该仍然可以正常工作。
也许您已经知道了,但是如果您有兴趣使用图形作为唯一的数据源(可能是也可能不是这种情况),您可能会发现有趣的 graph-oriented 数据库,例如 Neo4j.