How to generate random words from a list of characters?

Viewed 521

I would like to generate a list of 50 words from the letters "a b c d". every word should have 5 characters. every word has to be different from the others in at least 2 positions (letters) using base R.

x="a,b,c,d"

and results should be list of 50 words:

l=['abcda','cdabd','bdaca'.......]

expand.grid function in R generate words with only 1 letter difference.

2 Answers

If you want to sample from a complete set of words, you can first construct such complete set as the first step (see X in the code below), and then you can reuse it for multiple times by running sample(X, 50) simply

v <- do.call(paste0, expand.grid(rep(list(letters[1:4]), 5)))
X <- Reduce(
  function(S, k) {
    if (all(adist(k, S) >= 2)) {
      S <- c(S, k)
    }
    S
  }, v
)
res <- sample(X, 50)

Another option is using while loop and keeping the set of selected words updated in each iteration

res <- paste0(sample(letters[1:4], 5, replace = TRUE), collapse = "")
while (length(res) < 50) {
  k <- paste0(sample(letters[1:4], 5, replace = TRUE), collapse = "")
  if (all(adist(k, res) >= 2)) {
    res <- c(res, k)
  }
}
res

First we need to create an helper which tests if two words have at least two positions (letters) different:

two_char_distinct <- function(word_1, word_2) {
  sum( ! unlist(strsplit(word_1, "")) == unlist(strsplit(word_2, ""))) > 1 
}

Edit: It is better to use adist see @ThomasCoding answer


Then you genereate a word with sample() and add it to the vector words only if it is different (two_char_distinct) from all other words:

words <- c()
while(length(words) < 50) {
  new_word <- paste0(sample(letters[1:4], size = 5, replace = T),
                    collapse = "")
  tests <- sapply(words, function(w) two_char_distinct(w, new_word))
  if(all(tests)) words <- c(words, new_word)
}

words

output

 [1] "cdbdc" "bdacc" "cdaad" "dbcca" "baaac" "bdadd" "cbbbd" "dcccb" "ddcad"
[10] "dabdd" "dcacc" "cabdb" "dcada" "ddbba" "acbdc" "cddda" "badbd" "bcbad"
[19] "ccdcb" "addbc" "dcddc" "bcbcc" "dacaa" "ccdba" "badda" "abaca" "adcca"
[28] "bacdc" "dacbd" "bbdcd" "bbcdb" "adbcd" "bcbdb" "cbadb" "caadc" "cbabc"
[37] "bccbc" "bdcda" "dddab" "cdcac" "cbbaa" "bbbba" "ccaab" "adbda" "bddaa"
[46] "aaabd" "abcbc" "cadcd" "aaaaa" "baacb"
Related