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.