裏 RjpWiki

文字通り,RjpWiki の裏を行きます
R プログラム コンピュータ・サイエンス 統計学

PPAP で遊々プログラミング

2016年10月30日 | ブログラミング

一つ目

I.HAVE.A = I.HAVE.AN = function(x) x
cat(rev(c(c(I.HAVE.A("PEN"), I.HAVE.AN("APPLE")),
rev(c(I.HAVE.A("PEN"), I.HAVE.A("PINEAPPLE"))))))

二つ目...わざわざ複雑そうに

PPAP = function(s, t, u, v) {
    cat1 = function(s, ...) cat(toupper(substr(s, 1, 1)), ...)
    cat2 = function(s) cat(sprintf("I have a%s %s.", ifelse(grepl(tolower(substr(s, 1, 1)), "aiueo"), "n", ""), s), "\n")
    cat3 = function(s) {cat2(s[1]); cat2(s[2]); cat(s[2:1], ".\n")}
    sapply(c(s, t, u, v, "\n"), cat1)
    sapply(list(c(s, t), c(u,v)), cat3)
    cat(sprintf("%2$s %1$s, %4$s %3$s.\n", s, t, u, v))
    cat(sprintf("%3$s %4$s, %2$s %1$s!\n", s, t, u, v))
}
PPAP("pen", "apple", "pen", "pineapple")
PPAP("ball", "baseball", "pen", "pencl")

コメント

限られた数字で作れる数の、まんなかの値

2016年10月21日 | ブログラミング

締め切りが 10/21 10:00 AM というので,その 1 分後に投稿されるように予約

限られた数字で作れる数の、まんなかの値」を求める

【概要】
たとえば。
0, 4, 5以外の数を使わずに作ることができる3桁以下の非負の整数は、

    0, 4, 5, 40, 44, 45, 50, 54, 55, 400, 404, 405, 440, 444, 445, 450, 454, 455, 500, 504, 505, 540, 544, 545, 550, 554, 555

の27個です。中央は14番目の数なので、求める値は444になります。
このような感じで、桁数の最大値と使える数字を与えますので、作ることができる数の中央の値を求めてください。

【入出力】
入力は
3 045
こんな感じです。
空白の前が桁数の上限。空白の後が使える数字です。使える数字は重複なく昇順に並んでいます。

出力は、
444
のように、中央の値を出力してください。
作れる数が偶数個の場合には、中央に近い数を2つ、小さい順にコンマ区切りで並べてください。

【例】
入力     出力
3 045     444
1 012789     2,7
10 059     5555555555

【補足】
桁数の上限の最小値は 1 。最大値は 15 です
不正な入力に対処する必要はありません

================================

f = function(s) {
    g = function(m) {
        d = 0
        if (m > 0) {
            m = m-1 # 与えられる中央値は 1 から始まるので,j 進数で 0 から始めるために 1 を引く
            for (i in 1:99) {
                if (m == 0) break
                d[i] = x[m %% j + 1] # j 進数で各桁を決める。ただし,表記に使うのは x にある,実際に使える数字
                m = m %/% j
            }
        }
        paste(rev(d), collapse="")
    }
    options(scipen=100)
    s = unlist(strsplit(s, " "))
    k = as.numeric(s[1])
    x = as.numeric(unlist(strsplit(s[2], "")))
    if (length(x) == 1) { # 1 桁の場合は特別に扱う(簡単なのだけど)
        f = unique(as.numeric(sapply(1:k, function(y) paste(rep(x, y), collapse=""))))
        n = length(f)
        m = n %/% 2
        if (n %% 2 == 1) {
            cat(f[m+1])
        } else {
            cat(f[m+0:1], sep=",")
        }
    } else {
        j = length(x) # 使える数字の個数を j
        n = j^k # 作られる数の個数は 0 〜 (j^k)-1 の n 個。それぞれに 1 を足して 1 〜 n=j^k とする
        if (n %% 2 == 0) { # 真ん中の数は,要するに中央値。求め方は初歩の統計学の教科書に書いてある
            m = n/2
            cat(g(m), ",", g(m+1), sep="") # g() は十進数表記の中央値を j 進数で表記し直すだけ
        } else {
            m = (n+1) / 2
            cat(g(m))
        }
    }
}

> f("1 2") # 2
2
> f("2 2") # 2,22
2,22
> f("15 3") # 33333333
33333333
> f("1 0") # 0
0
> f("2 0") # 0
0
> f("15 04") # 44444444444444,400000000000000
44444444444444,400000000000000
> f("1 0246") # 2,4
2,4
> f("2 0246") # 26, 40
26,40
> f("15 0246") # 266666666666666,400000000000000
266666666666666,400000000000000
> f("15 12345789")
499999999999999,511111111111111
> f("15 123456789")
555555555555555
> f("15 0123456789") # 499999999999999,500000000000000
499999999999999,500000000000000

以下の 2 ケースの解が異なるのだが
■テストケース10 ・・・ 【入力値:15 12345789】【期待値:444444444444444,444444444444445】
■テストケース11 ・・・ 【入力値:15 123456789】【期待値:494949494949495】

コメント

数列の判定

2016年10月14日 | ブログラミング

締め切りが 2016/10/24 10:00 AM なので,その 1 分後に投稿されるように予約。
当初の締め切りが延期されても,当方は一切関知しない。

【問題】
スペース区切りで 5個の10 進数が並んでいます。
与えられた数列が以下のいずれの数列(の、途中の連続した5項)なのかを判別するプログラムを書いてください。
記号     名称
G     等比数列
A     等差数列
F     フィボナッチ数
x     G, A, F のいずれにも該当しない

出力は、G, A, F, x のいずれかを出力してください。


【例】
入力     出力
1 2 4 8 16     G
1 2 3 4 5     A
3 5 8 13 21     F
1 2 123 1234 9999     x



【補足】
入力に含まれる値は、1以上、100億以下の整数です。
入力は、全て狭義単調増加列になっています。
不正な入力に対処する必要はありません。
G, A, F は大文字ですが、 x は小文字です。
1, 4, 5, 9, 14, 23, ... という数列はフィボナッチではありません。

f = function(s) {
    mul = function(x, y) { # 等比数列の各項が大きな値のとき,等比になっているかどうかは,ある項の二乗が前後の二項の積に等しいかどうかを見ないといけない
        x = rev(as.integer(unlist(strsplit(as.character(x), ""))))
        y = rev(as.integer(unlist(strsplit(as.character(y), ""))))
        l.x = length(x)
        l.y = length(y)
        z = integer(l.x+l.y)
        for (i in 1:l.x) {
            for (j in 1:l.y) {
                z[i+j-1] = z[i+j-1]+x[i]*y[j]
            }
        }
        for (i in 1:(l.x+l.y-1)) {
            z[i+1] = z[i+1] + z[i] %/% 10
            z[i] = z[i] %% 10
        }
        paste(rev(z), collapse="")
    }
    sqr = function(x) { # 二乗する関数
        mul(x, x)
    }
    d = as.numeric(unlist(strsplit(s, " ")))
    dif = diff(d)
    if (all(dif[1] == dif)) {
        cat("A")
    } else if (mul(d[1], d[3]) == sqr(d[2]) && # a[i-1] * a[i+1] == a[i]^2
               mul(d[2], d[4]) == sqr(d[3]) &&
               mul(d[3], d[5]) == sqr(d[4])) {
        cat("G")
    } else {
        n = 1:49
        fib = round((((1+sqrt(5))/2)^n - ((1-sqrt(5))/2)^n) / sqrt(5))
        i = which(fib == d[1])
        if (length(i) != 0 && all(d == fib[i[1]+0:4])) {
            cat("F")
        } else {
            cat("x")
        }
    }
}
f("160816114 194672138 235655746 285267482 345323794") # G
f("9845600625 9876856500 9908211600 9939666240 9971220736") # G
f("9715064832 9751864320 9788803200 9825882000 9863101250") # G
f("1234 6912 12590 18268 23946") # A
f("9999999990 9999999991 9999999992 9999999993 9999999994") # A
f("1 2000000000 3999999999 5999999998 7999999997") # A
f("13 21 34 55 89") # F
f("121393 196418 317811 514229 832040") # F
f("1134903170 1836311903 2971215073 4807526976 7778742049") # F
f("9983848527 9987006973 9990166419 9993326864 9996488308") # x
f("969323029 1568397607 2537720636 4106118243 6643838879") # x
f("1032569015 1670731762 2703300777 4374032539 7077333316") # x

コメント