所以Wendy宣称他们的三明治有256种组合 - 这意味着有8种成分你可以不具备(虽然我想知道为什么他们会计算你没有任何有效的组合,但我离题了。)
通用方法允许您将每个选择的各种状态相乘,从而允许更复杂的组合。在这种情况下,Wendy的项目只能包含或排除。但是一些三明治可能有两种芥末的选择(但不是两种,以节省成本)。
这些都相当简单。你将选项的数量相乘,所以For Wendy's:
2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 = 256
如果他们将芥末选择多样化,如上所述:
2 * 2 * 3 * 2 * 2 * 2 * 2 * 2 = 384
进一步看起来更难。
如果你将芝麻作为一个单独的项目,那么他们需要发髻项目。只有在包含面包的情况下才可以吃芝麻,并且可以没有芝麻的面包,但是如果没有芝麻,你就不能吃芝麻。这可以简化为具有三种状态的单个发髻物品(无,带有种子的发髻,没有发髻),但有些情况无法完成。
例如,戴尔的计算机配置器不允许某些组合(可能插槽已满,当放入同一系统时项目不兼容等)。答案 0 :(得分:5)
惠普在加利福尼亚的高端服务器制造工厂多年来一直使用基于规则的自定义系统来实现这一目标。
工厂车间构建周期流程包括预先检查,以确保在将订单发布给构建商和测试人员之前可以构建订单。
其中一项检查确定订单的物料清单(BOM)是否符合过程工程师指定的规则列表。例如,如果客户订购处理器,请确保他们还订购了足够的直流转换器部件;或者,如果他们订购了一定数量的内存DIMM,请确保他们还订购了一块子板以容纳额外的容量。
具有编译器背景的计算机科学专业的学生会认识到这些代码。代码解析了BOM,在内部生成按类型分组的线程化零件树。然后,它将规则应用于内部树,以确定订单是否符合。
作为副作用,系统还为每个订单生成构建文档,工作人员在构建每个系统时将其拉出。它还为构建后的老化过程生成了预期的测试结果,因此测试托架可以引用它们并确定是否所有内容都已正确构建。
答案 1 :(得分:4)
Adam Davis :如果我理解正确,您打算开发某种系统,该系统实际上可以用于帮助用户购买兼容零件的购物车。
这是一个图形问题(不是全部),你有与其他项目兼容的项目。例如,Pentium i3-2020
与任何Socket 1155 Motherboard
兼容,Asrock H61M-VS
是 Socket 1155 Motherboard
,与2xDDR3兼容(速度= 1066),并且需要PCI-Express GPU
,DDR3 PC RAM{Total(size) <= 16GB}
,4 pin ATX 12V power
等
您需要能够(a)确定购物篮中的每个商品是否满足购物篮中的其他商品(即RAM卡具有兼容的主板),(b)分配最合适的商品(即分配USB Hub)主板USB端口和打印机到USB集线器,如果主板用完USB端口,而不是反过来让集线器干燥),(c)为用户提供查找满意组件列表的功能。也许USB集线器总是优先考虑,因为它们是扩展(但要注意它)。
你需要一个简单的分类系统,即H61M-VS 是一个主板,H61M-VS 有一个 DDR3
内存插槽(带速度)每个插槽的属性。)
在分类和组成方面,您需要确定需求,这非常简单。现在,简单的分类可以允许简单的SQL查询来查找适合分类的所有项目。
要测试篮子,需要创建一个配置,确定哪些项目与哪个匹配(即主板的DDR3插槽与4GB Ram模块匹配,SATA HDD线缆连接到主板SATA端口和PSU的SATA电源线,而PSU的4针ATX 12V电源线连接主板。
最简单的方法就是检查是否存在另一个令人满意的项目
您从一个项目开始,比如一个处理器。处理器需要主板和风扇,因此您可以选择主板(将处理器风扇添加到list_of_things_to_be_satisfied
)。这一直持续到list_of_things_to_be_satisfied
中没有其他项目为止。当然,这完全取决于您的确切要求,并且知道将为用户解决的问题。
答案 2 :(得分:3)
您可以通过多种方式在代码中实现此功能,但我认为这是在编程之前解决问题的最佳方法:
在定义所有“部件”时,识别部件的层次结构和分类将是至关重要的。这是正确的,因为某些规则可能是唯一的部分(例如“仅限褐色芥末”),某些分类(例如“所有芥末”),某些输入(例如“所有调味品”)等。
为每个独特的零件,类别,类型和成品定义规则集(先决条件,排除等)。
这可能听起来很愚蠢,但必须非常小心以确保规则在适当的范围内定义。例如,如果成品是Burger
:
prerequisite
exclusive
exclusive
在“部件”的独特/类别/类型规则上花了这么多时间之后,许多设计师会忽略仅适用于成品的规则,即使部件没有冲突也是如此。
condition
prerequisite
这张规则图很快就会变得非常复杂。
确保您的结构适应层次结构和分类。例如:“褐芥末”和“第戎芥末”是单独的物品,它们都是芥末和两种调味品。
仔细选择继承建模(基类)和对象属性(例如Category
属性或HasCondiments
标志)的正确组合,以使其工作。
在每个分层对象级别为RuleSets
创建私有字段。
为HasConflicts
标志和RuleViolations
集合制作公共属性。
将零件添加到产品时,请检查所有级别的规则(其自身,类别,类型和产品) - 通过公共功能执行此操作从产品中调用。或者为了更好的内化,您可以在部件本身上创建事件处理程序。
这是我吮吸的地方,也是好事,因为它超出了你的问题的范围。
这一步骤的技巧将是如何在代码中实现向树/图形移动的规则 - 例如,当特定部分与其范围之外的另一部分有问题时,或者当它的验证如何运行时另外一部分被添加?我的想法:
对每个部分使用公共功能方法。传递产品的CurrentParts
集合。
在Product对象上,定义处理程序以处理OnPartAdded
和OnPartRemoved
,并让它们枚举CurrentParts
集合并调用每个部分的验证函数。
interface IProduct
{
void AddPart();
void OnAddPart();
}
// base class for products
public class Product() : IProduct
{
// private or no setter. write functions as you like to add/remove parts.
public ICollection<Part> CurrentParts { get; };
// Add part function adds to collection and triggers a handler.
public void AddPart(Part p)
{
CurrentParts.Add(p);
OnAddParts();
}
// handler for adding a part should trigger part validations
public void OnAddPart()
{
// validate part-scope rules, you'll want to return some message/exception
foreach(var part in CurrentParts) {
part.ValidateRules(CurrentParts);
}
ValidateRules(); // validate Product-scope rules.
}
}
interface IProduct
{
// "object" should be replaced with whatever way you implement your rules
void object RuleSet;
void ValidateRules(ICollection<Part> otherParts);
}
// base class for parts
public class Part : IPart
{
public object RuleSet; // see note in interface.
public ValidateRules(ICollection<Part> otherParts)
{
// insert your algorithms here for validating
// the product parts against this part's rule set.
}
}
很干净。
答案 3 :(得分:2)
“Generating Functions”作为一种可以在解决此类问题时使用的构造而浮现在脑海中。我注意到,根据你的需要,有几种不同的生成函数。
在北美,汽车牌照在计算所有排列方面可能是一个有趣的组合问题,其中6或7的每个位置有36个可能的值,这是牌照的长度,取决于一个人获得牌照的位置。然而,由于某些组合中存在咒骂词或种族主义词语而导致稍微更难的问题,因此某些组合被取消资格。例如,有一个很少的N字,至少有几种不同的拼写,我认为不会在车牌上允许。
另一个例子是使用包含重复多次的一些项目的给定字母来确定所有不同的单词顺序。例如,如果一个人想要所有不同的方式来安排说“字母”这个词的字母,那么它不仅仅是6个!这将是“abcdef”的情况,因为有两对字母使计算起来有点棘手。
L33t可能是另一种方法,在识别不合适的单词时会带来更多的复杂性,因为虽然ass被审查为$$或@ss可能不一定会以相同的方式对待,即使它基本上是相同的术语表达的不同的方法。我不确定是否会在车牌上出现许多像$或@这样的特殊字符,但有人可能会认为父母对网页内容的控制必须要有这些算法来确定要审查的字词。
答案 4 :(得分:2)
作为程序员,我会做以下事情(虽然我从来没有在现实生活中做过这样的事情):
如果您将所有组合视为一组,则例外只会删除该组的成员。但是您不需要存储整个集合,只需存储异常,因为您可以非常轻松地计算集合的大小。
答案 5 :(得分:1)
您可能希望创建一个唯一表示单个配置的数据结构。然后,应该以这样的方式定义每个兼容性规则,即它可以生成包含失败该规则的所有单个配置的集合。然后,您将获取所有规则生成的所有集合的并集,以获取未通过规则的所有配置集。然后计算该组的大小,并从设置所有可能配置的大小中减去它。
困难的部分是以一种可以由规则生成的方式定义数据结构,并且可以对其进行设置操作!这是读者的练习,AKA我什么都没有。
答案 6 :(得分:1)
我现在唯一能想到的就是构建如果你可以构建一个树来定义你有一个简单解决方案的部分之间的依赖关系。
sandwitch
|
|__Bun(2)__sesame(1)
|
|__Mustard(3)
|
|__Mayo(2)
|
|__Ketchup(2)
|
|__Olives(3)
这简单地说你有两个发髻选项(发髻或没发髻) - 1芝麻(只有你有一个发髻 - 表示依赖 - 如果你有一个7这里它意味着7种类型可以存在如果你只有一个发髻)
3为芥末..等等
然后简单地乘以所有分支的总和。
答案 7 :(得分:1)
可能将问题形式化为k-sat problem。在某些情况下,问题似乎是NP完全的,你必须列举所有可能性来检查它们是否满足所有条件。在其他一些情况下,问题很容易解决(例如,当需要很少的条件时)。这是一个活跃的研究领域。你会在谷歌学者身上找到相关的参考资料。
对于芥末,您将为芥末类型添加二进制条目“mustard_type”并引入条件:not (not mustard and mustard_type)
其中mustard
是芥末的二进制条目。当您选择mustard_type == 0
时,它会强加默认选项not mustard
。
对于芝麻选择,这更明确:not (sesame and not bun)
。
因此,您提出的案件似乎属于2-sat家族的问题。