List of all 1 numbers that differ by exactly 1 digit
Here are some solutions:
1) replace_ith
replaces i-th digit in a
with 1 if it is 2 and 2 if it is 1. Apply this to each digit:
replace_ith <- function(i, a) {
ch <- strsplit(as.character(a), "")[[1]]
ch[i] <- if (ch[i] == "1") "2" else "1"
as.numeric(paste(ch, collapse = ""))
}
a <- 11121
sapply(1:nchar(a), replace_ith, a)
giving:
[1] 21121 12121 11221 11111 11122
2) Here is the second possible implementation replace_ith
:
replace_ith <- function(i, a) {
a <- as.character(a)
substr(a, i, i) <- if (substr(a, i, i) == "1") "2" else "1"
as.numeric(a)
}
3) Here is the third implementation. The three terms are digits before the i-th digit times 10^i
, the inverse of the i-th digit times 10^(i-1)
and the digits after the i-th digit:
replace_ith <- function(i, a) {
(a %/% 10^i) * 10^i + 10^(i-1) * ( 3 - (a %% 10^i) %/% 10^(i-1) ) + a %% 10^(i-1)
}
source to share
Here the answer is done purely numerically and vectorized as a single line:
(2 * a %/% (b <- 10^(1:5))) * b +
((2 * a) %% (b / 10)) +
0.3 * b - a
It works by zeroing each digit 2 * a
in turn and inserting 3 in their place, which will flip from 2 to 1, or vice versa. It creates a variable b
to shorten the code a bit. This can be removed by replacing each b
with its definition or by calling an expression inside local()
.
Here's another, using the pipe of magrittr
and matrix operator :
a %>% as.character %>% strsplit("") %>%
unlist %>% as.numeric %>% matrix(5, 5) %>%
`diag<-`(., 3 - diag(.)) %>% t %>% `%*%`(10 ^ (4:0))
And here's a neater version of the second, using purely numeric methods:
a %>% rep(5) %>% outer(4:0, function(x, y) x %/% (10 ^ y) %% 10) %>%
`diag<-`(., 3 - diag(.)) %>% `%*%`(10 ^ (0:4))
And another one using binary and using a package R.utils
:
as.character(a) %>% strsplit("") %>% {.[[1]] == "2"} %>%
multiply_by_matrix(2 ^ (4:0)) %>% bitwXor(2 ^ (4:0)) %>%
intToBin %>% as.integer(.) + 11111
source to share