R で解く FizzBuzz 問題
description
Transcript of R で解く FizzBuzz 問題
R で解くFizzBuzz 問題
kos59125[2011-11-19] Tokyo.R#19
FizzBuzz•以下の条件で 1 から数字を数え上げる✓ 3 の倍数のときは Fizz✓ 5 の倍数のときは Buzz✓ 3 の倍数かつ 5 の倍数のときは FizzBuzz
やってみよう
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
…
FizzBuzz 問題
• FizzBuzz をプログラムで書く•上限 n を引数として受け取り, FizzBuzz の文字列ベクトルを返す関数を作る• 普通の FizzBuzz 問題はコンソールに出力できれば OK
> fizzbuzz <- function(n) { # Write your code here }
> fizzbuzz(20) [1] "1" "2" "Fizz" [4] "4" "Buzz" "Fizz" [7] "7" "8" "Fizz"[10] "Buzz" "11" "Fizz" [13] "13" "14" "FizzBuzz"[16] "16" "17" "Fizz" [19] "19" "Buzz"
解答例
fb1 <- function(n) { fb <- character(n) for (i in 1:n) { if (i %% 3 == 0 && i %% 5 == 0) fb[i] <- "FizzBuzz" else if (i %% 3 == 0) fb[i] <- "Fizz" else if (i %% 5 == 0) fb[i] <- "Buzz" else fb[i] <- i } fb}
R っぽくない
fb2 <- function(n) { sapply(1:n, function(i) { if (i %% 3 == 0 && i %% 5 == 0) "FizzBuzz" else if (i %% 3 == 0) "Fizz" else if (i %% 5 == 0) "Buzz" else i })}
なんとなくR っぽくなった?
でもやっぱり…
R といえばベクトル演算ですよね!
つまり…
fb3 <- function(n) { isFizz <- rep(c(F,F,T), length=n) isBuzz <- rep(c(F,F,F,F,T), length=n) isNumber <- !isFizz & !isBuzz
fizz <- ifelse(isFizz, "Fizz", "") buzz <- ifelse(isBuzz, "Buzz", "") number <- ifelse(isNumber, 1:n, "")
paste(fizz, buzz, number, sep="")}
これぞR 的 FizzBuzz
ところで
そんな変な書き方に意味があるんですか?
よろしいならばベンチマークだ
> N <- 100> benchmark(fb1(N), fb2(N), fb3(N), order="relative", replications=10000)
test elapsed relative3 fb3(N) 4.172 1.0000002 fb2(N) 6.669 1.5985141 fb1(N) 7.779 1.864573
> N <- 10000> benchmark(fb1(N), fb2(N), fb3(N), order="relative", replications=100)
test elapsed relative3 fb3(N) 2.907 1.0000002 fb2(N) 7.823 2.6910901 fb1(N) 8.200 2.820777
> N <- 1000000> benchmark(fb1(N), fb2(N), fb3(N), order="relative", replications=5)
test elapsed relative3 fb3(N) 28.287 1.0000001 fb1(N) 46.198 1.6331882 fb2(N) 52.223 1.846184
完全勝利
まとめ
• R 的な書き方 (ベクトル化) をすることで高速化が期待できる
おまけ
バイナリと比較
• compiler パッケージ• R のコードをコンパイル• inline パッケージ• C や Fortran のコードをコンパイル
library(compiler) # Installed by defaultlibrary(inline) # Needs manual installation
fbcpp <- cxxfunction( signature(ns="integer"), body=src, # Shown in the next slide plugin="Rcpp")
fb1.c <- cmpfun(fb1)fb2.c <- cmpfun(fb2)fb3.c <- cmpfun(fb3)fbcpp.c <- cmpfun(fbcpp)
int n = Rcpp::as<int>(ns);Rcpp::CharacterVector fb(n);for (int index = 0; index < n; index++) { int i = index + 1; if (i % 3 == 0 && i % 5 == 0) fb[index] = "FizzBuzz"; else if (i % 3 == 0) fb[index] = "Fizz"; else if (i % 5 == 0) fb[index] = "Buzz"; else { char s[11]; // Integer is 10 or less digit sprintf(s, "%d", i); fb[index] = s; }}return(fb);
ベンチマーク
Simple Functional Vectorized Native
FizzBuzz up to 100 (N=10,000)
Relative Time to Complete FizzBuzz
05
1015
ControlCompiled
Simple Functional Vectorized Native
FizzBuzz up to 10,000 (N=100)
Relative Time to Complete FizzBuzz
05
1015
ControlCompiled
どう書く?•一人・対話環境➡ベクトル化
•複数人 (開発者の能力にばらつき)➡単純記述で compiler
•実行速度が重要➡他言語による拡張
参考文献
• The new R compiler package in R 2.13.0: Some first experimentsThinking inside the box