6

I think an example should make things clear enough.

I have

a_1 = 6547

and I want some function that transform a_1 into the following a_2

a_2 = c(6, 5, 4, 7)

Remi.b
  • 17,389
  • 28
  • 87
  • 168
  • This has been answered a couple times on SO. Naturally, I can't find them, but if you track the other questions down, you'll find some, errr... creative solutions. – Carl Witthoft Nov 04 '13 at 12:31
  • 1
    Found the link: http://stackoverflow.com/questions/18786432/program-for-armstrong-number-in-r/18786780#18786780 – Carl Witthoft Nov 04 '13 at 12:44

5 Answers5

15

Convert to character then split will do the trick

a <- 6547
as.numeric(strsplit(as.character(a), "")[[1]])
## [1] 6 5 4 7
CHP
  • 16,981
  • 4
  • 38
  • 57
14
(a %% c(1e4, 1e3, 1e2, 1e1)) %/% c(1e3, 1e2, 1e1, 1e0)

This is 3-4x as fast on my computer than doing a strsplit. But the strsplit is a lot more elegant and the difference decreases with longer vectors.

library(microbenchmark)
microbenchmark((a %% c(1e4, 1e3, 1e2, 1e1)) %/% c(1e3, 1e2, 1e1, 1e0))
# median of 1.56 seconds
microbenchmark(as.numeric(strsplit(as.character(a), "")[[1]]))
# median of 8.88 seconds

Edit: using Carl's insight, here is a more general version.

a <- 6547
dig <- ceiling(log10(a))
vec1 <- 10^(dig:1)
vec2 <- vec1/10
(a%%vec1)%/%vec2
Anirban
  • 271
  • 2
  • 8
  • 2
    You should rewrite to handle the general case, by calculating `log10(a)` and using the (truncated or rounded) value to set the maximum power you wish to divide by. I wrote the code for that in some previous answer on SO but can't track it down just now. – Carl Witthoft Nov 04 '13 at 12:33
  • Interesting approach. Would be interesting to see if this is faster for very long vectors? – CHP Nov 09 '13 at 06:04
  • 1
    This code is actually incorrect and fails for numbers which are a power of 10, (100,1000,10000 etc.). This can easily be explained by the fact that ceiling(log10(1000)) == 3, and not 4. I think the code can be corrected by: dig <- floor(log10(a)+1). It also does not work for 0, but my change does not fix that. – Arno Kalkman Nov 27 '14 at 11:12
1

This also works. It's slower than the other answers, but possibly easier to read...

library(stringr)
as.integer(unlist(str_split(a, "")))[-1]
dardisco
  • 5,086
  • 2
  • 39
  • 54
0

I think you should use power of 10 to do it. And recursivly, downgrade this power , add the part found in vector and remove this to a_1. 6 x 1000, 5 x 100, 4 x 10, 7 x1 .....

Mayhem50
  • 165
  • 2
  • 8
0

Maybe this gather both the faster solutions in a single line:

a <- 6547
(a%%(10^(floor(log10(a)+1):1)))%/%((10^(floor(log10(a)+1):1))/10)

[1] 6 5 4 7