如何实现随机题库生成

背景描述:

对于每一个不同的用户,从题库里随机抽取题目, 抽取的题目都是该用户未抽取过的,每个用户产生的考卷不相同。

解决方案:

方法一:使用bitSet保存用户历史题集

内存占用分析:百万级用户*万级题目量=100GB
缺点: bitSet持久化比较麻烦

方法二:哈希

选取一个大于题库总数的最小质数p, 对每个用户生成独特哈希函数

h a b ( x ) = ( a x + b ) m o d   p ( 0 < a < p , 0 ≤ b < p ) h_{ab}(x) = (ax+b)mod\ p\qquad(0<a<p, 0 \le b <p) hab(x)=(ax+b)mod p(0<a<p,0b<p)

可以证明, 对于不同的x,y<p, h a b ( x ) ≠ h a b ( y ) h_{ab}(x) \ne h_{ab}(y) hab(x)=hab(y)

那么对于每个用户, 保存a,b,x

x是每次递增1的做题进度, 通过哈希函数生成下一题号, 生成题号大于总题数m则跳过.

public class RandomQuestion {
    private static class QuestionBank {
        // 题库数量
        private static int QUESTION_SUM = 50;

        // 大于题库总数的最小质数p
        private static int P = 53;

        public static int getUserNextQuestion(User u) {
            int next = u.getNext(P);
            if (next > QUESTION_SUM) {
                return getUserNextQuestion(u);
            }
            return next;
        }
    }

    private static class User {
        private int a;
        private int b;
        private int current;

        public User(int a, int b) {
            this.a = a;
            this.b = b;
            this.current = 0;
        }

        public int getNext(int p) {
            return Math.floorMod((a * current++ + b), p);
        }
    }

    public static void main(String[] args) {
        User a = new User(new Random().nextInt(), new Random().nextInt());
        User b = new User(new Random().nextInt(), new Random().nextInt());

        System.out.println("user a:");
        for (int i = 0; i < 50; i++) {
            System.out.print(QuestionBank.getUserNextQuestion(a) + " ");
        }
        System.out.println("\nuser b:");
        for (int i = 0; i < 50; i++) {
            System.out.print(QuestionBank.getUserNextQuestion(b) + " ");
        }
    }
}
问题延伸
  1. 如何处理题库增加题目的问题,用户不受影响的问题,质数D选个大一点的,这样C可以直接增加,或者是是参考一致性哈希的思想
  2. 问题添加权重,高优问题优先展示
  3. 问题添加难度系数,生成的每份考卷难度系数之和在某个范围
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值