在R中找到X + 2Y + 5Z = 12的非负整数解

时间:2016-05-07 06:30:38

标签: r data-manipulation

我使用了“for”循环和“if”条件来解决它。       我正在寻找智能和快速的解决方案

2 个答案:

答案 0 :(得分:4)

这是一个通用解决方案:

solve.linear.nonneg <- function(...) {
    args <- list(...);
    if (!all(sapply(args,is.integer))) stop('all arguments must be integers.');
    args <- do.call(c,args);
    if (length(args)<1L) stop('missing rhs.');
    if (length(args)<2L) stop('missing coefs.');
    coefs <- args[-length(args)];
    rhs <- args[length(args)];
    cns <- make.unique(sep='',rep(c(letters[24:26],letters[23:1]),len=length(coefs)));
    can <- do.call(expand.grid,setNames(nm=cns,lapply(coefs,function(x) if (x==0L) 0L else 0:(rhs%/%x))));
    can[Reduce(`+`,Map(`*`,coefs,can))==rhs,,drop=F];
}; ## end solve.linear.nonneg()

一些演示:

solve.linear.nonneg(3L,9L); ## 3x = 9
##   x
## 4 3
solve.linear.nonneg(3L,3L,9L); ## 3x + 3y = 9
##    x y
## 4  3 0
## 7  2 1
## 10 1 2
## 13 0 3
solve.linear.nonneg(1L,2L,3L,4L,6L); ## x + 2y + 3z + 4w = 6
##    x y z w
## 7  6 0 0 0
## 12 4 1 0 0
## 17 2 2 0 0
## 22 0 3 0 0
## 32 3 0 1 0
## 37 1 1 1 0
## 57 0 0 2 0
## 87 2 0 0 1
## 92 0 1 0 1

你的等式:

solve.linear.nonneg(1L,2L,5L,12L); ## x + 2y + 5z = 12
##      x y z
## 13  12 0 0
## 24  10 1 0
## 35   8 2 0
## 46   6 3 0
## 57   4 4 0
## 68   2 5 0
## 79   0 6 0
## 99   7 0 1
## 110  5 1 1
## 121  3 2 1
## 132  1 3 1
## 185  2 0 2
## 196  0 1 2

答案 1 :(得分:2)

请注意,手动解决这个问题并不困难。

Z只能是0,1或2,因此注意到在替换Z后Y项始终是偶数,减少右侧X必须是偶数或奇数,因为右侧减小:

  • 如果Z = 0,那么我们有X + 2Y = 12因此X必须是偶数,因此对于X连续使用0,2,4,6,8,10,12并且求解Y,解是(0 ,6,0),(2,5,0),(4,4,0),(6,3,0),(8,2,0),(10,1,0),(12,0) ,0)。

  • 如果Z = 1,那么我们得到X + 2Y = 7,这意味着X是奇数,因此对X连续使用1,3,5,7并求解Y,解是(1,3,1) ,(3,2,1),(5,1,1),(7,0,1)。

  • 如果Z = 2,那么我们得到X + 2Y = 2,这意味着X必须是偶数,因此对于X连续使用0和2并求解Y,解是(0,1,2),(2, 0,2)。

我们可以通过蛮力双重检查上面的内容 - 我们可以分别使用12,6和2作为X,Y和Z的上限,因为很明显它们不能超过这些值但是因为问题很小而简单我们在每种情况下使用12:

subset(expand.grid(X = 0:12, Y  = 0:12, Z = 0:12), X + 2*Y + 5*Z == 12)

给出与手算相对应的以下内容:

     X Y Z
13  12 0 0
24  10 1 0
35   8 2 0
46   6 3 0
57   4 4 0
68   2 5 0
79   0 6 0
177  7 0 1
188  5 1 1
199  3 2 1
210  1 3 1
341  2 0 2
352  0 1 2