開発環境
- macOS Catalina - Apple (OS)
- Emacs (Text Editor)
- Windows 10 Pro (OS)
- Visual Studio Code (Text Editor)
- Go (プログラミング言語)
入門Goプログラミング (Nathan Youngman(著)、Roger Peppé(著)、吉川 邦夫(監修, 翻訳)、翔泳社)のUNIT 7(並行プログラミング)、LESSON 32(チャレンジ:火星で生きるもの)の32.1(ローバーが移動するグリッド)の解答を求めてみる。
コード
package main
import (
"fmt"
"image"
"math/rand"
"sync"
"time"
)
type occupier struct {
*marsGrid
pos image.Point
}
func (o *occupier) moveTo(pos image.Point) bool {
o.marsGrid.mu.Lock()
defer o.marsGrid.mu.Unlock()
cell := o.cell(pos)
if cell == nil || cell.occupier != nil {
return false
}
o.marsGrid.cell(o.pos).occupier = nil
o.marsGrid.cell(pos).occupier = o
o.pos = pos
return true
}
type cell struct {
*occupier
}
type marsGrid struct {
rect image.Rectangle
cells [][]cell
mu sync.Mutex
}
func newMarsGrid(p image.Point) *marsGrid {
cells := make([][]cell, p.Y)
for y := range cells {
cells[y] = make([]cell, p.X)
}
g := marsGrid{
rect: image.Rectangle{Max: p},
cells: cells,
}
return &g
}
func (g *marsGrid) cell(p image.Point) *cell {
if !p.In(g.rect) {
return nil
}
return &g.cells[p.Y][p.X]
}
func (g *marsGrid) occupy(p image.Point) *occupier {
g.mu.Lock()
defer g.mu.Unlock()
cell := g.cell(p)
if cell == nil || cell.occupier != nil {
return nil
}
cell.occupier = &occupier{
marsGrid: g,
pos: p,
}
return cell.occupier
}
type command int
const (
right = command(0)
left = command(1)
start = command(2)
stop = command(3)
)
type roverDriver struct {
commandc chan command
name string
*occupier
}
func newRoverDriver(name string, o *occupier) *roverDriver {
r := &roverDriver{
commandc: make(chan command),
name: name,
occupier: o,
}
go r.drive()
return r
}
func (r *roverDriver) right() {
r.commandc <- right
}
func (r *roverDriver) left() {
r.commandc <- left
}
func (r *roverDriver) start() {
r.commandc <- start
}
func (r *roverDriver) stop() {
r.commandc <- stop
}
func (r *roverDriver) drive() {
direction := image.Point{X: 1, Y: 0}
updateInterval := 250 * time.Millisecond
nextMove := time.After(updateInterval)
speed := 1
for {
select {
case c := <-r.commandc:
switch c {
case right:
direction = image.Point{
X: -direction.Y,
Y: direction.X,
}
case left:
direction = image.Point{
X: direction.Y,
Y: -direction.X,
}
case start:
speed = 1
case stop:
speed = 0
}
case <-nextMove:
if speed == 0 {
fmt.Printf("%vは位置(%v,%v)で停止中\n", r.name, r.pos.X, r.pos.Y)
} else {
pos := r.occupier.pos.Add(direction.Mul(speed))
if r.occupier.moveTo(pos) {
fmt.Printf("%vは位置(%v,%v)に移動完了\n", r.name, pos.X, pos.Y)
} else {
n := 1 + rand.Intn(3)
for i := 0; i < n; i++ {
direction = image.Point{
X: -direction.Y,
Y: direction.X,
}
}
fmt.Printf("%vは位置(%v,%v)に移動できず方向を%vに変更\n",
r.name, pos.X, pos.Y, direction)
}
}
nextMove = time.After(updateInterval)
}
}
}
func main() {
rand.Seed(time.Now().UnixNano())
width := 20
height := 10
g := newMarsGrid(image.Point{X: width, Y: height})
o1 := occupier{
marsGrid: g,
pos: image.Point{
X: rand.Intn(width / 2),
Y: rand.Intn(height / 2),
},
}
r1 := newRoverDriver("rover1", &o1)
o2 := occupier{
marsGrid: g,
pos: image.Point{
X: width/2 + rand.Intn(width/2),
Y: height/2 + rand.Intn(height/2),
},
}
r2 := newRoverDriver("rover2", &o2)
methods := []func(){
r1.right,
r1.left,
r1.start,
r1.stop,
r2.right,
r2.left,
r2.start,
r2.stop,
}
for _, method := range methods {
time.Sleep(time.Second)
method()
}
r1.start()
r2.start()
for i := 0; i < 10; i++ {
time.Sleep(time.Second)
methods[rand.Intn(len(methods))]()
}
}
入出力結果(Zsh、PowerShell、Terminal)
% go build marsgrid.go
% ./marsgrid
rover2は位置(19,5)に移動完了
rover1は位置(5,0)に移動完了
rover1は位置(6,0)に移動完了
rover2は位置(20,5)に移動できず方向を(0,1)に変更
rover2は位置(19,6)に移動完了
rover1は位置(7,0)に移動完了
rover2は位置(19,7)に移動完了
rover1は位置(7,1)に移動完了
rover1は位置(7,2)に移動完了
rover2は位置(19,8)に移動完了
rover1は位置(7,3)に移動完了
rover2は位置(19,9)に移動完了
rover1は位置(7,4)に移動完了
rover2は位置(19,10)に移動できず方向を(1,0)に変更
rover1は位置(8,4)に移動完了
rover2は位置(20,9)に移動できず方向を(0,-1)に変更
rover2は位置(19,8)に移動完了
rover1は位置(9,4)に移動完了
rover2は位置(19,7)に移動完了
rover1は位置(10,4)に移動完了
rover2は位置(19,6)に移動完了
rover1は位置(11,4)に移動完了
rover1は位置(12,4)に移動完了
rover2は位置(19,5)に移動完了
rover2は位置(19,4)に移動完了
rover1は位置(13,4)に移動完了
rover2は位置(19,3)に移動完了
rover1は位置(14,4)に移動完了
rover1は位置(15,4)に移動完了
rover2は位置(19,2)に移動完了
rover1は位置(15,4)で停止中
rover2は位置(19,1)に移動完了
rover2は位置(19,0)に移動完了
rover1は位置(15,4)で停止中
rover1は位置(15,4)で停止中
rover2は位置(19,-1)に移動できず方向を(1,0)に変更
rover1は位置(15,4)で停止中
rover2は位置(20,0)に移動できず方向を(0,-1)に変更
rover1は位置(15,4)で停止中
rover2は位置(20,0)に移動できず方向を(0,-1)に変更
rover1は位置(15,4)で停止中
rover2は位置(19,-1)に移動できず方向を(-1,0)に変更
rover2は位置(18,0)に移動完了
rover1は位置(15,4)で停止中
rover1は位置(15,4)で停止中
rover2は位置(17,0)に移動完了
rover1は位置(15,4)で停止中
rover2は位置(17,1)に移動完了
rover1は位置(15,4)で停止中
rover2は位置(17,2)に移動完了
rover1は位置(15,4)で停止中
rover2は位置(17,3)に移動完了
rover1は位置(15,4)で停止中
rover2は位置(17,4)に移動完了
rover1は位置(15,4)で停止中
rover2は位置(17,5)に移動完了
rover1は位置(15,4)で停止中
rover2は位置(17,6)に移動完了
rover2は位置(17,7)に移動完了
rover1は位置(15,4)で停止中
rover2は位置(17,8)に移動完了
rover1は位置(15,4)で停止中
rover1は位置(16,4)に移動完了
rover2は位置(17,9)に移動完了
rover1は位置(17,4)に移動完了
rover2は位置(17,10)に移動できず方向を(-1,0)に変更
rover2は位置(16,9)に移動完了
rover1は位置(18,4)に移動完了
rover2は位置(15,9)に移動完了
rover1は位置(19,4)に移動完了
rover2は位置(14,9)に移動完了
rover1は位置(19,4)で停止中
rover1は位置(19,4)で停止中
rover2は位置(13,9)に移動完了
rover2は位置(12,9)に移動完了
rover1は位置(19,4)で停止中
rover1は位置(19,4)で停止中
rover2は位置(11,9)に移動完了
rover2は位置(10,9)に移動完了
rover1は位置(19,4)で停止中
rover1は位置(19,4)で停止中
rover2は位置(9,9)に移動完了
rover2は位置(8,9)に移動完了
rover1は位置(19,4)で停止中
rover2は位置(7,9)に移動完了
rover1は位置(19,4)で停止中
rover2は位置(6,9)に移動完了
rover1は位置(19,4)で停止中
rover1は位置(19,4)で停止中
rover2は位置(5,9)に移動完了
rover1は位置(19,4)で停止中
rover2は位置(4,9)に移動完了
rover2は位置(3,9)に移動完了
rover1は位置(19,4)で停止中
rover1は位置(19,4)で停止中
rover2は位置(2,9)に移動完了
rover2は位置(1,9)に移動完了
rover1は位置(19,4)で停止中
rover1は位置(19,4)で停止中
rover2は位置(0,9)に移動完了
rover2は位置(-1,9)に移動できず方向を(0,-1)に変更
rover1は位置(19,4)で停止中
rover1は位置(19,4)で停止中
rover2は位置(0,8)に移動完了
rover2は位置(0,7)に移動完了
rover1は位置(19,4)で停止中
rover1は位置(19,4)で停止中
rover2は位置(0,6)に移動完了
rover1は位置(19,4)で停止中
rover2は位置(0,5)に移動完了
rover2は位置(0,4)に移動完了
rover1は位置(19,3)に移動完了
rover1は位置(19,2)に移動完了
rover2は位置(0,3)に移動完了
rover1は位置(19,1)に移動完了
rover2は位置(0,2)に移動完了
rover2は位置(0,1)に移動完了
rover1は位置(19,0)に移動完了
rover2は位置(0,0)に移動完了
rover1は位置(19,-1)に移動できず方向を(-1,0)に変更
rover1は位置(18,0)に移動完了
rover2は位置(0,-1)に移動できず方向を(0,1)に変更
rover1は位置(17,0)に移動完了
rover2は位置(0,1)に移動完了
rover2は位置(0,2)に移動完了
rover1は位置(16,0)に移動完了
rover2は位置(1,2)に移動完了
rover1は位置(15,0)に移動完了
rover1は位置(14,0)に移動完了
rover2は位置(2,2)に移動完了
rover1は位置(13,0)に移動完了
rover2は位置(3,2)に移動完了
rover2は位置(4,2)に移動完了
rover1は位置(12,0)に移動完了
rover2は位置(4,1)に移動完了
rover1は位置(11,0)に移動完了
rover1は位置(10,0)に移動完了
rover2は位置(4,0)に移動完了
rover1は位置(9,0)に移動完了
rover2は位置(4,-1)に移動できず方向を(1,0)に変更
rover2は位置(5,0)に移動完了
rover1は位置(8,0)に移動完了
% ./marsgrid
rover2は位置(16,5)に移動完了
rover1は位置(6,3)に移動完了
rover1は位置(7,3)に移動完了
rover2は位置(17,5)に移動完了
rover2は位置(18,5)に移動完了
rover1は位置(8,3)に移動完了
rover1は位置(8,4)に移動完了
rover2は位置(19,5)に移動完了
rover1は位置(8,5)に移動完了
rover2は位置(20,5)に移動できず方向を(0,1)に変更
rover2は位置(19,6)に移動完了
rover1は位置(8,6)に移動完了
rover2は位置(19,7)に移動完了
rover1は位置(8,7)に移動完了
rover2は位置(19,8)に移動完了
rover1は位置(9,7)に移動完了
rover1は位置(10,7)に移動完了
rover2は位置(19,9)に移動完了
rover1は位置(11,7)に移動完了
rover2は位置(19,10)に移動できず方向を(0,-1)に変更
rover1は位置(12,7)に移動完了
rover2は位置(19,8)に移動完了
rover1は位置(13,7)に移動完了
rover2は位置(19,7)に移動完了
rover2は位置(19,6)に移動完了
rover1は位置(14,7)に移動完了
rover1は位置(15,7)に移動完了
rover2は位置(19,5)に移動完了
rover2は位置(19,4)に移動完了
rover1は位置(16,7)に移動完了
rover2は位置(19,3)に移動完了
rover1は位置(16,7)で停止中
rover1は位置(16,7)で停止中
rover2は位置(19,2)に移動完了
rover2は位置(19,1)に移動完了
rover1は位置(16,7)で停止中
rover1は位置(16,7)で停止中
rover2は位置(19,0)に移動完了
rover1は位置(16,7)で停止中
rover2は位置(20,0)に移動できず方向を(-1,0)に変更
rover2は位置(18,0)に移動完了
rover1は位置(16,7)で停止中
rover1は位置(16,7)で停止中
rover2は位置(17,0)に移動完了
rover1は位置(16,7)で停止中
rover2は位置(16,0)に移動完了
rover2は位置(16,1)に移動完了
rover1は位置(16,7)で停止中
rover1は位置(16,7)で停止中
rover2は位置(16,2)に移動完了
rover2は位置(16,3)に移動完了
rover1は位置(16,7)で停止中
rover1は位置(16,7)で停止中
rover2は位置(16,4)に移動完了
rover2は位置(16,5)に移動完了
rover1は位置(16,7)で停止中
rover1は位置(16,7)で停止中
rover2は位置(16,6)に移動完了
rover1は位置(16,7)で停止中
rover2は位置(16,7)に移動できず方向を(-1,0)に変更
rover1は位置(16,7)で停止中
rover2は位置(15,6)に移動完了
rover2は位置(14,6)に移動完了
rover1は位置(17,7)に移動完了
rover2は位置(13,6)に移動完了
rover1は位置(18,7)に移動完了
rover1は位置(19,7)に移動完了
rover2は位置(12,6)に移動完了
rover1は位置(20,7)に移動できず方向を(0,1)に変更
rover2は位置(11,6)に移動完了
rover2は位置(11,6)で停止中
rover1は位置(19,8)に移動完了
rover2は位置(11,6)で停止中
rover1は位置(19,9)に移動完了
rover2は位置(11,6)で停止中
rover1は位置(19,10)に移動できず方向を(1,0)に変更
rover1は位置(20,9)に移動できず方向を(-1,0)に変更
rover2は位置(11,6)で停止中
rover2は位置(11,6)で停止中
rover1は位置(19,8)に移動完了
rover2は位置(11,6)で停止中
rover1は位置(19,7)に移動完了
rover1は位置(19,6)に移動完了
rover2は位置(11,6)で停止中
rover1は位置(19,5)に移動完了
rover2は位置(11,6)で停止中
rover2は位置(10,6)に移動完了
rover1は位置(19,4)に移動完了
rover1は位置(19,3)に移動完了
rover2は位置(9,6)に移動完了
rover2は位置(8,6)に移動完了
rover1は位置(19,2)に移動完了
rover1は位置(19,1)に移動完了
rover2は位置(7,6)に移動完了
rover2は位置(6,6)に移動完了
rover1は位置(19,1)で停止中
rover1は位置(19,1)で停止中
rover2は位置(5,6)に移動完了
rover2は位置(4,6)に移動完了
rover1は位置(19,1)で停止中
rover1は位置(19,1)で停止中
rover2は位置(3,6)に移動完了
rover2は位置(3,6)で停止中
rover1は位置(19,1)で停止中
rover2は位置(3,6)で停止中
rover1は位置(19,1)で停止中
rover1は位置(19,1)で停止中
rover2は位置(3,6)で停止中
rover2は位置(3,6)で停止中
rover1は位置(19,1)で停止中
rover1は位置(19,0)に移動完了
rover2は位置(3,6)で停止中
rover2は位置(3,6)で停止中
rover1は位置(19,-1)に移動できず方向を(0,1)に変更
rover2は位置(3,6)で停止中
rover1は位置(19,1)に移動完了
rover1は位置(19,2)に移動完了
rover2は位置(3,6)で停止中
rover2は位置(3,6)で停止中
rover1は位置(20,2)に移動できず方向を(0,-1)に変更
rover1は位置(19,1)に移動完了
rover2は位置(3,6)で停止中
rover1は位置(19,0)に移動完了
rover2は位置(3,6)で停止中
rover2は位置(3,6)で停止中
rover1は位置(19,-1)に移動できず方向を(-1,0)に変更
rover1は位置(18,0)に移動完了
rover2は位置(3,6)で停止中
rover2は位置(3,6)で停止中
rover1は位置(17,0)に移動完了
rover1は位置(16,0)に移動完了
rover2は位置(3,6)で停止中
rover2は位置(3,6)で停止中
rover1は位置(15,0)に移動完了
rover1は位置(14,0)に移動完了
rover2は位置(3,6)で停止中
rover1は位置(13,0)に移動完了
rover2は位置(3,6)で停止中
rover2は位置(3,6)で停止中
rover1は位置(12,0)に移動完了
rover1は位置(11,0)に移動完了
rover2は位置(3,6)で停止中
%
0 コメント:
コメントを投稿