0

Edit: I could've asked this question better and as I was re-writing it multiple people provided good answers below. Stack etiquette is to not delete an answered question, so this post shall remain up.

So here is my "reprex":

inputs <- (12.8, 30, 10, 10.3, 3.1) 

# I want a function to do the following
function(inputs)

# Output: 12.8 + 10 + 10.3 - 3.1 = 30

The tricky part is here is:

  1. I don't know what single number is going to be on the right of the equality.
  2. The only operations permitted are addition and subtraction.

The input vector will always be such that there is only one way to add/subtract numbers and come to a value that exists within the input.

I am flexible on how the output looks. Above is just an example.

solve() and other systems of equations packages I have found thus far require me to determine one side of the equality in advance.

grapestory
  • 183
  • 11
  • Is there a practical use for this? Or is this some type of programming homework assignment? – MrFlick Feb 27 '23 at 20:46
  • I am trying to detect accounting flaws in federal data collected about the environment. The data is in xbrl format, so I tried to simplify the reprex so no one had to install anything. – grapestory Feb 27 '23 at 20:48
  • 1
    How big can the problem get? Will `inputs` always be length 5, or will it be somewhere around 5, or could it get much larger? – Gregor Thomas Feb 27 '23 at 20:52
  • What are you trying to solve? Must the answer on the RHS be one of the values in the LHS? I do not know what you mean by solving. Solving involves having a designated goal. in your case, will adding all the numbers be wrong? If so that means that you have a designated goal. What is it? – Onyambu Feb 27 '23 at 20:55
  • 1
    This answer doesn't seem to be unique. What about `3.1-12.8 +30.0-10.3 == 10` and `30.0 -12.8 -10.0 + 3.1 == 10.3` – MrFlick Feb 27 '23 at 20:57
  • I will work on re-phrasing the question and perhaps post it again. Essentially I have a expense budget and then a list of costs. I am trying to ensure that the agencies reported their costs correctly (by verifying I can solve their equation), however they don't label which values are the budgets and which are the costs. – grapestory Feb 27 '23 at 21:02

3 Answers3

1

If your inputs size isn't too big, I would designate the first element as the "target" and then compute all possible sums of 1 and -1 times the other elements, something like this:

inputs <- c(12.8, 30, 10, 10.3, 3.1) 

target = inputs[1]
remaining = inputs[-1]
n = length(remaining)

## if all your lines have the same length, the `mult`
## matrix can be computed once and re-used
mult = as.matrix(do.call(expand.grid, rep(list(c(1, -1)), n)))

candidates = mult %*% remaining
i = which(abs(candidates - target) < 1e-6)  ## using a tolerance rather than == since we are dealing with floats
(results = remaining * mult[i, ])

# Var1  Var2  Var3  Var4 
# 30.0 -10.0 -10.3   3.1 
## indicating 12.8 (the target) = 30 - 10 - 10.3 + 3.1
Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
0
m <- as.data.frame(sweep(as.matrix(expand.grid(replicate(length(v), c(1,-1), simplify = FALSE))), MARGIN = 2, inputs, `*`))
m[abs(rowSums(m)) < 0.01,]


    Var1 Var2 Var3  Var4 Var5
14 -12.8   30  -10 -10.3  3.1 
19  12.8  -30   10  10.3 -3.1  
Jon Spring
  • 55,165
  • 4
  • 35
  • 53
0

See this answer. Simply set the sfind parameter to half the sum of inputs. The xfind element in the returned list is the vector of values that are either on the right side of the equation or negative on the left side of the equation (or vice versa).

findSumm(inputs, sum(inputs)/2)$xfind
#> Already found nmax solutions.
#>  Found 1 solutions in time 0.000443 seconds.
#> [[1]]
#> [1] 30.0  3.1

The result corresponds to :

12.8 + 10 + 10.3 = 30.0 + 3.1
12.8 + 10 + 10.3 - 3.1 = 30.0
12.8 + 10 + 10.3 - 3.1 - 30.0 = 0
30.0 + 3.1 - 12.8 = 10 + 10.3
.
.
. # etc

All of which are correct equalities.

A second, somewhat larger, example. (The chosen element in the returned list indicates which input elements are in xfind when sorted descending.)

set.seed(348739719)
inputs <- sample(100, 20)
inputs <- sort(c(inputs, sum(inputs*sample(c(-1L, 1L), 20, 1))), TRUE)
inputs
#>  [1] 97 89 87 83 80 76 74 65 58 50 49 43 35 33 32 24 21 11  4  2  1
idx <- which(findSumm(inputs, sum(inputs)/2)$chosen[[1]])
#> Already found nmax solutions.
#>  Found 1 solutions in time 0.000756 seconds.
sum(inputs[idx]) == sum(inputs[-idx])
#> [1] TRUE
jblood94
  • 10,340
  • 1
  • 10
  • 15