Summary

This R script solves a Cryptarithm (Crypt 4 Puzzle 1) by brute force. The “starting point” relationships are used to check every possible key permutation, obviating the need for rigorously solving the puzzle by hand.

Program

Load Dependency

First, the combinat library is loaded. This package contains the permn function used to generate the list of key permutations.

library(combinat)

Define variables and generate permutations

Next, variables are declared and the list of permutations is generated. letters is given the list of letters used in the puzzle, and numList is populated with the list of key permutations (all 10! of them).

letters <- c('n', 'a', 'f', 's', 'l', 'v', 'e', 'd', 'o', 'i')
numList <- permn(c(9, 8, 7, 6, 5, 4, 3, 2, 1, 0))

Iteratively check permutations

In each iteration, one permutation from numList is unpacked into variables representing the individual character symbols being used in the puzzle. These individual letters are then used to generate the two- and three-character blocks that define the relationships given in the puzzle. These relationships are tested, and the program exits the loop when the solution has been found.

count <- 0
success <- FALSE
while(!success){

  # iterate permutation index
  count <- count + 1
  
  # populate variables with integers from guess
  n <- numList[[count]][1]
  a <- numList[[count]][2]
  f <- numList[[count]][3]
  s <- numList[[count]][4]
  l <- numList[[count]][5]
  v <- numList[[count]][6]
  e <- numList[[count]][7]
  d <- numList[[count]][8]
  o <- numList[[count]][9]
  i <- numList[[count]][10]
  
  # generate derivative variables
  n_squared <- n^2
  af <- as.integer(paste(as.character(a), as.character(f), sep = ""))
  sa <- as.integer(paste(as.character(s), as.character(a), sep = ""))
  slv <- as.integer(paste(as.character(s), as.character(l), as.character(v), sep = ""))
  aof <- as.integer(paste(as.character(a), as.character(o), as.character(f), sep = ""))
  veo <- as.integer(paste(as.character(v), as.character(e), as.character(o), sep = ""))
  ia <- as.integer(paste(as.character(i), as.character(a), sep = ""))
  df <- as.integer(paste(as.character(d), as.character(f), sep = ""))
  vs <- as.integer(paste(as.character(v), as.character(s), sep = ""))

  # check conditions
  if((n_squared == af) && (sa - af == s) && (slv - aof == veo) && (ia - df == vs) )
      success <- TRUE
}

Format and return result

The result is returned by printing the puzzle’s letters in the order corresponding to their equivalents in the numeric key.

print(paste("Solution found at permutation number", count))
## [1] "Solution found at permutation number 1429777"
print(letters[order(numList[[count]], decreasing = TRUE)])
##  [1] "f" "i" "n" "d" "s" "a" "l" "o" "v" "e"

All that remains is to identify the three words given by the ordered string of letters.