Reputation: 357
I want to write a function to reverse the order of any numbers. Here is what I have but it doesn't work. Please help me!
n=123
rev_number=function(n){
m=strsplit(as.character(n),"")
if (m==rev(m)) print("reversed number")
}
The desired output is n=321
Upvotes: 7
Views: 12119
Reputation: 102710
Here are some other base R options using utf8ToInt
or substring
> n <- 123478634
> as.integer(intToUtf8(rev(utf8ToInt(as.character(n)))))
[1] 436874321
> as.integer(paste0(substring(n, nchar(n):1, nchar(n):1), collapse = ""))
[1] 436874321
Upvotes: 1
Reputation: 31
Here's my attempt by extending your code
n=-123
rev_number=function(n){
if(n>0)
return(as.integer(paste0(rev(unlist(strsplit(as.character(n), ""))), collapse = "")))
else{
return(-as.integer(paste0(rev(unlist(strsplit(as.character(abs(n)), ""))), collapse = "")))
}
}
rev_number(n)
If else is to handle negative numbers. First it converts the integer to characters and then uses strsplit to split the number. Then unlist is used to convert the list to vector. Then we can use rev to reverse the vector and collapse the vector using paste. Finally as.integer is used to convert the string in to int.
If you do not wish to convert the number to characters, below one does not need any additional packages but only works with positive integers
reverse_number <- function(n){
rev <- 0
while (n > 0) {
r <- n %% 10
rev <- rev * 10 + r
n <- n %/% 10
}
return(rev)
}
reverse_number(134576)
Upvotes: 2
Reputation: 3649
An R function to reverse numbers based on integer division with successive powers of 10. This came up in a school project related to palindrome numbers.
Reverse_number <- function(x){
n <- trunc(log10(x)) # now many powers of 10 are we dealing with
x.rem <- x # the remaining numbers to be reversed
x.out <- 0 # stores the output
for(i in n:0){
x.out <- x.out + (x.rem %/% 10^i)*10^(n-i) # multiply and add
x.rem <- x.rem - (x.rem %/% 10^i)*10^i # multiply and subtract
}
return(x.out)
}
Upvotes: 1
Reputation: 92300
I feel like reverse an integer should stay in the integer world instead of getting into the string manipulation world. It seems there isn't a built in function for such task in R, so we can create one, using the Rcpp package for instance. Here's an example
library(Rcpp)
cppFunction('int Reverse_CPP(int x) {
int reverse = 0;
while(x != 0) {
int remainder = x%10;
reverse = reverse*10 + remainder;
x/= 10;
}
return reverse ;
}')
Reverse_CPP(1234)
# [1] 4321
And here's a vectorized version
cppFunction('IntegerVector Reverse_CPP2(IntegerVector x) {
int n = x.size();
IntegerVector out(n);
IntegerVector xx = clone(x); // Will need this if you don"t want to modify x in place
for (int i = 0; i < n; ++i){
int reverse = 0;
while(xx[i] != 0) {
int remainder = xx[i]%10;
reverse = reverse*10 + remainder;
xx[i]/= 10;
}
out[i] = reverse;
}
return out;
}')
Reverse_CPP2(c(12345, 21331, 4324234, 4243))
# [1] 54321 13312 4324234 3424
Note that I had to add IntegerVector xx = clone(x);
and hence slow the function drastically (see @alexis_laz comment) as Rcpp will modify the original x
by reference otherwise. You don't need that if you are passing a bare vector or if you don't care if the original vector is being modifyied
Some benchmarks against other vectorized string manipulation functions
Stringi <- function(x) as.integer(stringi::stri_reverse(x))
Base <- function(x) {
as.integer(vapply(lapply(strsplit(as.character(x), "", fixed = TRUE), rev),
paste, collapse = "", FUN.VALUE = character(1L)))
}
library(microbenchmark)
set.seed(123)
x <- sample(1e3L:1e7L, 1e5, replace = TRUE)
microbenchmark(
Base(x),
Stringi(x),
Reverse_CPP2(x)
)
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# Base(x) 855.985729 913.602215 994.60640 976.836206 1025.482170 1867.448511 100 c
# Stringi(x) 86.244426 94.882566 105.58049 102.962924 110.334702 179.918461 100 b
# Reverse_CPP2(x) 1.842699 1.865594 2.06674 1.947703 2.076983 6.546552 100 a
Upvotes: 13
Reputation: 23818
For integers n > 9
this function can be used:
reverse_int <- function(n) {
t1 <- floor(log10(n))
t2 <- 0
for (i in t1:1) t2 <- t2 + floor(n/10^i) * 10^(t1-i)
return(n*10^t1 - 99*t2)
}
reverse_int(678754)
#[1] 457876
Note that the function is not vectorized; it only takes one parameter n
as input.
Upvotes: 1