我有n=4
名为A
,B
,C
和D
的人。有些人可以属于同一组,有些则不能。此信息由以下内容给出(在R
中编码)
comparisons = c("A-B", "A-C", "A-D", "B-C", "B-D", "C-D")
areEnemies = c(FALSE, FALSE, TRUE, FALSE, FALSE, TRUE)
根据这些数据,个人A
和D
是敌人,不能属于同一群组。个人C
和D
以及敌人也不能属于同一群组。所有其他人都是朋友(当你不是你的敌人时,那么他就是你的朋友)。
我的目标是创建群组
上述示例的解决方案(使用组名称的小写字母)是
A
属于群组a
B
属于群组a
和群组b
C
属于群组a
D
属于群组b
我无法解决这个问题。你能提供帮助吗?
如果你想编写代码,我欢迎使用R,C,C ++,Java,Bash,Python,但对流程(或伪代码)的口头描述已经非常有用。请注意,性能不会太受关注,因为我通常只有5-10个人,并且不会经常运行此过程。
答案 0 :(得分:2)
您所描述的内容基本上是图形问题
数据
library(tidyverse)
df <- tibble(A = c("A", "A", "A", "B", "B", "C"),
B = c("B", "C", "D", "C", "D", "D"),
lgl = c(FALSE, FALSE, TRUE, FALSE, FALSE, TRUE))
# A tibble: 6 x 3
# A B lgl
# <chr> <chr> <lgl>
# 1 A B F
# 2 A C F
# 3 A D T
# 4 B C F
# 5 B D F
# 6 C D T
1 - 从数据框中过滤掉敌人,2 - 然后制作无向图(绘制它以查看它)。 3 - 确定图表的max_cliques
。
library(igraph)
data <- filter(df, lgl == FALSE) # friends
G <- graph_from_data_frame(data, directed=FALSE)
plot(G)
max_cliques(G)
# [[1]]
# + 2/4 vertices, named, from 5940a66:
# [1] D B
# [[2]]
# + 3/4 vertices, named, from 5940a66:
# [1] A B C
答案 1 :(得分:0)
#checks if two people are enemies
def areEnimies(a, b, enemies):
for x in enemies:
if (x[0] is a and x[1] is b) or (x[1] is a and x[0] is b):
return True
return False
enemies = ["AD", "CD"] #list of enemies side by side
people = "ABCD" #the list of people who are in the game
groups = []
ans = []
#for each unique enemy, give them there own group
for x in enemies:
if not x[0] in groups:
groups.append(x[0])
if not x[1] in groups:
groups.append(x[1])
#populate this group with everyone else who is not their enemy
for g in range(len(groups)):
for p in people:
if not areEnimies((groups[g])[0], p, enemies) and (groups[g])[0] != p:
groups[g] += p
#sort each group
for g in range(len(groups)):
groups[g] = sorted(groups[g])
#if any groups are duplicates of one another we can remove them
for i in range(len(groups)):
dup = False
for j in range(i+1, len(groups)):
if groups[i] == groups[j]:
dup = True
break
if not dup:
ans.append(groups[i])
print(ans)
输出= [['A','B','C'],['B','D']]
> This is what I came up with
> 1. Write down each unique person that is enemies with someone
> 2. Populate each of those lists with friends
> 3. Remove duplicate groups if they exist
敌人由无序对给出,被放入群组的人用字符串表示,请注意我们不需要朋友列表,因为任何不是敌人的人都可以认为是朋友。可能有更有效的方法来做到这一点,但它适用于小组,并使用我试过的几个不同的输入
干杯!
答案 2 :(得分:0)
问题本质上是图论问题。以下是要采取的步骤
以下是R
### input data
d <- tibble(A = c("A", "A", "A", "B", "B", "C"),
B = c("B", "C", "D", "C", "D", "D"),
friend = c(TRUE, TRUE, FALSE, TRUE, TRUE, FALSE))
### list vertices
vertexes = unique(c(d$from,d$to))
## Create graphs of friends
dFriend = d[d$friend,]
gFriend = graph.data.frame(dFriend, directed=FALSE)
## List all cliques
cliques = lapply(cliques(gFriend), function(x) {names(x)})
## Remove cliques that are contained within other cliques
if (length(cliques))
{
cliqueIndicesToRemove = c()
for (i in 1:length(cliques))
{
clique_sub = cliques[[i]]
for (j in 1:length(cliques))
{
if (i!=j)
{
clique_sup = cliques[[j]]
if (all(clique_sub %in% clique_sup))
{
cliqueIndicesToRemove = c(cliqueIndicesToRemove, i)
}
}
}
}
cliques = cliques[-unique(cliqueIndicesToRemove)]
}
## return object
r = tibble(
cliques = "",
vertex = vertexes
)
if (length(cliques))
{
for (i in 1:length(cliques))
{
clique = cliques[[i]]
matchingVertexes = which(r$vertex %in% clique)
for (match in matchingVertexes)
{
r$cliques[match] = paste0(r$cliques[match], letters[i] )
}
}
}
## Make sure that vertices with no friend still get assigned to a clique
nextLetterIndex = length(cliques) + 1
for (i in 1:nrow(r))
{
if (r$cliques[i] == "")
{
r$cliques[i] = letters[nextLetterIndex]
nextLetterIndex = nextLetterIndex + 1
}
}
这个解决方案非常受@ CPak答案的启发。