Как заменить все буквы в слове на пару, созданную в предыдущей функции? - PullRequest
4 голосов
/ 19 июня 2020

Сначала я создал функцию, которая дает мне шаблон криптографии

plugboard <- function(){
  matrix(sample(letters, 26), nrow = 2, ncol = 13)
} 

Это дает мне матрицу, в которой каждая буква (в нижнем регистре) соединена с другой.

Теперь мне нужно создайте другую функцию, которая или закодирует, или декодирует в этой криптографии, поэтому, если у меня есть:

    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
[1,] "v"  "h"  "k"  "a"  "w"  "l"  "f"  "d"  "u"  "r"   "t"   "m"   "s"  
[2,] "p"  "q"  "b"  "g"  "x"  "y"  "i"  "n"  "z"  "o"   "j"   "e"   "c"  

Тогда, если я введу эту новую функцию «ДОМ» или «дом», она даст мне: «qrzcm» и если я наберу «qrzcm», получится «дом».

Я пробовал сделать следующее:

ATdecoder <- function(word){
  word <- x
  pat <- data.frame(plugboard())
  tolower(x)
  x = gsub(pat$V1, pat$V2, x)
}

Но я изо всех сил пытаюсь заставить это работать.

Пожалуйста помощь

Ответы [ 3 ]

4 голосов
/ 19 июня 2020

Вам нужно установить семя, я не могу воспроизвести ваш домашний пример. Скорее всего, вам нужно объявить декодер вне функции, иначе он будет каждый раз отличаться!

Две вещи: 1) вам нужно разделить строку ввода на отдельные символы, а во-вторых, вы просто сопоставите их с первую строку вашей матрицы, вызовите вторую строку.

Превращение его в data.frame не помогает, потому что первая строка не распознается как имя столбца.

Do:

plugboard <- function(){
  matrix(sample(letters, 26), nrow = 2, ncol = 13)
}

set.seed(111)
pat <- plugboard()

pat

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
[1,] "n"  "s"  "e"  "h"  "m"  "d"  "y"  "i"  "a"  "v"   "r"   "u"   "p"  
[2,] "t"  "o"  "c"  "q"  "j"  "w"  "x"  "z"  "g"  "l"   "f"   "k"   "b"  

ATdecoder <- function(word,pat){
  x <- unlist(strsplit(tolower(word),""))
  if(all(x %in% pat[1,])){
  paste(pat[2,match(x,pat[1,])],collapse="")
  }else{
  paste(pat[1,match(x,pat[2,])],collapse="")
  }
}

ATdecoder("pave",pat)
[1] "bglc"
> ATdecoder("bglc",pat)
[1] "pave"
1 голос
/ 20 июня 2020

Как указано в комментариях, chartr - хороший вариант для этого. Кроме того, как указано в ответе @ StupidWolf, потребуется seed, поэтому я написал функцию, включающую set.seed. Вот один из вариантов:

opt1 <- function(word, seed = 1) {
  set.seed(seed)
  a <- matrix(sample(letters, 26), nrow = 2, ncol = 13)
  b <- apply(a, 1, paste, collapse = "")
  chartr(paste(b, collapse = ""), paste(rev(b), collapse = ""), tolower(word))
}

Вот функция в действии:

opt1("house")
# [1] "ianes"
opt1(opt1("house"))
# [1] "house"

## Different seed
opt1("house", 2)
# [1] "batlr"

В качестве альтернативы функцию можно записать так, используя strsplit и match. Обратите внимание, что я только что расширил таблицу поиска, чтобы упростить работу.

opt2 <- function(word, seed = 1) {
  set.seed(seed)
  a <- matrix(sample(letters, 26), nrow = 2, ncol = 13)
  a <- cbind(a, a[2:1, ])
  s_word <- strsplit(tolower(word), "", TRUE)[[1]]
  paste(a[2, ][match(s_word, a[1, ])], collapse = "")
}

Лично мне opt1 нравится больше из-за того, как он обрабатывает более длинные строки. Из-за использования match в opt2 символы, которых нет на входе, сопоставляются с NA, что может привести к некрасивому результату. Рассмотрим следующие примеры:

opt1("This is a string, isn't it?")
# [1] "rihe he o erthuj, heu'r hr?"
opt2("This is a string, isn't it?")
# [1] "riheNAheNAoNAerthujNANAheuNArNAhrNA"

В этом случае только opt1 более или менее обратимо (без заглавных букв):

opt1("rihe he o erthuj, heu'r hr?")
# [1] "this is a string, isn't it?"
1 голос
/ 19 июня 2020

В качестве альтернативы вы можете рассчитать смещения и применить их к базовым байтам utf8

plugboard <- c("v","h","k","a","w","l","f","d","u","r","t","m","s",
               "p","q","b","g","x","y","i","n","z","o","j","e","c" )


offsets <- utf8ToInt(paste0(plugboard[c(14:26, 1:13)], collapse = "")) - 
  utf8ToInt(paste0(plugboard, collapse = ""))


ATdecoder <- function(word){

  word <- tolower(word)

  bytes <- utf8ToInt(word)

  myOffsets <- offsets[match(strsplit(word, "")[[1]], plugboard)]

  paste0(intToUtf8(bytes + myOffsets), collapse = "")

}

ATdecoder("house")
[1] "qrzcm"

ATdecoder("HOUSE")
[1] "qrzcm"

ATdecoder("qrzcm")
[1] "house"
...