Вид ради добавления еще одной опции с использованием двоичной логики:
Предполагая, что ваша строка всегда имеет длину 4 символа:
input<-"ECET"
invec <- strsplit(input,'')[[1]]
sapply(1:7, function(x) {
z <- invec
z[rev(as.logical(intToBits(x))[1:4])] <- "X"
paste0(z,collapse = '')
})
[1] "ECEX" "ECXT" "ECXX" "EXET" "EXEX" "EXXT" "EXXX"
Если строка должна быть длиннее, вы можете вычислить значения со степенью 2, что-то вроде этого должно сделать:
input<-"ECETC"
pow <- nchar(input)
invec <- strsplit(input,'')[[1]]
sapply(1:(2^(pow-1) - 1), function(x) {
z <- invec
z[rev(as.logical(intToBits(x))[1:(pow)])] <- "X"
paste0(z,collapse = '')
})
[1] "ECETX" "ECEXC" "ECEXX" "ECXTC" "ECXTX" "ECXXC" "ECXXX" "EXETC" "EXETX" "EXEXC" "EXEXX" "EXXTC" "EXXTX" "EXXXC"
[15] "EXXXX"
Идея состоит в том, чтобы узнать количество возможных изменений, это двоичный файл из 3 позиций, поэтому 2 ^ 3 минус 1, так как мы не хотим оставлять строку без замены: 7
intToBits возвращает двоичное значение целого числа для 5:
> intToBits(5)
[1] 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
R использует 32 бита по умолчанию, но мы просто хотим, чтобы логический вектор соответствовал нашей длине строки, поэтому мы просто сохраняем nchar исходной строки.
Затем мы конвертируем в логическое и инвертируем эти 4 логических значения, так как мы никогда не будем запускать последний бит (8 для 4 символов), он никогда не будет истинным:
> intToBits(5)
[1] 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> tmp<-as.logical(intToBits(5)[1:4])
> tmp
[1] TRUE FALSE TRUE FALSE
> rev(tmp)
[1] FALSE TRUE FALSE TRUE
Чтобы избежать перезаписи нашего исходного вектора, мы копируем его в z, а затем просто заменяем позицию в z, используя этот логический вектор.
Для хорошего вывода мы возвращаем paste0 с collapse как ничто, чтобы воссоздать одну строку и получить символьный вектор.