确保不再看到已查看的项目

时间:2009-05-31 04:19:13

标签: algorithm google-app-engine

我有一个解决我正在努力解决的问题的可能方案,但我想在这里运行它只是为了安全起见。面临的挑战是确保在考试申请中经历过一些测试问题的用户在后续测试中不再遇到这些问题。

我没有使用SQL数据库,这允许我使用左连接,子查询,临时表等。我正在使用Google App Engine的数据存储区,并希望在单个HTTP请求和单个线程中获取所需的信息,最好是在一秒钟内。

假设存在100,000个特定类型的词汇表问题(例如,同义词)。对于给定的考试部分,该应用程序将从池中选择30个问题。这就是我在想的事情:

  • 当第一个问题创建时,请在池中为其指定一个随机整数位置。
  • 在个人第一次考试时,选择一个随机数,然后选择按位置排序的前100个问题,其位置大于该数字。跟踪数字作为问题窗口的下限,并作为整个池的起始位置。跟踪结果集中最后一个问题的(最大)位置,作为新窗口的上限。
  • 从窗口中随机选择30个问题,然后将其作为部分提供。存储剩余的70个问题,以便稍后在考试中使用,并可能在随后的考试中使用。
  • 当用户浏览其他部分(比如练习)时,当前窗口中剩余问题的列表已耗尽,请从池中选择接下来的100个问题,这些问题的位置大于先前存储的上限。使旧的上限绑定到新的下限并找到新窗口的上限。
  • 当查询返回少于100个问题时,回绕到0的位置并继续直到遇到原始起点(任何人都不可能通过整个池,但重要的是要确定)。

这些职位被随机分配的主要原因是抵消问题写法风格变化的影响,例如,在较少经验与较晚经验相关时先前编写的问题。

应用程序会为问题指定一个位置,而不会检查该位置是否唯一。如果有足够多的问题,birthday paradox表明重复的职位将变得越来越普遍。我的想法是,偶尔会出现重复并不会有什么坏处,而且这会比确保给定位置是唯一的更简单,这可能需要重试以及随之而来的相关网络成本。更重要的是,没有重复的问题,而不是确保向用户展示一系列问题中的每个问题。

有更好的方法吗?可以不担心重复的职位吗?

4 个答案:

答案 0 :(得分:1)

使用0到1之间的浮点数而不是整数。它有一个很好的域,它不会随着你拥有的实体数量而改变,而且double有一个52位的尾数,在我们预料到碰撞之前它会给我们大约2 ^ 26个对象;远远超过你所处理的。

答案 1 :(得分:1)

我认为您不需要在100个问题池中“随意选择30”。 100开始随机选择 - 如果你采取前30,那些已经随机化。您的代码将更简单,随机性也不会更低。

答案 2 :(得分:1)

答案 3 :(得分:0)

这是一种需要考虑的方法。没有足够的时间来编写和编辑,所以要提前为任何问题道歉。使用您的100K问题创建一个模型,以便您可以使用密钥名称(例如question_000001,question_0000002等)访问它们。当学生注册时,使用三个TextProperties创建他/她的记录。创建记录时,从1-100K生成一组随机数字,并将其序列化为分隔文本字符串。第二个字符串是记录已回答的问题,但尚未进行任务队列处理。第三个字符串用于TQ处理后的已回答问题。

当用户登录时,发送待激活字符串的前N个字段(N =足够多的问题来服务任何类型的会话),以及整个已回答的问题字符串。在客户端,将它们分成一系列要问的问题,并回答问题的散列。如果问题在哈希中,请跳过它。当用户解决问题时,每个问题都由对您的在线处理程序的简单get_by_id调用提供服务。在回答每个问题时,客户端将其发送到GAE,您将问题编号附加到最近回答问题的文本字段,并设置布尔值以标记以便稍后进行TQ处理。每天或每天一次,运行任务队列过程,通过拆分要询问的问题文本字段来更新记录,并删除自上次更新以来回答的所有问题。将这些内容移至已完成问题的第三个文本。

请注意,您可以仅使用两个文本字段跳过大量此操作,并在发布答案时进行更新。但是,我的倾向是始终尽可能少地使用在线处理程序,并将内容推送到TQ。

没有计数器(通过获取分割GAE文本字段的长度始终可用),无查询(TQ布尔标志查询除外)。没有复杂性。有许多方法可以提高效率:传输的数据量。等。

希望我有更多的时间来确保这是100%符合您的需求,但必须去。所以我给你留下一个“HTH”-stevep