LoginSignup
0
0

More than 5 years have passed since last update.

オフラインリアルタイムどう書く F05 の ruby と kotlin による実装例

Posted at

問題:http://nabetani.sakura.ne.jp/hena/ordf05rotblo/
実装リンク集:http://qiita.com/Nabetani/items/a6ed674166a151fd0a0a

まずは最初に書いた ruby から:

ruby
N=5

def rot( cells, cx, cy )
  r = Array.new(N){ [0]*N }
  N.times do |y|
    N.times do |x|
      next unless cells[y][x]==1
      nx = -(y-cy)+cx
      ny = (x-cx)+cy
      return nil unless (0...N)===nx && (0...N)===ny
      r[ny][nx]=1
    end
  end
  r
end

def solve( src )
  center, map = src.split(":")
  cells = map.split("/").map{ |x| x.chars.map(&:to_i) }
  rotated = case center
  when "a"; rot( cells, 1, 2 )
  when "b"; rot( cells, 1.5r, 1.5r )
  end
  rotated ? rotated.map(&:join).join("/") : "-"
end

DATA.map{ |line|
  num, src, expected = line.split( /\s+/ )
  actual = solve( src )
  okay = actual == expected
  puts "%s %s %s->%s( %s )" % [ num, okay ? "ok" : "**NG**", src, actual, expected ]
  okay
}.all?.tap{ |x| puts( x ? "okay" : "something wrong" ) }

__END__
0 a:00000/00110/00100/00100/00000 00000/00000/00000/11100/00100
1 b:00000/00000/00000/00011/00011 -
2 a:00000/00000/00000/00011/00011 -
55  a:01011/10001/00000/00000/00000 -

いつも通り、テストデータの大半は省略。

順当にブロックを回しているつもり。
セルの座標から中心を引いて、回転行列をかけてから中心を足す。
ブロック内ブロックから return で抜けているところが ruby ならではの技。

続いて、kotlin。
上記の ruby を移植しただけ。
kotlin 歴が極めて浅いのできっとなにかおかしいと思う。

kotlin
val N = 5

class MyException() : Throwable() {}

fun rotate(cells: List<List<Char>>, cx: Double, cy: Double): List<List<Char>> {
    val r = mutableListOf<MutableList<Char>>()
    (0 until N).forEach {
        val s = (0 until N).map { '0' }.toMutableList()
        r.add(s)
    }
    try {
        (0 until N).forEach { y ->
            (0 until N).forEach { x ->
                if (cells[y][x] == '1') {
                    val nx = Math.round(-(y - cy) + cx).toInt()
                    val ny = Math.round((x - cx) + cy).toInt()
                    if (nx in (0 until N) && ny in (0 until N)) {
                        r[ny][nx]='1'
                    } else {
                        throw MyException() //
                    }
                }
            }
        }
        return r;
    } catch (e: MyException) {
        return mutableListOf<MutableList<Char>>()
    }
}

fun solve(src: String): String {
    val split: List<String> = src.split(":")
    val center = split[0]
    val cells = split[1].split("/").map { line -> (0 until 5).map { line[it] } } // TODO:もっときれいに書けるはず
    val rotated = if (center == "a") {
        rotate(cells, 1.0, 2.0)
    } else {
        rotate(cells, 1.5, 1.5)
    }
    if (rotated.isEmpty()) {
        return "-"
    }
    return rotated.map { it.joinToString("") }.joinToString("/")
}

fun test(src: String, expected: String): Boolean {
    val actual = solve(src)
    val okay = (actual == expected)
    print(if (okay) {
        "ok"
    } else {
        "***NG***"
    })
    println(src)
    return okay
}

fun main(args: Array<String>) {
    var okay = true
/*0*/ okay = okay and test("a:00000/00110/00100/00100/00000", "00000/00000/00000/11100/00100");
/*1*/ okay = okay and test("b:00000/00000/00000/00011/00011", "-");
/*55*/ okay = okay and test("a:01011/10001/00000/00000/00000", "-");
    println(if (okay) {
        "okay"
    } else {
        "something wrong"
    })
}

ruby では ブロック内ブロックから return で抜けているところは、仕方ないので throw した。もっといい方法がありそうなものだけどわからない。

「// TODO:もっときれいに書けるはず」と書いたところが一番の不満。
MutableList の MutableList を作るコードも不満。

でもまあ、書けたので良しとしよう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0