2020年5月17日日曜日

x

開発環境

入門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 コメント:

コメントを投稿