zoukankan      html  css  js  c++  java
  • 多条件试卷提取的问题(附带测试代码)

    问题来自http://q.cnblogs.com/q/38789/

    题目如下:

    最近在开发一个项目,做一个试题系统,其中有一个组卷功能(随机抽题),试题属性有:所属专业、题型、难易度、认知层次等。 现在需要实现随机组卷,抽出100道题满足以下条件:

    条件1:

    所属专业: 内科 20%  外科 30%    口腔科 25%  神经科 25。

    条件2:

    题型: 单选题  30%  多选题 40%   简答题 30%

    条件3:

    难易度:  难 20%   中 60%    易 20% 

    条件4:

    认知层次: 记忆25%   应用40%   理解 35%

    这类题在博问看到了好几次,花了点时间写了下面的代码希望能帮助到需要的人。

     

    其实多条件问题之所以难就是在效率上,所以一般是反过来解决,看条件挑符合的,测试中因为是随机生成的样本库,随机了几次都打不到100题,所以直接生成相应的题目。

    下面类实现了两种场景的效率考虑,如果是遍历比较快的可以直接调用AddTest全加一遍,如果是查询比较快的可以通过KindOfTestNeed来提取查询条件,目前的代码生成的结果每次是一样的,如果有真实的库可以采取查询结果的随机化和KindOfTestNeed条件的随机化来生成不同的卷子。

    实际引用可以参考Artwl的文章:

    实例讲解遗传算法——基于遗传算法的自动组卷系统【理论篇】

    实例讲解遗传算法——基于遗传算法的自动组卷系统【实践篇】

    直接上代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using FizzWare.NBuilder;
    using Xunit;
    
    namespace ExerciseGenerateSystem
    {
        //条件1:
        //所属专业: 内科 20%  外科 30%    口腔科 25%  神经科 25。
        //条件2:
        //题型: 单选题  30%  多选题 40%   简答题 30%
        //条件3:
        //难易度:  难 20%   中 60%    易 20% 
        //条件4:
        //认知层次: 记忆25%   应用40%   理解 35%
        public class ExerciseItem
        {
            public long Id { get; set; }
            public Major Major { get; set; }
            public TestType TestType { get; set; }
            public Difficulty Difficulty { get; set; }
            public Awareness Awareness { get; set; }
    
            public override string ToString()
            {
                return string.Format("{0}\t{1}\t{2}\t{3}\t{4}", this.Id, this.Major, this.TestType, this.Difficulty,
                                     this.Awareness);
            }
        }
        public enum Major
        {
            [Description("内科")]
            Medicine,
            [Description("外科")]
            Surgery,
            [Description("口腔科")]
            Stomatology,
            [Description("神经科")]
            Neurology
        }
        public enum TestType
        {
            SingleAnswer,
            MultiAnswer,
            ShortAnswer
        }
        public enum Difficulty
        {
            Hard,
            Middle,
            Easy
        }
        public enum Awareness
        {
            Remember,
            Impl,
            Understand
        }
    
        public class GenerateMyTest
        {
            private const int TestTotal = 100;
            [Fact]
            public void DoGenerate()
            {
                //var testLibary = Builder<ExerciseItem>
                //    .CreateListOfSize(299999)
                //    .All()
                //    .With(e=>e.Awareness=(Awareness)random(2))
                //    .With(e => e.Difficulty = (Difficulty)random(2))
                //    .With(e => e.Major = (Major)random(3))
                //    .With(e => e.TestType = (TestType)random(2))
                //    .Build();
                var myTest = new MyTest(TestTotal);
    
                myTest.AddMajorCondition(Major.Medicine, 0.2);
                myTest.AddMajorCondition(Major.Surgery, 0.3);
                myTest.AddMajorCondition(Major.Stomatology, 0.25);
                myTest.AddMajorCondition(Major.Neurology, 0.25);
    
                myTest.AddTestTypeCondidtion(TestType.SingleAnswer, 0.3);
                myTest.AddTestTypeCondidtion(TestType.MultiAnswer, 0.4);
                myTest.AddTestTypeCondidtion(TestType.ShortAnswer, 0.3);
    
                myTest.AddDifficultyCondition(Difficulty.Hard, 0.2);
                myTest.AddDifficultyCondition(Difficulty.Middle, 0.6);
                myTest.AddDifficultyCondition(Difficulty.Easy, 0.2);
    
                myTest.AddAwarenessCondition(Awareness.Remember, 0.25);
                myTest.AddAwarenessCondition(Awareness.Impl, 0.4);
                myTest.AddAwarenessCondition(Awareness.Understand, 0.35);
    
                var kindOfTestNeed = myTest.KindOfTestNeed();
    
                for (var i = 1l; !myTest.IsValid() && kindOfTestNeed != null; i++)
                {
                    var item = new ExerciseItem
                                   {
                                       Id = i,
                                       Awareness = kindOfTestNeed.Item4,
                                       Difficulty = kindOfTestNeed.Item3,
                                       Major = kindOfTestNeed.Item1,
                                       TestType = kindOfTestNeed.Item2
                                   };
                    //testLibary.FirstOrDefault(
                    //    t =>
                    //    !myTest.Contains(t)
                    //    && t.Major == kindOfTestNeed.Item1
                    //    && t.Difficulty == kindOfTestNeed.Item3
                    //    && t.TestType == kindOfTestNeed.Item2
                    //    && t.Awareness == kindOfTestNeed.Item4);
                    if (item == null)
                    {
                        myTest.Print();
                        throw new Exception("Libary is not fit this conditions!");
                    }
                    if (!myTest.AddTest(item))
                    {
                        kindOfTestNeed = myTest.KindOfTestNeed();
                    }
                }
                myTest.Print();
                Assert.True(myTest.Validate());
    
            }
            Random r = new Random();
            private int random(int max)
            {
                return r.Next(0, max);
            }
            [Fact]
            public void Test()
            {
                Console.WriteLine(123d / 123);
            }
        }
    
        public class ConditionStats
        {
            public ConditionStats(double scale)
            {
                this.Scale = scale;
            }
            public double Scale;
    
            public bool IsEnough { get; set; }
    
            public bool IsTooMuch { get; set; }
    
            public void Update(long count, long total)
            {
                var ret = (double)count / (double)total;
                IsEnough = ret >= Scale;
                IsTooMuch = ret > Scale;
            }
        }
    
        public class MyTest
        {
            private readonly IList<ExerciseItem> _exerciseItems = new List<ExerciseItem>();
            private readonly long _total;
            private readonly Dictionary<Major, ConditionStats> _majorConditions = new Dictionary<Major, ConditionStats>();
            private readonly Dictionary<TestType, ConditionStats> _testTypeConditions = new Dictionary<TestType, ConditionStats>();
            private readonly Dictionary<Difficulty, ConditionStats> _difficultyConditions = new Dictionary<Difficulty, ConditionStats>();
            private readonly Dictionary<Awareness, ConditionStats> _awarenessConditions = new Dictionary<Awareness, ConditionStats>();
    
            public MyTest(long total)
            {
                _total = total;
            }
    
            public void AddMajorCondition(Major major, double scale)
            {
                _majorConditions.Add(major, new ConditionStats(scale));
            }
    
            public void AddTestTypeCondidtion(TestType testType, double scale)
            {
                _testTypeConditions.Add(testType, new ConditionStats(scale));
            }
    
            public void AddDifficultyCondition(Difficulty difficulty, double scale)
            {
                _difficultyConditions.Add(difficulty, new ConditionStats(scale));
            }
    
            public void AddAwarenessCondition(Awareness awareness, double scale)
            {
                _awarenessConditions.Add(awareness, new ConditionStats(scale));
            }
    
            public bool Contains(ExerciseItem item)
            {
                return _exerciseItems.Any(e => e.Id == item.Id);
            }
    
            public bool AddTest(ExerciseItem item)
            {
                _exerciseItems.Add(item);
                UpdateStats(item);
                if (IsTooMuch())
                {
                    _exerciseItems.Remove(item);
                    UpdateStats(item);
                    return false;
                }
                return true;
            }
    
            private int i = 1;
            public void UpdateStats(ExerciseItem exerciseItem)
            {
                i++;
                var major = _majorConditions[exerciseItem.Major];
                major.Update(_exerciseItems.LongCount(e => e.Major == exerciseItem.Major), _total);
                var testType = _testTypeConditions[exerciseItem.TestType];
                testType.Update(_exerciseItems.LongCount(e => e.TestType == exerciseItem.TestType), _total);
                var difficulty = _difficultyConditions[exerciseItem.Difficulty];
                difficulty.Update(_exerciseItems.LongCount(e => e.Difficulty == exerciseItem.Difficulty), _total);
                var awareness = _awarenessConditions[exerciseItem.Awareness];
                awareness.Update(_exerciseItems.LongCount(e => e.Awareness == exerciseItem.Awareness), _total);
            }
    
            public bool IsTooMuch()
            {
                return _majorConditions.Any(mc => mc.Value.IsTooMuch)
                       ||
                       _testTypeConditions.Any(mc => mc.Value.IsTooMuch)
                       ||
                       _difficultyConditions.Any(mc => mc.Value.IsTooMuch)
                       ||
                       _awarenessConditions.Any(mc => mc.Value.IsTooMuch);
            }
    
            public Tuple<Major, TestType, Difficulty, Awareness> KindOfTestNeed()
            {
                if (_majorConditions.Any(mc => !mc.Value.IsEnough)
                       &&
                       _testTypeConditions.Any(mc => !mc.Value.IsEnough)
                       &&
                       _difficultyConditions.Any(mc => !mc.Value.IsEnough)
                       &&
                       _awarenessConditions.Any(mc => !mc.Value.IsEnough))
                {
                    return new Tuple<Major, TestType, Difficulty, Awareness>
                        (
                        _majorConditions.First(mc => !mc.Value.IsEnough).Key,
                        _testTypeConditions.First(mc => !mc.Value.IsEnough).Key,
                        _difficultyConditions.First(mc => !mc.Value.IsEnough).Key,
                        _awarenessConditions.First(mc => !mc.Value.IsEnough).Key
                        )
                        ;
                }
                return null;
            }
            public bool Validate()
            {
                return _majorConditions.All(mc => mc.Value.IsEnough)
                       &&
                       _testTypeConditions.All(mc => mc.Value.IsEnough)
                       &&
                       _difficultyConditions.All(mc => mc.Value.IsEnough)
                       &&
                       _awarenessConditions.All(mc => mc.Value.IsEnough);
            }
            public bool IsValid()
            {
                return _total == _exerciseItems.LongCount();
            }
    
            public void Print()
            {
                Console.WriteLine("Totoal:{0}", _exerciseItems.Count());
                _exerciseItems.ToList().ForEach(Console.WriteLine);
            }
        }
    }
    

     测试结果:

    DoGenerate : PassedTotoal:100
    1    Medicine    SingleAnswer    Hard    Remember
    2    Medicine    SingleAnswer    Hard    Remember
    3    Medicine    SingleAnswer    Hard    Remember
    4    Medicine    SingleAnswer    Hard    Remember
    5    Medicine    SingleAnswer    Hard    Remember
    6    Medicine    SingleAnswer    Hard    Remember
    7    Medicine    SingleAnswer    Hard    Remember
    8    Medicine    SingleAnswer    Hard    Remember
    9    Medicine    SingleAnswer    Hard    Remember
    10    Medicine    SingleAnswer    Hard    Remember
    11    Medicine    SingleAnswer    Hard    Remember
    12    Medicine    SingleAnswer    Hard    Remember
    13    Medicine    SingleAnswer    Hard    Remember
    14    Medicine    SingleAnswer    Hard    Remember
    15    Medicine    SingleAnswer    Hard    Remember
    16    Medicine    SingleAnswer    Hard    Remember
    17    Medicine    SingleAnswer    Hard    Remember
    18    Medicine    SingleAnswer    Hard    Remember
    19    Medicine    SingleAnswer    Hard    Remember
    20    Medicine    SingleAnswer    Hard    Remember
    22    Surgery    SingleAnswer    Middle    Remember
    23    Surgery    SingleAnswer    Middle    Remember
    24    Surgery    SingleAnswer    Middle    Remember
    25    Surgery    SingleAnswer    Middle    Remember
    26    Surgery    SingleAnswer    Middle    Remember
    28    Surgery    SingleAnswer    Middle    Impl
    29    Surgery    SingleAnswer    Middle    Impl
    30    Surgery    SingleAnswer    Middle    Impl
    31    Surgery    SingleAnswer    Middle    Impl
    32    Surgery    SingleAnswer    Middle    Impl
    34    Surgery    MultiAnswer    Middle    Impl
    35    Surgery    MultiAnswer    Middle    Impl
    36    Surgery    MultiAnswer    Middle    Impl
    37    Surgery    MultiAnswer    Middle    Impl
    38    Surgery    MultiAnswer    Middle    Impl
    39    Surgery    MultiAnswer    Middle    Impl
    40    Surgery    MultiAnswer    Middle    Impl
    41    Surgery    MultiAnswer    Middle    Impl
    42    Surgery    MultiAnswer    Middle    Impl
    43    Surgery    MultiAnswer    Middle    Impl
    44    Surgery    MultiAnswer    Middle    Impl
    45    Surgery    MultiAnswer    Middle    Impl
    46    Surgery    MultiAnswer    Middle    Impl
    47    Surgery    MultiAnswer    Middle    Impl
    48    Surgery    MultiAnswer    Middle    Impl
    49    Surgery    MultiAnswer    Middle    Impl
    50    Surgery    MultiAnswer    Middle    Impl
    51    Surgery    MultiAnswer    Middle    Impl
    52    Surgery    MultiAnswer    Middle    Impl
    53    Surgery    MultiAnswer    Middle    Impl
    55    Stomatology    MultiAnswer    Middle    Impl
    56    Stomatology    MultiAnswer    Middle    Impl
    57    Stomatology    MultiAnswer    Middle    Impl
    58    Stomatology    MultiAnswer    Middle    Impl
    59    Stomatology    MultiAnswer    Middle    Impl
    60    Stomatology    MultiAnswer    Middle    Impl
    61    Stomatology    MultiAnswer    Middle    Impl
    62    Stomatology    MultiAnswer    Middle    Impl
    63    Stomatology    MultiAnswer    Middle    Impl
    64    Stomatology    MultiAnswer    Middle    Impl
    65    Stomatology    MultiAnswer    Middle    Impl
    66    Stomatology    MultiAnswer    Middle    Impl
    67    Stomatology    MultiAnswer    Middle    Impl
    68    Stomatology    MultiAnswer    Middle    Impl
    69    Stomatology    MultiAnswer    Middle    Impl
    71    Stomatology    MultiAnswer    Middle    Understand
    72    Stomatology    MultiAnswer    Middle    Understand
    73    Stomatology    MultiAnswer    Middle    Understand
    74    Stomatology    MultiAnswer    Middle    Understand
    75    Stomatology    MultiAnswer    Middle    Understand
    77    Stomatology    ShortAnswer    Middle    Understand
    78    Stomatology    ShortAnswer    Middle    Understand
    79    Stomatology    ShortAnswer    Middle    Understand
    80    Stomatology    ShortAnswer    Middle    Understand
    81    Stomatology    ShortAnswer    Middle    Understand
    83    Neurology    ShortAnswer    Middle    Understand
    84    Neurology    ShortAnswer    Middle    Understand
    85    Neurology    ShortAnswer    Middle    Understand
    86    Neurology    ShortAnswer    Middle    Understand
    87    Neurology    ShortAnswer    Middle    Understand
    89    Neurology    ShortAnswer    Easy    Understand
    90    Neurology    ShortAnswer    Easy    Understand
    91    Neurology    ShortAnswer    Easy    Understand
    92    Neurology    ShortAnswer    Easy    Understand
    93    Neurology    ShortAnswer    Easy    Understand
    94    Neurology    ShortAnswer    Easy    Understand
    95    Neurology    ShortAnswer    Easy    Understand
    96    Neurology    ShortAnswer    Easy    Understand
    97    Neurology    ShortAnswer    Easy    Understand
    98    Neurology    ShortAnswer    Easy    Understand
    99    Neurology    ShortAnswer    Easy    Understand
    100    Neurology    ShortAnswer    Easy    Understand
    101    Neurology    ShortAnswer    Easy    Understand
    102    Neurology    ShortAnswer    Easy    Understand
    103    Neurology    ShortAnswer    Easy    Understand
    104    Neurology    ShortAnswer    Easy    Understand
    105    Neurology    ShortAnswer    Easy    Understand
    106    Neurology    ShortAnswer    Easy    Understand
    107    Neurology    ShortAnswer    Easy    Understand
    108    Neurology    ShortAnswer    Easy    Understand
    
  • 相关阅读:
    Java 类加载、调用构造器、执行方法的过程
    flink定义各类source
    flink个人基础笔记
    flink任务提交流程
    Flink 命令
    Flink开发环境搭建(idea2019)
    Flink集群部署
    canal开启状态,但是不能生产数据到kafka,问题解决
    Cannal单节点部署
    kafka单节点部署
  • 原文地址:https://www.cnblogs.com/jinzhao/p/2597297.html
Copyright © 2011-2022 走看看