Using all of the numbers 1, 3, 4, 6 exactly once, and any combination of: addition, substraction, multiplication and division (and parenthesis to group operations however you like), arrive at the number: 24.
This question was asked while in a bar with (actuarial) collegues, and let me tell you, it ruined the party (until someone found the solution). Before looking at the solution below, give it a try !
I couldn’t solve it, but I think I can have R do it for me. My approach will be to do a recursive (tree-based) brute-force search. I’ll be using the wonderful data.tree package:
library(data.tree)
Initialize a list of possible operations (from this list we wil pick with replacement):
opnames <- list('Add', 'Substract', 'Multiply', 'Divide')
ops <- list(`+`, `-`, `*`, `/`)
Initialize list of available numbers (from this list we will pick without replacement)
numbers <- c(1, 3, 4, 6)
Below is a function that recursively builds a random tree using the available numbers and the list of operations.
Each node is either an operator or a value, which we store within the node as we build the tree. Note that we use a name_prefix because siblings can’t have the same name
build_tree <- function(available_numbers, name_prefix=""){
#if there is only 1 available number left, we have to return a value
if(length(available_numbers)==1){
Node$new(paste0(name_prefix, available_numbers[1]), type="value", value=available_numbers[1])
}
#otherwise we will return an operator node
#distributing the available numbers between left and right child nodes
#then calling the build_tree function recursively
else{
op <- sample(1:length(ops), 1)
n1 <- Node$new(paste0(name_prefix, opnames[op]), type="op", func=ops[[op]])
numbers_left_size <- sample(1:(length(available_numbers)-1))
numbers_left <- sample(available_numbers, numbers_left_size)
numbers_right <- available_numbers[!(available_numbers %in% numbers_left)]
n1$AddChildNode(build_tree(numbers_left, name_prefix="a."))
n1$AddChildNode(build_tree(numbers_right, name_prefix="b."))
n1
}
}
Next we need a function to evaluate a tree (i.e. apply the operations it encodes) Obviously, this also works recursively
eval_tree <- function(tree){
if(tree$type == "value"){
tree$value
}
else{
tree$func(eval_tree(tree$children[[1]]), eval_tree(tree$children[[2]]))
}
}
Finally we can loop: build/eval until we find our solution !
success <- FALSE
iteration = 0
while(!success){
t <- build_tree(numbers)
r <- eval_tree(t)
if(r == 24){
success <- TRUE
print(sprintf("Iteration: %i", iteration))
print(t)
}
iteration <- iteration + 1
}
## [1] "Iteration: 4159"
## levelName
## 1 Divide
## 2 ¦--a.6
## 3 °--b.Substract
## 4 ¦--a.1
## 5 °--b.Divide
## 6 ¦--a.3
## 7 °--b.4
Which reads as: 6/(1-3/4) = 24.