R で解く FizzBuzz 問題

Post on 27-May-2015

1.835 views 8 download

Tags:

description

FizzBuzz question in R language.

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

•実行速度が重要➡他言語による拡張