裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

数学の問題を R で解く(その2)

2017年03月29日 | ブログラミング

10 桁の数字 n(すなわち 1000000000 ≦ n ≦ 9999999999) において,n^n の末尾の 3 桁が 777 になるのは,何個あるか

1 桁の数字でそのようなものは,0 個
2 桁の数字でそのようなものは,0 個
3 桁の数字でそのようなものは,1 個
4 桁の数字でそのようなものは,9 個
  :

f = function(x) {
    y = 1
    for (i in 1:x) {
        y = (y*x) %% 1000
    }
    y == 777
}
sum(sapply(0:9, f)) # 0
sum(sapply(10:99, f)) # 0
sum(sapply(100:999, f)) # 1
sum(sapply(1000:9999, f)) # 9
# sum(sapply(1000000000:9999999999, f)) # oh! no!

 

10 桁の数字でそのようなものは,90000000 個

 

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

数学の問題を R で解く

2017年03月29日 | ブログラミング

スコットランドの高校生(16〜18歳)対象の数学問題

1匹のワニが20メートル上流の川の対岸にいる獲物に忍び寄ろうとしている。

ワニの移動速度は地上と水中では異なる。
図に示されているxメートル上流にある対岸のP地点へ向けてワニが泳いだ場合,獲物に到達するまでの移動時間が最小となる。
この所要時間は,以下の等式によって求められる。(引用者注:時間の単位は特に定める必要がないので省略し,無名数とする)

T(x) = 5*sqrt(36+x^2)+4*(20-x)

(a) (i) ワニが地上を移動しなかった場合の所要時間を求めよ。
    (ii) ワニの泳いだ距離が最小だった場合の所要時間を求めよ。
(b) これらの両極端の2つの選択肢の中間に,所要時間を最小化するxの値が1つある。そのxの値を求めよ。

この問題を R を用いて解く。
まず,T(x) の図を描いておこう(0 ≦ x ≦ 20)
> T = function(x) 5*sqrt(36+x^2)+4*(20-x)
> x = seq(0, 20, by=0.01)
> y = T(x)
> plot(x, y, type="l")


(a) (i) 「ワニが地上を移動しなかった場合」というのは,川を斜めに渡ったということ。すなわち,x = 20 のときの T(x) が答え。
> T(0)
[1] 110
答え 110

(a) (ii)  「ワニの泳いだ距離が最小だった場合」というのは,川を垂直に渡ったということ。すなわち,x = 0 のときの T(x) が答え。
> T(20)
[1] 104.4031
答え 104.4031

(b) T(x) が最小になるときの x を求めるということは,T(x) の微分係数が 0 になるときの x を求めるということ。
> g = deriv(~5*sqrt(36+x^2)+4*(20-x), "x", function.arg="x")
> g # 微分係数の関数
function (x)
{
    .expr2 <- 36 + x^2
    .value <- 5 * sqrt(.expr2) + 4 * (20 - x)
    .grad <- array(0, c(length(.value), 1L), list(NULL, c("x")))
    .grad[, "x"] <- 5 * (0.5 * (2 * x * .expr2^-0.5)) - 4
    attr(.value, "gradient") <- .grad
    .value
}
微分係数のグラフを描いておこう。
> plot(x, attr(g(x), "gradient"))
> plot(x, attr(g(x), "gradient"), type="l")
> abline(h=0, v=8, col="red", lty=2) # 結果論ではあるが x = 8 のとき,微分係数が 0 になることを図示しておく


関数の最小値を求めるのは optimize 関数が使える

> optimize(g, lower=0, upper=20, tol = .Machine$double.eps) # deriv 関数の戻り値 g を与える場合
$minimum
[1] 8

$objective
[1] 98
attr(,"gradient")
                 x
[1,] -5.039269e-08

または

> optimize(T, lower=0, upper=20, tol=.Machine$double.eps) # もとの関数を与える場合
$minimum
[1] 8

$objective
[1] 98

いずれにせよ $minimum = 8 が解である(最短時間は $objective = 98)。

なお,deriv 関数が返す導関数 5 * (0.5 * (2 * x * (36 + x^2)^-0.5)) - 4 が 0 になる値は,uniroot でも求められる。

> h = function(x) 5 * (0.5 * (2 * x * (36 + x^2)^-0.5)) - 4
> uniroot(h, lower=0, upper=20, tol=.Machine$double.eps)
$root
[1] 8

$f.root
[1] 0

$iter
[1] 8

$init.it
[1] NA

$estim.prec
[1] 2.993504e-05

$root = 8 が解である(そのとき,$f.root = 0 となる)

> h(8)
[1] 0

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村