给定一个非负整数n和一组用户定义的不等式(例如外部文本文件),我想确定n是否满足任何不等式,如果满足,则确定哪个不等式。
这是一张积分表。
n = 0: 1
n < 5: 5
n = 5: 10
如果你画一个等于5的数字n,你得到10分。
如果n小于5,则得5分。
如果n为0,则得1分。
冒号左边的内容是“条件”,右边的内容是“值”。
所有条目的格式如下:
n1 op n2: val
在这个体系中,平等优先于不平等,因此它们出现的顺序最终将无关紧要。输入是非负整数,但中间值和结果可能不是非负的结果甚至可能不是数字(例如:可能是字符串)。我设计它的目的是只接受最基本的不等式,使编写解析器更容易(并查看这个想法是否可行)
我的程序有两个组件:
将读取结构化输入并构建数据结构以存储条件及其相关结果的解析器。
一个函数,它接受一个参数(一个非负整数)并返回结果(或者,如示例中所示,返回我接收到的点数)
如果列表是硬编码的,那么这是一个简单的任务:只要使用一个case when或If else block,我就完成了但问题并没有那么简单。
回想一下最上面的列表它可以包含任意数量的(in)等式也许上面只有三个。也许没有,也许有10,20,50,甚至100万实际上,对于m>=0,可以有m个不等式
给定一个数字n和一个包含任意数量条件和结果的数据结构,我希望能够确定它是否满足任何条件并返回相关值。所以和上面的例子一样,如果我传入5,函数将返回10。
它们的条件/值对在原始形式中不是唯一的。您可能有多个相同(in)相等但具有不同值的实例。如:
n = 0: 10
n = 0: 1000
n > 0: n
注意最后一条:如果n大于0,那么它就是你得到的。
如果满足多个不等式(例如:n>5,n>6,n>7),则应返回所有不等式。如果这不可能有效地做到,我可以只返回第一个满意的,而忽略其余的。但我希望能够检索到整个列表。
我已经考虑了一段时间,我想我应该使用两个哈希表:第一个存储等式,第二个存储不等式。
相等性很容易处理:只需将条件作为一个键并拥有一个值列表然后我可以快速检查n是否在散列中并获取适当的值。
然而,对于不平等,我不确定它将如何运作。有人知道我如何用尽可能少的计算步骤来解决这个问题吗?很明显,我可以很容易地在O(n)时间内完成这项工作:只需逐一地在每个(I n)等式中运行它但是如果这项检查是实时的,会发生什么呢?(例如:不断更新)
例如,很明显,如果我有100个不等式,其中99个检查值大于100,而另一个检查值小于等于100,那么当我通过47时,我不必费心检查那些99个不等式。
您可以使用任何数据结构来存储数据。解析程序本身不包含在计算中,因为它将被预处理,只需要执行一次,但是如果解析数据花费太长时间可能会有问题。
由于我使用露比,我可能有更灵活的选择,当谈到“弄乱”的数据,以及它将如何解释。
最佳答案
class RuleSet
Rule = Struct.new(:op1,:op,:op2,:result) do
def <=>(r2)
# Op of "=" sorts before others
[op=="=" ? 0 : 1, op2.to_i] <=> [r2.op=="=" ? 0 : 1, r2.op2.to_i]
end
def matches(n)
@op2i ||= op2.to_i
case op
when "=" then n == @op2i
when "<" then n < @op2i
when ">" then n > @op2i
end
end
end
def initialize(text)
@rules = text.each_line.map do |line|
Rule.new *line.split(/[\s:]+/)
end.sort
end
def value_for( n )
if rule = @rules.find{ |r| r.matches(n) }
rule.result=="n" ? n : rule.result.to_i
end
end
end
set = RuleSet.new( DATA.read )
-1.upto(8) do |n|
puts "%2i => %s" % [ n, set.value_for(n).inspect ]
end
#=> -1 => 5
#=> 0 => 1
#=> 1 => 5
#=> 2 => 5
#=> 3 => 5
#=> 4 => 5
#=> 5 => 10
#=> 6 => nil
#=> 7 => 7
#=> 8 => nil
__END__
n = 0: 1
n < 5: 5
n = 5: 10
n = 7: n