我有以下2d水果阵列:
var camera, scene, renderer;
var geometry, material, mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.set(20,0,20);
scene = new THREE.Scene();
// Instantiate a loader
var loader = new THREE.GLTFLoader();
// Load a glTF resource
loader.load( 'Box.gltf', function ( gltf ) {
scene.add( gltf.scene );
gltf.animations; // Array<THREE.AnimationClip>
gltf.scene; // THREE.Scene
gltf.scenes; // Array<THREE.Scene>
gltf.cameras; // Array<THREE.Camera>
} );
var light = new THREE.AmbientLight(0xffffff);
scene.add(light);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
任务是在条件之后找到N长度的对序列:
fruits = [["apple", "lemon"],["apple", "cucumber"],["carrot", "lemon"],["carrot", "cucumber"],["peach", "cucumber"],["lemon", "melon"],["grape", "cucumber"],["lime", "lemon"],["lime", "cucumber"],["apricot", "lemon"],["apricot", "cucumber"],["avocado", "cucumber"],["banana", "lemon"],["banana", "cucumber"],["blackberry", "lemon"],["blackberry", "cucumber"],["blackberry", "prune"],["blueberry", "lemon"],["blueberry", "melon"],["blueberry", "cucumber"],["cherry", "lemon"],["cherry", "cucumber"],["papaya", "lemon"],["plum", "lemon"],["plum", "cucumber"],["feijoa", "lemon"],["fig", "lemon"],["fig", "cucumber"],["eggplant", "lemon"],["eggplant", "cucumber"],["raspberry", "lemon"],["raspberry", "cucumber"],["cranberry", "lemon"],["cranberry", "cucumber"],["pomelo", "lemon"],["pomelo", "cucumber"],["orange", "lemon"],["orange", "cucumber"],["olive", "cucumber"],["gooseberry", "lemon"],["guava", "lemon"],["guava", "blueberry"],["guava", "cucumber"],["redcurrant", "lemon"],["redcurrant", "cucumber"],["pomergranate", "lemon"],["pomergranate", "cucumber"],["nectarine", "cucumber"],["mulberry", "lemon"],["mulberry", "cucumber"],["dragonfruit", "lemon"],["dragonfruit", "cucumber"],["pear", "lemon"],["cucumber", "lemon"],["cucumber", "blueberry"],["cucumber", "salmonberry"],["cucumber", "melon"],["prune", "lemon"],["prune", "guava"],["prune", "cucumber"],["kiwi", "cucumber"],["mangosteen", "cucumber"],["jujube", "lemon"],["jujube", "cucumber"],["clementine", "lemon"],["clementine", "blueberry"],["clementine", "cucumber"],["tangerine", "lemon"],["tangerine", "cucumber"],["pea", "lemon"],["pea", "cucumber"],["tomato", "cucumber"],["yuzu", "cucumber"]]
。"lemon"
。N = 4的例子:
"lemon"
我为N = 3和4编写了这段代码,
[["apple","lemon"], ["apple","cucumber"], ["clementine","cucumber"], ["clementine","lemon"]]
[["lime","lemon"], ["lime","cucumber"], ["pomelo","cucumber"], ["pomelo","lemon"]]
[["banana","lemon"], ["banana","cucumber"], ["pomergranate","cucumber"], ["pomergranate","lemon"]]
但我觉得这不是最好的方法。是否有任何元编程技巧可以使其适用于任何N长度?
答案 0 :(得分:1)
以下将强制执行n不受限制的所有规则(未检查n&lt; 3)。
第一条和第二条规则很简单。第三和第四条规则的大部分工作都是由each_cons完成的,它将获得所需的数组,以便独立于n。
pairs.permutation(n).select do |ar|
lemon_bracketed = (ar.first & ar.last).include?('lemon')
no_squeeze = !ar[1..-2].include?('lemon')
consecutive_pair = ar.each_cons(2).map { |x| x }.none { |first, last| (first & last).empty? }
consecutive_n = n == 3 ||
ar.each_cons(n-1)
.map { |x| x }
.all? { |group| group[1..-1].reduce(group[0]) { |combination, additional| combination & additional } }
lemon_bracketed && no_squeeze && consecutive_pair && consecutive_n
end
虽然这有效但速度很慢。但是pairs.permutation(n)
部分的表现似乎丢失了,所以这里没有太多可以做的。
答案 1 :(得分:1)
是的,您可以为任意length
参数执行强力解决方案:
class FruitCombinations
PAIRS = [["apple", "lemon"],["apple", "cucumber"],["carrot", "lemon"],["carrot", "cucumber"],["peach", "cucumber"],["lemon", "melon"],["grape", "cucumber"],["lime", "lemon"],["lime", "cucumber"],["apricot", "lemon"],["apricot", "cucumber"],["avocado", "cucumber"],["banana", "lemon"],["banana", "cucumber"],["blackberry", "lemon"],["blackberry", "cucumber"],["blackberry", "prune"],["blueberry", "lemon"],["blueberry", "melon"],["blueberry", "cucumber"],["cherry", "lemon"],["cherry", "cucumber"],["papaya", "lemon"],["plum", "lemon"],["plum", "cucumber"],["feijoa", "lemon"],["fig", "lemon"],["fig", "cucumber"],["eggplant", "lemon"],["eggplant", "cucumber"],["raspberry", "lemon"],["raspberry", "cucumber"],["cranberry", "lemon"],["cranberry", "cucumber"],["pomelo", "lemon"],["pomelo", "cucumber"],["orange", "lemon"],["orange", "cucumber"],["olive", "cucumber"],["gooseberry", "lemon"],["guava", "lemon"],["guava", "blueberry"],["guava", "cucumber"],["redcurrant", "lemon"],["redcurrant", "cucumber"],["pomergranate", "lemon"],["pomergranate", "cucumber"],["nectarine", "cucumber"],["mulberry", "lemon"],["mulberry", "cucumber"],["dragonfruit", "lemon"],["dragonfruit", "cucumber"],["pear", "lemon"],["cucumber", "lemon"],["cucumber", "blueberry"],["cucumber", "salmonberry"],["cucumber", "melon"],["prune", "lemon"],["prune", "guava"],["prune", "cucumber"],["kiwi", "cucumber"],["mangosteen", "cucumber"],["jujube", "lemon"],["jujube", "cucumber"],["clementine", "lemon"],["clementine", "blueberry"],["clementine", "cucumber"],["tangerine", "lemon"],["tangerine", "cucumber"],["pea", "lemon"],["pea", "cucumber"],["tomato", "cucumber"],["yuzu", "cucumber"]]
def self.list_valid(length)
PAIRS.permutation(length).select do |pair_permutation|
first = pair_permutation[0]
middle = pair_permutation[1..-2]
last = pair_permutation[-1]
first & last == ['lemon'] &&
middle.none? { |pair| pair.include?('lemon') } &&
!(first & middle[0]).empty? &&
!(middle[-1] & last).empty? &&
middle.each_cons(2).none? { |pair_of_pairs| (pair_of_pairs[0] & pair_of_pairs[-1]).empty? }
end
end
end
请注意,对于长度== 4,这是非常慢的,对于更长的长度,它会更慢。有人指出,递归解决方案会更有效率。
答案 2 :(得分:1)
这是一个递归解决方案,它直接构造所需的数组,而不是构造更大的排列数组,然后删除不满足所有规则的元素。
<强>代码强>
def combos(n, fruits)
with_lemon, without_lemon = fruits.partition { |a| a.include?("lemon") }
return [] if n < 2 || with_lemon.size < 2 || without_lemon.size < n - 2
with_lemon.each_with_object([]) do |pair, arr|
recurse(n, n-1, with_lemon - [pair], without_lemon, pair, pair, fruits.flatten).
each { |a| arr << ([pair] + a) }
end
end
def recurse(n, n_left, with_lemon, without_lemon, last, in_all_from_1st, in_all_from_2nd)
if n_left == 1
with = with_lemon.select { |pair| (last & pair).any? }
with.select! { |pair| (in_all_from_2nd & pair).empty? } unless n <= 3
with.map { |pair| [pair] }
else
without = without_lemon.select { |pair| (last & pair).any? }
return [] if without.empty?
without.each_with_object([]) do |pair, arr|
if n <= 3 || n_left > 2 || (in_all_from_1st & pair).empty?
recurse(n, n_left-1, with_lemon, without_lemon-[pair],
pair, in_all_from_1st, in_all_from_2nd & pair).
each { |a| arr << ([pair] + a) unless a.empty? }
end
end
end
end
<强>实施例强>
为了使示例更易于管理,我在OP给出的示例中选择了73对中的8对。
fruits = [["tomato", "cucumber"], ["fig", "lemon"], ["tomato", "lemon"],
["cucumber", "fig"], ["fig", "tomato"], ["lemon", "cucumber"],
["pomergranate", "cucumber"], ["lemon", "fig"]]
首先,我要定义一个帮助器。此方法返回一对[f,n]
,其中f
是水果,n
是f
出现的2元组的数量,n
是最大的数字任何水果的外观。
def max_nbr_appearances(n, fruits)
combos(n, fruits).map do |arr|
arr.map(&:uniq).flatten.group_by(&:itself).
transform_values { |v| v.size }.max_by(&:last)
end.max_by(&:last)
end
n = 2
combos(2, fruits)
#=> [[["fig", "lemon"], ["tomato", "lemon"]],
# [["fig", "lemon"], ["lemon", "cucumber"]],
# [["fig", "lemon"], ["lemon", "fig"]],
# [["tomato", "lemon"], ["fig", "lemon"]],
# [["tomato", "lemon"], ["lemon", "cucumber"]],
# [["tomato", "lemon"], ["lemon", "fig"]],
# [["lemon", "cucumber"], ["fig", "lemon"]],
# [["lemon", "cucumber"], ["tomato", "lemon"]],
# [["lemon", "cucumber"], ["lemon", "fig"]],
# [["lemon", "fig"], ["fig", "lemon"]],
# [["lemon", "fig"], ["tomato", "lemon"]],
# [["lemon", "fig"], ["lemon", "cucumber"]]]
n = 3
combos(n, fruits)
#=> [[["fig", "lemon"], ["cucumber", "fig"], ["lemon", "cucumber"]],
## [["fig", "lemon"], ["cucumber", "fig"], ["lemon", "fig"]],
# [["fig", "lemon"], ["fig", "tomato"], ["tomato", "lemon"]],
## [["fig", "lemon"], ["fig", "tomato"], ["lemon", "fig"]],
# [["tomato", "lemon"], ["tomato", "cucumber"], ["lemon", "cucumber"]],
# [["tomato", "lemon"], ["fig", "tomato"], ["fig", "lemon"]],
# [["tomato", "lemon"], ["fig", "tomato"], ["lemon", "fig"]], \
# [["lemon", "cucumber"], ["tomato", "cucumber"], ["tomato", "lemon"]],
# [["lemon", "cucumber"], ["cucumber", "fig"], ["fig", "lemon"]],
# [["lemon", "cucumber"], ["cucumber", "fig"], ["lemon", "fig"]],
## [["lemon", "fig"], ["cucumber", "fig"], ["fig", "lemon"]],
# [["lemon", "fig"], ["cucumber", "fig"], ["lemon", "cucumber"]],
# [["lemon", "fig"], ["fig", "tomato"], ["fig", "lemon"]],
# [["lemon", "fig"], ["fig", "tomato"], ["tomato", "lemon"]]]
开头**
以上的行有一个水果出现在所有三个2元组中(始终为"fig"
)。这是允许的,因为n = 3 <= 3
。
n = 4
combos(n, fruits)
#=> [[["fig", "lemon"], ["cucumber", "fig"], ["tomato", "cucumber"],
# ["tomato", "lemon"]],
# [["fig", "lemon"], ["fig", "tomato"], ["tomato", "cucumber"],
# ["lemon", "cucumber"]],
# [["tomato", "lemon"], ["tomato", "cucumber"], ["cucumber", "fig"],
# ["fig", "lemon"]],
# [["tomato", "lemon"], ["tomato", "cucumber"], ["cucumber", "fig"],
# ["lemon", "fig"]],
# [["tomato", "lemon"], ["fig", "tomato"], ["cucumber", "fig"],
# ["lemon", "cucumber"]],
# [["lemon", "cucumber"], ["tomato", "cucumber"], ["fig", "tomato"],
# ["fig", "lemon"]],
# [["lemon", "cucumber"], ["tomato", "cucumber"], ["fig", "tomato"],
# ["lemon", "fig"]],
# [["lemon", "cucumber"], ["cucumber", "fig"], ["fig", "tomato"],
# ["tomato", "lemon"]],
# [["lemon", "fig"], ["cucumber", "fig"], ["tomato", "cucumber"],
# ["tomato", "lemon"]],
# [["lemon", "fig"], ["fig", "tomato"], ["tomato", "cucumber"],
# ["lemon", "cucumber"]]]
combos(n, fruits).size
#=> 10
max_nbr_appearances(n, fruits)
#=> ["fig", 2]
最后的计算显示&#34;无花果&#34;在(至少)一个排列中出现两次并且没有水果(包括&#34;无花果&#34;)在排列中出现两次以上。 (关于外观最多的关系很常见。我只显示了一个。)因此最后一个条件得到满足。
n = 5
combos(n, fruits)
#=> [[["fig", "lemon"], ["cucumber", "fig"], ["fig", "tomato"],
# ["tomato", "cucumber"], ["tomato", "lemon"]],
# [["fig", "lemon"], ["cucumber", "fig"], ["fig", "tomato"],
# ["tomato", "cucumber"], ["lemon", "cucumber"]],
# ...
# [["lemon", "fig"], ["fig", "tomato"], ["cucumber", "fig"],
# ["pomergranate", "cucumber"], ["lemon", "cucumber"]]]
combos(n,fruits).size
#=> 36
max_nbr_appearances(n, fruits)
#=> ["fig", 3]
n = 6
combos(n,fruits)
#=> [[["fig", "lemon"], ["cucumber", "fig"], ["fig", "tomato"],
# ["tomato", "cucumber"], ["pomergranate", "cucumber"], ["lemon", "cucumber"]],
# [["fig", "lemon"], ["fig", "tomato"], ["tomato", "cucumber"],
# ["cucumber", "fig"], ["pomergranate", "cucumber"], ["lemon", "cucumber"]],
# ...
# [["lemon", "fig"], ["fig", "tomato"], ["cucumber", "fig"],
# ["pomergranate", "cucumber"], ["tomato", "cucumber"], ["lemon", "cucumber"]]]
combos(n,fruits).size
#=> 28
max_nbr_appearances(n, fruits)
#=> ["cucumber", 4]
n = 7
combos(7,fruits)
#=> []
对于问题中给出的fruits
fruits.size #=> 73
,获得了以下结果。
require 'time'
def ops_fruits(n, fruits)
t = Time.now
puts "\ncombos(#{n}, fruits).size = %d, elapsed seconds = %d" %
[combos(n, fruits).size, Time.now - t]
puts "max_nbr_appearances(#{n}, fruits) = #{max_nbr_appearances(n, fruits)}"
end
ops_fruits(3, fruits)
combos(3, fruits).size = 64, elapsed seconds = 0
max_nbr_appearances(3, fruits) = ["apple", 2]
ops_fruits(4, fruits)
combos(4, fruits).size = 736, elapsed seconds = 0
max_nbr_appearances(4, fruits) = ["apple", 2]
ops_fruits(5, fruits)
combos(5, fruits).size = 27822, elapsed seconds = 1
max_nbr_appearances(5, fruits) = ["cucumber", 3]
ops_fruits(6, fruits)
combos(6, fruits).size = 952504, elapsed seconds = 60
max_nbr_appearances(6, fruits) = ["cucumber", 4]
答案 3 :(得分:1)
摘要:
数据结构是一个图形 - 每个水果都是一个顶点,数组中的对是它们之间的边。
要解决此问题,请执行深度优先搜索。
第一对和最后一对应该包含“柠檬” 第一个和最后一个之间的对不应该包含“柠檬”。
"lemon"
节点(级别0)。N
。"lemon"
节点,除非它处于N
级别。每两个连续两对应包含一个共同元素。
每个连续的N-1对,其中N不是3,不应包含所有这些对中共有的任何元素。