LoveVegas
LoveVegas

Reputation: 11

Exchange the order of only the middle letters of a word and keep the order of the punctuation mark if there is one

I require a function that exchanges only the characters of the middle of the word (between first and last character). The function should not change anything if the word is composed of less than 4 characters. The function has an argument called exclude which is a vector of potential punctuation marks at the end of a word.

You can assume that there is only one possible punctuation mark. If there is such a mark, it should not be changed and not counted towards the number of characters the actual word is composed of.

My idea is to


string <-c("well!")
interchange.middle.of.word <- function(string, exclude = c(",",".","!","?")){
  result1 <- strsplit(string, split= "")
  result2 <- unlist(result1)
  result3 <- result2[ - which(result2 %in% exclude)]
  result4 <- head(result3,-1)
  result5 <- tail(result4,-1)
  result6 <- sample(result5,replace = FALSE)
  result7 <- c(result3[1],result6)
  result8 <- c(result7, result4[length(result4)])
  result9 <- c(result8, result2[which(result2 %in% exclude)])
  result10 <- paste(result9,collapse="")
  return(result10)
}

The code worked for the example 'well!', but not for another example like 'hello?' or words less than 3 letters like 'Tes':

I would be grateful if anyone can tell me where I went wrong about the code. Many thanks.

Upvotes: 1

Views: 77

Answers (1)

bgoldst
bgoldst

Reputation: 35314

Assuming you want to reverse the order of the middle characters:

revmiddle <- function(s,exclude=c(',','.','!','?')) {
    if (nchar(s)<4L) return(s);
    x <- strsplit(s,'')[[1L]];
    if (x[length(x)]%in%exclude) {
        punc <- x[length(x)];
        x <- x[-length(x)];
    } else {
        punc <- NULL;
    }; ## end if
    paste(collapse='',c(x[1L],x[seq(length(x)-1L,2L)],x[length(x)],punc));
}; ## end revmiddle()

Demo:

revmiddle('well!');
## [1] "wlel!"
revmiddle('hello?');
## [1] "hlleo?"
revmiddle('Tes');
## [1] "Tes"

To randomize the order of the middle characters:

randmiddle <- function(s,exclude=c(',','.','!','?')) {
    if (nchar(s)<4L) return(s);
    x <- strsplit(s,'')[[1L]];
    if (x[length(x)]%in%exclude) {
        punc <- x[length(x)];
        x <- x[-length(x)];
    } else {
        punc <- NULL;
    }; ## end if
    paste(collapse='',c(x[1L],sample(x[-c(1L,length(x))]),x[length(x)],punc));
}; ## end randmiddle()

Demo (intentionally performing many executions and collecting sorted unique results, which effectively demonstrates all possible outcomes):

sort(unique(replicate(1e3L,randmiddle('well!'))));
## [1] "well!" "wlel!"
sort(unique(replicate(1e3L,randmiddle('hello?'))));
## [1] "hello?" "hlelo?" "hlleo?"
sort(unique(replicate(1e3L,randmiddle('Tes'))));
## [1] "Tes"

Upvotes: 2

Related Questions