オフラインリアルタイムどう書く 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 がわかりにくいね。