裏 RjpWiki

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

くたばれ Python

2018年02月02日 | ブログラミング

Python を使う輩の気が知れない

R を使うべし

根拠はたくさんある

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

展開図上の反対側

2018年02月02日 | ブログラミング

展開図上の反対側

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

マス目を6つ指定します。
6つのマス目を立方体の展開図として組み上げた場合に、最初の面の反対側がどの面になるのかを計算してください。

【入出力】
入力は
glkmnq
のようになっています。

区切り文字なしで、面を示すアルファベット(図を参照)が6つ並んでいます。

出力するのは、最初の面の反対側の面のアルファベットです。
glkmnq
に対応する出力は、下図の通り、g の反対側は q なので
q
になります。

ただし、
jotfkpやklmngi
のように、
入力が立方体の展開図をなしていない場合は
-
を出力してください。

【例】
入力 glkmnq  出力 q

入力 klmngi  出力 -

入力 jotfkp  出力 -

入力 bcdhmr  出力 d


【補足】
    •    不正な入力に対処する必要はありません。
    •    ひとつながりになっていない場合は、展開図にはなっていないと判断してください。

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

f = function(s) {
    abnormal = function(mat) {
        if (any(colSums(mat != " ") == 5, rowSums(mat != " ") == 5)) { # 縦(横)に5個並んでいる
            return(TRUE)
        }
        for (i in 1:4) { # 2行2列がある
            for (j in 1:4) {
                if (mat[i,j] != " " && mat[i+1,j] != " " && mat[i,j+1] != " " && mat[i+1,j+1] != " ") {
                    return(TRUE)
                }
            }
        }
        return(FALSE)
    }
    check = function(xy, m, n) { # (i, j) に隣接する面を辿って裏側になるものがあるかチェック
        a = array(xy, dim=c(2, m, n))
        for (k in 1:n) {
            ok = TRUE
            for (l in 1:m) {
                x = i+a[1, l, k]
                y = j+a[2, l, k]
                if (x < 1 || x > 5 || y < 1 || y > 5) {
                    ok = FALSE
                    break
                } else if (mat[x, y] == " ") {
                    ok = FALSE
                    break
                }
            }
            if (ok) {
                return(list(ok = TRUE, result = mat[x, y]))
            }
        }
        return(list(ok=FALSE, result=""))
    }
    letters = letters[1:25]
    t = unlist(strsplit(s, ""))
    mat = matrix(ifelse(letters %in% t, letters, " "), 5, byrow=TRUE)
    if (abnormal(mat)) { # 不正な展開図
        cat("-")
    } else {
        pos = grep(t[1], letters)-1
        i = pos %/% 5+1
        j = pos %% 5+1
        # B*E の場合(縦横の4方向) E が裏側
        # B の後の (i,j) の増分
        xy2 = c(0,-1,0,-2, -1,0,-2,0, 0,1,0,2, 1,0,2,0)
        a = check(xy2, 2, 4)
        if (a$ok) {
            cat(a$result)
            invisible()
        }
        # B
        # **
        #  E の場合 (8方向)
        xy3 = c(0,-1,1,-1,1,-2,
                0,-1,-1,-1,-1,-2,
                -1,0,-1,-1,-2,-1,
                -1,0,-1,1,-2,1,
                0,1,-1,1,-1,2,
                0,1,1,1,1,2,
                1,0,1,1,2,1,
                1,0,1,-1,2,-1)
        a = check(xy3, 3, 8)
        if (a$ok) {
            cat(a$result)
            invisible()
        }
        # B
        # ***
        #   E の場合 (8方向)
        xy4 = c(0,-1,1,-1,2,-1,2,-2,
                0,-1,-1,-1,-2,-1,-2,-2,
                -1,0,-1,-1,-1,-2,-2,-2,
                -1,0,-1,1,-1,2,-2,2,
                0,1,-1,1,-2,1,-2,2,
                0,1,1,1,2,1,2,2,
                1,0,1,1,1,2,2,2,
                1,0,1,-1,1,-2,2,-2)
        a = check(xy4, 4, 8)
        if (a$ok) {
            cat(a$result)
            invisible()
        }
        # B
        # ****
        #    E の場合 (8方向)
        xy5 = c(0,-1,1,-1,2,-1,3,-1,3,-2,
                0,-1,-1,-1,-2,-1,-3,-1,-3,-2,
                -1,0,-1,-1,-1,-2,-1,-3,-2,-3,
                -1,0,-1,1,-1,2,-1,3,-2,3,
                0,1,-1,1,-2,1,-3,1,-3,2,
                0,1,1,1,2,1,3,1,3,2,
                1,0,1,1,1,2,1,3,2,3,
                1,0,1,-1,1,-2,1,-3,2,-3)
        a = check(xy5, 5, 8)
        if (a$ok) {
            cat(a$result)
            invisible()
        }
    }
}
# f(readLines(file("stdin", "r")))

f("ngmbah") # g
f("rdmgch") # h
f("imdsen") # s
f("nuqprs") # u
f("gmknlr") # r
f("jbhaci") # h
f("ijcmbh") # b
f("gmlnrf") # r
f("nagihb") # b
f("pwrtsq") # -
f("fgbach") # -
f("mihgsn") # -

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

画像から連結成分の数を求めよう

2018年02月02日 | ブログラミング

画像から連結成分の数を求めよう

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

あなたは食品メーカーに勤めており、画像認識で商品を検査することで業務を省力化するよう求められました。

画像認識はDeep Learningが得意とする分野ですが、まず「隗より始めよ」ということで、画像から物体の数を求めるプログラムの開発に着手することにしました。

本設問で求められるプログラムの前提条件は、以下の通りとなります。

・ 標準入力から、ドット(.)とゼロ(0)の2文字で構成された文字列が同文字数複数行送られる。
・ 入力は1文字を1ピクセル、1行分の文字列を横一列とした2値画像とみなす。
・ この時横軸、縦軸とも長さは4以上20以下とする。
・ ゼロ(0)が上下左右斜めの8方向に連結した領域(連結成分)の数を求め、その数を標準出力に返すこと。
・ なお領域外のピクセルは、ドット(.)とみなすこと。

【問題】
標準入力から、ドット(.)とゼロ(0)の2文字で構成された文字列が同文字数複数行送られます。
この入力を2値画像とみなし、ゼロが上下左右斜めの8方向に連結した領域(連結成分)の数を求め、その数を標準出力に返してください。

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

20×20 だと,地道にやっても R でも楽勝

f = function(s) {
    count = 0
    n = length(s)
    a = matrix(0, n+2, n+2)
    r = 1:n+1
    a[r, r] = sapply(s, function(t) unlist(strsplit(t, "")))
    repeat {
        # 新しい「島」の一端("0" のセル)を探す
        found = FALSE
        for (i in r) {
            for (j in r) {
                if (a[i, j] == "0") {
                    found = TRUE
                    count = count+1
                    a[i, j] = "*" # あったら "*" にする
                    break
                }
            }
            if (found) {
                break
            }
        }
        if (!found) {
            break # "0" が 1 つもなかった(全て処理済み)ならば,終わり
        }
        # 1 つでもあれば,「島」を拡張する
        si = c(-1, 0, 1, -1, 1, -1, 0, 1)
        sj = c(-1,-1,-1,  0, 0,  1, 1, 1)
        repeat {
            replace = FALSE
            for (i in r) {
                for (j in r) {
                    if (a[i, j] == "*") { # "*" のセルの八方に "0" があれば
                        for (k in 1:8) {
                            if (a[i+si[k], j+sj[k]] == "0") {
                                a[i+si[k], j+sj[k]] = "*" # "*" に置き換える
                                replace = TRUE # 置き換えがあったことを記録
                            }
                        }
                    }
                }
            }
            if (!replace) { # 置き換えがなかったら「島」の拡張は終了
                for (i in r) {
                    for (j in r) {
                        if (a[i, j] == "*") {
                            a[i, j] = "." # 処理済みの「島」は「島」でないようにする
                        }
                    }
                }
                break
            }
        }
    }
    cat(count)
}

#f(readLines(file("stdin", "r")))

f(readLines("dat1")) # 2
f(readLines("dat2")) # 5
f(readLines("dat3")) # 7

dat1

00....
......
..000.
.00.0.
..000.
......

dat2

0....00.
0000000.
........
...0000.
..0....0
...0000.
........
.0.0..0.

dat3

....................
..000000............
.0..0..0....000000..
.0.....0....0....0..
.0000000....0.0..0..
............0.0.....
....00000...0.00000.
...00.......0.......
...0................
...0................
...0.....000........
....00..0...00......
.......00.....0.....
....................
...........000000...
.........00......00.
........0....000..0.
........0........00.
.........0000000000.
....................

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

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

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