LoginSignup
0
0

More than 5 years have passed since last update.

オフラインリアルタイムどう書く E15 の実装例( Go )

Posted at

オフラインリアルタイムどう書く E15 の実装例( Go )

問題 : http://nabetani.sakura.ne.jp/hena/orde15nohil/
実装リンク集 : https://qiita.com/Nabetani/items/705fa83cfbf20377b92f

順当に https://qiita.com/Nabetani/items/f516767d63dd7791672a を移植した。

実装
package e15

import (
    "fmt"
    "sort"
    "strconv"
)

type pos struct {
    x, y int
}

func numToPos(num int) pos {
    r := pos{0, 0}
    for w := 1; 0 < num; {
        switch num % 3 {
        case 0:
            // nothing to do here.
        case 1:
            r.x += w
        case 2:
            r.y += w
        }
        num /= 3
        w *= 2
    }
    return r
}

func posToNum(p pos) int {
    if p.x < 0 || p.y < 0 {
        return -1
    }
    if p.x == 0 && p.y == 0 {
        return 0
    }
    if p.x == 1 && p.y == 0 {
        return 1
    }
    if p.x == 0 && p.y == 1 {
        return 2
    }
    if p.x == 1 && p.y == 1 {
        return -1
    }
    a := posToNum(pos{p.x / 2, p.y / 2})
    b := posToNum(pos{p.x & 1, p.y & 1})
    if a < 0 || b < 0 {
        return -1
    }
    return a*3 + b
}

func impl(num int) []int {
    p := numToPos(num)
    neis := []pos{
        pos{p.x, p.y + 1},
        pos{p.x, p.y - 1},
        pos{p.x + 1, p.y},
        pos{p.x - 1, p.y},
    }
    nums := []int{}
    for _, e := range neis {
        n := posToNum(e)
        if 0 <= n {
            nums = append(nums, n)
        }
    }
    return nums
}

func solve(src string) string {
    num64, _ := strconv.ParseInt(src, 10, 32)
    num := int(num64)
    ans := impl(num)
    sort.Sort(sort.IntSlice(ans))
    r := ""
    for _, e := range ans {
        if r != "" {
            r += ","
        }
        r += fmt.Sprintf("%v", e)
    }
    return r
}
テスト
package e15

import (
    "testing"
)

func Test(t *testing.T) {
    var tests = []struct {
        name  string
        input string
        want  string
    }{
        {"0", "21", "19,22,23"},
        {"1", "0", "1,2"},
        {"2", "1", "0,3"},
        // 中略
        {"51", "1000000", "999999,1000002"},
    }
    for _, test := range tests {
        got := solve(test.input)
        if got != test.want {
            t.Errorf("%v: solve(%q)=%q, want %q\n", test.name, test.input, got, test.want)
        }
    }
}

ruby では「return [0,1,1i].index(pos) if 1==[x.size, y.size].max」と一行で書ける式に何行も費やしたのがちょっと悔しい。

今回は pos という struct を導入してみたけど、出来合いのそういう struct はあるのだろうか。調べずに書いたけど。

あと。やっぱり Sort がわかりにくいね。

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