views:

175

answers:

6

How can you reverse a string of numbers in R?

for instance, I have a vector of about 1000 six digit numbers, and I would like to know if they are palindromes. I would like to create a second set which is the exact reverse, so I could do a matchup.

A: 

what language are you working with?

EvanGWatkins
I'm using R -- It's better for stats though
@EvanGWatkins: This is a comment, not an answer.
Shane
@EvanGWatkins Welcome to Stackoverflow. We typically use comments below the orginal post for this type of question. Please refrain from using Answers to essentially enrich the original question but not really address it. Note: you may not have enough points yet to add comments; this will come soon...
mjv
haha, so much sass
My bad I didn't know how to add a comment I'm new to this...
EvanGWatkins
@EvanGWatkins No worries. While you're at it, you might try voting on answers to some of the questions that you've asked.
Shane
+2  A: 

Edit: I misread the question. Here's my answer for posterity.


You can use the rev function:

> 1:10
 [1]  1  2  3  4  5  6  7  8  9 10
> rev(1:10)
 [1] 10  9  8  7  6  5  4  3  2  1
Shane
can you apply that to individual indices? so get 1 2 3 etc. 8 9 01 11 21 31 41 etc
See Josh's answer; the `strsplit` function is usually used to divide a substring.
Shane
+3  A: 

I don't think rev quite does it. It reverses the elements of the vector, while the question is how to reverse the elements in the vector.

> nums <- sapply(1:10,function(i)as.numeric(paste(sample(1:9,6,TRUE),collapse="")))
> nums
 [1] 912516 568934 693275 835117 155656 378192 343266 685182 298574 666354
> sapply(strsplit(as.character(nums),""), function(i) paste(rev(i),collapse=""))
 [1] "615219" "439865" "572396" "711538" "656551" "291873" "662343" "281586" "475892" "453666"
Joshua Ulrich
+1 Oh wow. Nice work on close reading (http://en.wikipedia.org/wiki/Close_reading)!
Shane
+8  A: 

It is actually the decimial representation of the number that you are testing to be a palindrome, not the number itself (255 is a palendrome in hex and binary, but not decimal).

You can do this fairly simply using pattern matching:

> tmp <- c(100001, 123321, 123456)
> grepl( '^([0-9])([0-9])([0-9])\\3\\2\\1$', tmp )
[1]  TRUE  TRUE FALSE
> 

you could convert the numbers to character, split into individual characters (strsplit), reverse each number (sapply and rev), then paste the values back together (paste) and covert back to numbers (as.numeric). But I think the above is better if you are just interested in 6 digit palendromes.

Greg Snow
Nice answer Greg. I couldn't decide if the `strsplit` or regex method would be more straight-forward but, like you, I prefer the regex method. It may help to explain *why* the regular expression works.
Joshua Ulrich
thanks -- this is nice -- I had tried the strsplit, it was ugly
What does the hat in the grepl line do -- also, what do the double back slashes do?
The hat (^) matches the beginning of a string, the dollar sign ($) matches the end. This makes it so that only 6 digit numbers will match, not parts of 7 or greater. If you know that all numbers are at most 6 digits then both could be left off.
Greg Snow
The backslashes are doubled because the R string parser will evaluate them first, this leaves a single backslash for the regular expression, \1 means match what was matched by the 1st set of parentheses, \2 means match what was matched by the second, etc.
Greg Snow
got it -- thanks!
A: 

If you are interested in the reversals for their own sake, you can use sub with a longer version of Greg's regexp:

> x
[1] 123321 343324 563660
> sub( '^([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])','\\6\\5\\4\\3\\2\\1', x)
[1] "123321" "423343" "066365"

Although is this quicker than split/rev/paste?

Spacedman
Yes, regular expressions are faster (~5-10x) than then split/rev/paste/as.numeric.
Joshua Ulrich
A: 

This should work in the general case, with any choice of base:

is.palindromic <- function(x, base=10)
{
    p <- 0
    m <- floor(log(x,base))
    sig <- -1
    for (i in m:0)
        {
        tp <- floor(x/base^i)
        a <- i+1
        b <- m+1-i
        if(a==b){c<-0}else{c<-a*b;sig<-sig*-1}
        p <- p + tp*c*sig
        x <- x - tp*base^i
        }
    return(!as.logical(p))
}
James