8

如何在 R 中反转一串数字?

例如,我有一个大约 1000 个六位数字的向量,我想知道它们是否是回文。我想创建一个完全相反的第二组,所以我可以进行对决。

4

7 回答 7

14

它实际上是您要测试为回文的数字的十进制表示,而不是数字本身(255 是十六进制和二进制的回文,但不是十进制)。

您可以使用模式匹配相当简单地做到这一点:

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

您可以将数字转换为字符,拆分为单个字符(strsplit),反转每个数字(sapply 和 rev),然后将值重新粘贴在一起(粘贴)并转换回数字(as.numeric)。但我认为,如果您只对 6 位数字键盘感兴趣,上述方法会更好。

于 2010-09-21T19:17:22.393 回答
5

我不认为rev完全做到了。它反转向量的元素,而问题是如何反转向量的元素。

> 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"
于 2010-09-21T19:11:06.673 回答
4

编辑:我误读了这个问题。这是我对后代的回答。


您可以使用以下rev功能:

> 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
于 2010-09-21T19:05:32.937 回答
2

这应该适用于一般情况,可以选择任何基础:

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))
}
于 2010-09-22T09:52:10.043 回答
2

包中有功能stringi-stri_reverse

require(stringi)
stri_reverse("123456")
## [1] "654321"

现在回文函数可能就这么简单:

palindrome <- function(x) stri_reverse(x)==x
palindrome(c("651156","1234321"))
## [1] TRUE  TRUE
于 2014-04-11T14:24:24.420 回答
1

如果您对反转感兴趣,可以将 sub 与 Greg 的正则表达式的较长版本一起使用:

> 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"

虽然这比拆分/旋转/粘贴快吗?

于 2010-09-21T19:46:21.580 回答
0

使用intToUtf8进行拆分,然后反向:

tmp <- c(100001, 123321, 123456)

res <- sapply(tmp, function(i) intToUtf8(rev(utf8ToInt(as.character(i)))))

res
# [1] "100001" "123321" "654321"

要检查它是否是回文:

tmp == res
# [1]  TRUE  TRUE FALSE

基准

# bigger vector
tmpBIG <- rep(c(100001, 123321, 123456), 4000)

bench::mark(
  GregSnow = { grepl( '^([0-9])([0-9])([0-9])\\3\\2\\1$', tmpBIG) },
  bartektartanus = { tmpBIG == stringi::stri_reverse(tmpBIG) },
  Spacedman = { tmpBIG == sub( '^([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])','\\6\\5\\4\\3\\2\\1', tmpBIG) },
  Joshua = { tmpBIG == sapply(strsplit(as.character(tmpBIG),""), function(i) paste(rev(i),collapse="")) },
  zx8754 = { tmpBIG == sapply(tmpBIG, function(i) intToUtf8(rev(utf8ToInt(as.character(i))))) },
  relative = TRUE)[, 1:9]

# expression         min median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time
# <bch:expr>       <dbl>  <dbl>     <dbl>     <dbl>    <dbl> <int> <dbl>   <bch:tm>
# 1 GregSnow        1      1         6.82      1         NaN    23     0      517ms
# 2 bartektartanus  1.38   1.34      5.02      2.33      NaN    17     0      520ms
# 3 Spacedman       1.58   1.55      4.52      2.33      NaN    15     0      509ms
# 4 Joshua          5.82   5.56      1.24      5.29      Inf     5     6      617ms
# 5 zx8754          6.06   6.17      1         3.98      Inf     4     4      614ms
于 2019-12-02T12:01:27.160 回答