Решение на Ескалатори в мола от Живко Чобанов

Обратно към всички решения

Към профила на Живко Чобанов

Резултати

  • 8 точки от тестове
  • 0 бонус точки
  • 8 точки общо
  • 8 успешни тест(а)
  • 2 неуспешни тест(а)

Код

package main
import "sync"
var (
playerLifes sync.WaitGroup
lockCond *sync.Cond
isMarkedMallCell [4][4]bool
logLock sync.Mutex
)
var (
movesByPreference [][2]int = [][2]int{
{-1, -1},
{1, 1},
{1, -1},
{-1, 1}}
movesByPreferenceAndStatic [][2]int = make([][2]int, 5)
)
type runeMatrixDim4 [4][4]rune
func isPlayerHere(cell rune) bool {
return cell == 'X'
}
func (mall *runeMatrixDim4) forEachPlayer(action func(rowID, columnID int)) {
for rowID, row := range mall {
for columnID, cellRune := range row {
if isPlayerHere(cellRune) {
action(rowID, columnID)
}
}
}
}
func (mall *runeMatrixDim4) getNumberOfplayers() (numberOfPlayers int) {
mall.forEachPlayer(func(_, _ int) {
numberOfPlayers++
})
return
}
func setupWaitGroup(numberOfGoRutines int) {
playerLifes.Add(numberOfGoRutines)
}
func (mall *runeMatrixDim4) startPlayers(logChannel chan [2][2]int) {
mall.forEachPlayer(func(rowID, columnID int) {
go mall.playerLive(rowID, columnID, logChannel)
})
}
func newID(old, change int) int {
return (4 + old + change) % 4
}
func isNeighbourMoving(rowID, columnID int) bool {
isMarked := func(changeInRowID, changeInColumnID int) bool {
return isMarkedMallCell[newID(rowID, changeInRowID)][newID(columnID, changeInColumnID)] == true
}
return isMarked(0, 0) || isMarked(-1, -1) || isMarked(-1, 1) || isMarked(1, -1) || isMarked(1, 1)
}
func (mall *runeMatrixDim4) lockCellsSyncronically(rowID, columnID *int, action func() bool) bool {
markCell := func(changeInRowID, changeInColumnID int) {
isMarkedMallCell[newID(*rowID, changeInRowID)][newID(*columnID, changeInColumnID)] = true
}
unmarkCell := func(changeInRowID, changeInColumnID, rowID, columnID int) {
isMarkedMallCell[newID(rowID, changeInRowID)][newID(columnID, changeInColumnID)] = false
}
lockCond.L.Lock()
for isNeighbourMoving(*rowID, *columnID) {
lockCond.Wait()
}
for _, moves := range movesByPreferenceAndStatic {
markCell(moves[0], moves[1])
}
defer func(rowID, columnID int) {
for _, moves := range movesByPreferenceAndStatic {
unmarkCell(moves[0], moves[1], rowID, columnID)
}
lockCond.L.Unlock()
lockCond.Broadcast()
}(*rowID, *columnID)
hasBlocked := action()
return hasBlocked
}
func (mall *runeMatrixDim4) movePlayer(rowID, columnID *int, logChannel chan [2][2]int) bool {
hasMoved := false
newRowID := *rowID
newColumnID := *columnID
for _, moves := range movesByPreference {
newRowID = newID(*rowID, moves[0])
newColumnID = newID(*columnID, moves[1])
if !isPlayerHere(mall[newRowID][newColumnID]) {
hasMoved = true
break
}
}
if hasMoved {
logChannel <- [2][2]int{
{*rowID, *columnID},
{newRowID, newColumnID}}
mall[*rowID][*columnID] = '-'
mall[newRowID][newColumnID] = 'X'
*rowID = newRowID
*columnID = newColumnID
return false
} else {
logChannel <- [2][2]int{
{*rowID, *columnID},
{-2, -2}}
return true
}
}
func (mall *runeMatrixDim4) playerLive(rowID, columnID int, logChannel chan [2][2]int) {
defer playerLifes.Done()
hasBlocked := false
for i := 0; i < 100; i++ {
hasBlocked = mall.lockCellsSyncronically(&rowID, &columnID, func() bool {
return mall.movePlayer(&rowID, &columnID, logChannel)
})
if hasBlocked {
break
}
}
if !hasBlocked {
logChannel <- [2][2]int{
{rowID, columnID},
{-1, -1}}
}
}
func playMall(mall_input [4][4]rune) [][2][2]int {
mall := runeMatrixDim4(mall_input)
log := make([][2][2]int, 0)
lockCond = sync.NewCond(new(sync.Mutex))
copy(movesByPreferenceAndStatic, movesByPreference)
movesByPreferenceAndStatic[4] = [2]int{0, 0}
numberOfPlayers := mall.getNumberOfplayers()
if numberOfPlayers == 0 {
return [][2][2]int{{
{-1, -1},
{-1, -1}}}
} else {
setupWaitGroup(numberOfPlayers)
logChannel := make(chan [2][2]int, numberOfPlayers*101)
mall.startPlayers(logChannel)
playerLifes.Wait()
close(logChannel)
for move := range logChannel {
log = append(log, move)
}
return log
}
}

Лог от изпълнението

--- FAIL: Test10 (0.00 seconds)
panic: runtime error: index out of range [recovered]
	panic: runtime error: index out of range

goroutine 21 [running]:
testing.func·004()
	/usr/local/lib/go/src/pkg/testing/testing.go:348 +0x105
_/tmp/d20140123-11403-1rb5jbr.validWorldAndLogItem(0x18350280, 0xb7aaaf04, 0x1)
	/tmp/d20140123-11403-1rb5jbr/solution_test.go:32 +0x2d3
_/tmp/d20140123-11403-1rb5jbr.validLogItem(0x18350280, 0xb7aaaf04, 0x2d)
	/tmp/d20140123-11403-1rb5jbr/solution_test.go:78 +0x31
_/tmp/d20140123-11403-1rb5jbr.validGame(0x2d, 0x2d, 0x2d, 0x2d, 0x2d, ...)
	/tmp/d20140123-11403-1rb5jbr/solution_test.go:108 +0x12c
_/tmp/d20140123-11403-1rb5jbr.Test10(0x18355180)
	/tmp/d20140123-11403-1rb5jbr/solution_test.go:231 +0x4a
testing.tRunner(0x18355180, 0x81b018c)
	/usr/local/lib/go/src/pkg/testing/testing.go:353 +0x87
created by testing.RunTests
	/usr/local/lib/go/src/pkg/testing/testing.go:433 +0x684

goroutine 1 [chan receive]:
testing.RunTests(0x813d634, 0x81b0120, 0xa, 0xa, 0x1, ...)
	/usr/local/lib/go/src/pkg/testing/testing.go:434 +0x69f
testing.Main(0x813d634, 0x81b0120, 0xa, 0xa, 0x81b3580, ...)
	/usr/local/lib/go/src/pkg/testing/testing.go:365 +0x69
main.main()
	_/tmp/d20140123-11403-1rb5jbr/_test/_testmain.go:61 +0x81
exit status 2
FAIL	_/tmp/d20140123-11403-1rb5jbr	0.013s
PASS
ok  	_/tmp/d20140123-11403-1rb5jbr	0.012s
PASS
ok  	_/tmp/d20140123-11403-1rb5jbr	0.012s
PASS
ok  	_/tmp/d20140123-11403-1rb5jbr	0.011s
PASS
ok  	_/tmp/d20140123-11403-1rb5jbr	0.012s
PASS
ok  	_/tmp/d20140123-11403-1rb5jbr	0.012s
PASS
ok  	_/tmp/d20140123-11403-1rb5jbr	0.012s
PASS
ok  	_/tmp/d20140123-11403-1rb5jbr	0.013s
PASS
ok  	_/tmp/d20140123-11403-1rb5jbr	0.011s
--- FAIL: Test10 (0.00 seconds)
panic: runtime error: index out of range [recovered]
	panic: runtime error: index out of range

goroutine 4 [running]:
testing.func·004()
	/usr/local/lib/go/src/pkg/testing/testing.go:348 +0x105
_/tmp/d20140123-11403-1rb5jbr.validWorldAndLogItem(0x183501c0, 0xb7a94f04, 0x1)
	/tmp/d20140123-11403-1rb5jbr/solution_test.go:32 +0x2d3
_/tmp/d20140123-11403-1rb5jbr.validLogItem(0x183501c0, 0xb7a94f04, 0x2d)
	/tmp/d20140123-11403-1rb5jbr/solution_test.go:78 +0x31
_/tmp/d20140123-11403-1rb5jbr.validGame(0x2d, 0x2d, 0x2d, 0x2d, 0x2d, ...)
	/tmp/d20140123-11403-1rb5jbr/solution_test.go:108 +0x12c
_/tmp/d20140123-11403-1rb5jbr.Test10(0x18355120)
	/tmp/d20140123-11403-1rb5jbr/solution_test.go:231 +0x4a
testing.tRunner(0x18355120, 0x81b018c)
	/usr/local/lib/go/src/pkg/testing/testing.go:353 +0x87
created by testing.RunTests
	/usr/local/lib/go/src/pkg/testing/testing.go:433 +0x684

goroutine 1 [chan receive]:
testing.RunTests(0x813d634, 0x81b0120, 0xa, 0xa, 0x1, ...)
	/usr/local/lib/go/src/pkg/testing/testing.go:434 +0x69f
testing.Main(0x813d634, 0x81b0120, 0xa, 0xa, 0x81b3580, ...)
	/usr/local/lib/go/src/pkg/testing/testing.go:365 +0x69
main.main()
	_/tmp/d20140123-11403-1rb5jbr/_test/_testmain.go:61 +0x81
exit status 2
FAIL	_/tmp/d20140123-11403-1rb5jbr	0.012s

История (3 версии и 3 коментара)

Живко обнови решението на 22.01.2014 13:37 (преди над 4 години)

+package main
+
+import "sync"
+
+var (
+ mall [4][4]rune
+ log [][2][2]int
+)
+var (
+ playerLifes sync.WaitGroup
+ lockCond *sync.Cond
+ isMarkedMallCell [4][4]bool
+)
+var (
+ movesByPreference [][2]int = [][2]int{
+ {-1, -1},
+ {1, 1},
+ {1, -1},
+ {-1, 1}}
+ movesByPreferenceAndStatic [][2]int = make([][2]int, 5)
+)
+
+func isPlayerHere(cell rune) bool {
+ return cell == 'X'
+}
+
+func forEachPlayer(action func(rowID, columnID int)) {
+ for rowID, row := range mall {
+ for columnID, cellRune := range row {
+ if isPlayerHere(cellRune) {
+ action(rowID, columnID)
+ }
+ }
+ }
+}
+
+func getNumberOfplayers() (numberOfPlayers int) {
+ forEachPlayer(func(_, _ int) {
+ numberOfPlayers++
+ })
+ return
+}
+
+func setupWaitGroup(numberOfGoRutines int) {
+ playerLifes.Add(numberOfGoRutines)
+}
+
+func startPlayers() {
+ forEachPlayer(func(rowID, columnID int) {
+ go playerLive(rowID, columnID)
+ })
+}
+
+func newID(old, change int) int {
+ return (4 + old + change) % 4
+}
+
+func isNeighbourMoving(rowID, columnID int) bool {
+ isMarked := func(changeInRowID, changeInColumnID int) bool {
+ return isMarkedMallCell[newID(rowID, changeInRowID)][newID(columnID, changeInColumnID)] == true
+ }
+ return isMarked(0, 0) || isMarked(-1, -1) || isMarked(-1, 1) || isMarked(1, -1) || isMarked(1, 1)
+}
+
+func movePlayer(rowID, columnID *int) bool {
+ markCell := func(changeInRowID, changeInColumnID int) {
+ isMarkedMallCell[newID(*rowID, changeInRowID)][newID(*columnID, changeInColumnID)] = true
+ }
+ unmarkCell := func(changeInRowID, changeInColumnID, rowID, columnID int) {
+ isMarkedMallCell[newID(rowID, changeInRowID)][newID(columnID, changeInColumnID)] = false
+ }
+
+ lockCond.L.Lock()
+ for isNeighbourMoving(*rowID, *columnID) {
+ lockCond.Wait()
+ }
+ for _, moves := range movesByPreferenceAndStatic {
+ markCell(moves[0], moves[1])
+ }
+ defer func(rowID, columnID int) {
+ for _, moves := range movesByPreferenceAndStatic {
+ unmarkCell(moves[0], moves[1], rowID, columnID)
+ }
+ lockCond.L.Unlock()
+ lockCond.Broadcast()
+ }(*rowID, *columnID)
+
+ hasMoved := false
+ newRowID := *rowID
+ newColumnID := *columnID
+ for _, moves := range movesByPreference {
+ newRowID = newID(*rowID, moves[0])
+ newColumnID = newID(*columnID, moves[1])
+ if !isPlayerHere(mall[newRowID][newColumnID]) {
+ hasMoved = true
+ break
+ }
+ }
+
+ if hasMoved {
+ log = append(log, [2][2]int{[2]int{*rowID, *columnID},
+ [2]int{newRowID, newColumnID}})
+ mall[*rowID][*columnID] = '-'
+ mall[newRowID][newColumnID] = 'X'
+ *rowID = newRowID
+ *columnID = newColumnID
+ return true
+ } else {
+ log = append(log, [2][2]int{
+ {*rowID, *columnID},
+ {-2, -2}})
+ return false
+ }
+}
+
+func playerLive(rowID, columnID int) {
+ defer playerLifes.Done()
+
+ hasBlocked := false
+ for i := 0; i < 100; i++ {
+ if !movePlayer(&rowID, &columnID) {
+ hasBlocked = true
+ break
+ }
+ }
+ if !hasBlocked {
+ log = append(log, [2][2]int{
+ {rowID, columnID},
+ {-1, -1}})
+ }
+}
+
+func playMall(mall_input [4][4]rune) [][2][2]int {
+ mall = mall_input
+ log = make([][2][2]int, 0)
+ lockCond = sync.NewCond(new(sync.Mutex))
+ copy(movesByPreferenceAndStatic, movesByPreference)
+ movesByPreferenceAndStatic[4] = [2]int{0, 0}
+
+ numberOfPlayers := getNumberOfplayers()
+ if numberOfPlayers == 0 {
+ return [][2][2]int{{
+ {-1, -1},
+ {-1, -1}}}
+ } else {
+ setupWaitGroup(numberOfPlayers)
+ startPlayers()
+ playerLifes.Wait()
+ return log
+ }
+}

Живко обнови решението на 22.01.2014 23:18 (преди над 4 години)

package main
import "sync"
var (
mall [4][4]rune
log [][2][2]int
)
var (
playerLifes sync.WaitGroup
lockCond *sync.Cond
isMarkedMallCell [4][4]bool
+ logLock sync.Mutex
)
var (
movesByPreference [][2]int = [][2]int{
{-1, -1},
{1, 1},
{1, -1},
{-1, 1}}
movesByPreferenceAndStatic [][2]int = make([][2]int, 5)
)
func isPlayerHere(cell rune) bool {
return cell == 'X'
}
func forEachPlayer(action func(rowID, columnID int)) {
for rowID, row := range mall {
for columnID, cellRune := range row {
if isPlayerHere(cellRune) {
action(rowID, columnID)
}
}
}
}
func getNumberOfplayers() (numberOfPlayers int) {
forEachPlayer(func(_, _ int) {
numberOfPlayers++
})
return
}
func setupWaitGroup(numberOfGoRutines int) {
playerLifes.Add(numberOfGoRutines)
}
func startPlayers() {
forEachPlayer(func(rowID, columnID int) {
go playerLive(rowID, columnID)
})
}
func newID(old, change int) int {
return (4 + old + change) % 4
}
func isNeighbourMoving(rowID, columnID int) bool {
isMarked := func(changeInRowID, changeInColumnID int) bool {
return isMarkedMallCell[newID(rowID, changeInRowID)][newID(columnID, changeInColumnID)] == true
}
return isMarked(0, 0) || isMarked(-1, -1) || isMarked(-1, 1) || isMarked(1, -1) || isMarked(1, 1)
}
func movePlayer(rowID, columnID *int) bool {
markCell := func(changeInRowID, changeInColumnID int) {
isMarkedMallCell[newID(*rowID, changeInRowID)][newID(*columnID, changeInColumnID)] = true
}
unmarkCell := func(changeInRowID, changeInColumnID, rowID, columnID int) {
isMarkedMallCell[newID(rowID, changeInRowID)][newID(columnID, changeInColumnID)] = false
}
lockCond.L.Lock()
for isNeighbourMoving(*rowID, *columnID) {
lockCond.Wait()
}
for _, moves := range movesByPreferenceAndStatic {
markCell(moves[0], moves[1])
}
defer func(rowID, columnID int) {
for _, moves := range movesByPreferenceAndStatic {
unmarkCell(moves[0], moves[1], rowID, columnID)
}
lockCond.L.Unlock()
lockCond.Broadcast()
}(*rowID, *columnID)
hasMoved := false
newRowID := *rowID
newColumnID := *columnID
for _, moves := range movesByPreference {
newRowID = newID(*rowID, moves[0])
newColumnID = newID(*columnID, moves[1])
if !isPlayerHere(mall[newRowID][newColumnID]) {
hasMoved = true
break
}
}
if hasMoved {
- log = append(log, [2][2]int{[2]int{*rowID, *columnID},
- [2]int{newRowID, newColumnID}})
+ appendToLog([2][2]int{
+ {*rowID, *columnID},
+ {newRowID, newColumnID}})
mall[*rowID][*columnID] = '-'
mall[newRowID][newColumnID] = 'X'
*rowID = newRowID
*columnID = newColumnID
return true
} else {
- log = append(log, [2][2]int{
+ appendToLog([2][2]int{
{*rowID, *columnID},
{-2, -2}})
return false
}
}
+func appendToLog(move [2][2]int) {
+ logLock.Lock()
+ log = append(log, move)
+ logLock.Unlock()
+}
+
func playerLive(rowID, columnID int) {
defer playerLifes.Done()
hasBlocked := false
for i := 0; i < 100; i++ {
if !movePlayer(&rowID, &columnID) {
hasBlocked = true
break
}
}
if !hasBlocked {
- log = append(log, [2][2]int{
+ appendToLog([2][2]int{
{rowID, columnID},
{-1, -1}})
}
}
func playMall(mall_input [4][4]rune) [][2][2]int {
mall = mall_input
log = make([][2][2]int, 0)
lockCond = sync.NewCond(new(sync.Mutex))
copy(movesByPreferenceAndStatic, movesByPreference)
movesByPreferenceAndStatic[4] = [2]int{0, 0}
numberOfPlayers := getNumberOfplayers()
if numberOfPlayers == 0 {
return [][2][2]int{{
{-1, -1},
{-1, -1}}}
} else {
setupWaitGroup(numberOfPlayers)
startPlayers()
playerLifes.Wait()
return log
}
}

Живко обнови решението на 23.01.2014 16:52 (преди над 4 години)

package main
import "sync"
var (
- mall [4][4]rune
- log [][2][2]int
-)
-var (
playerLifes sync.WaitGroup
lockCond *sync.Cond
isMarkedMallCell [4][4]bool
logLock sync.Mutex
)
var (
movesByPreference [][2]int = [][2]int{
{-1, -1},
{1, 1},
{1, -1},
{-1, 1}}
movesByPreferenceAndStatic [][2]int = make([][2]int, 5)
)
+type runeMatrixDim4 [4][4]rune
+
func isPlayerHere(cell rune) bool {
return cell == 'X'
}
-func forEachPlayer(action func(rowID, columnID int)) {
+func (mall *runeMatrixDim4) forEachPlayer(action func(rowID, columnID int)) {
for rowID, row := range mall {
for columnID, cellRune := range row {
if isPlayerHere(cellRune) {
action(rowID, columnID)
}
}
}
}
-func getNumberOfplayers() (numberOfPlayers int) {
- forEachPlayer(func(_, _ int) {
+func (mall *runeMatrixDim4) getNumberOfplayers() (numberOfPlayers int) {
+ mall.forEachPlayer(func(_, _ int) {
numberOfPlayers++
})
return
}
func setupWaitGroup(numberOfGoRutines int) {
playerLifes.Add(numberOfGoRutines)
}
-func startPlayers() {
- forEachPlayer(func(rowID, columnID int) {
- go playerLive(rowID, columnID)
+func (mall *runeMatrixDim4) startPlayers(logChannel chan [2][2]int) {
+ mall.forEachPlayer(func(rowID, columnID int) {
+ go mall.playerLive(rowID, columnID, logChannel)
})
}
func newID(old, change int) int {
return (4 + old + change) % 4
}
func isNeighbourMoving(rowID, columnID int) bool {
isMarked := func(changeInRowID, changeInColumnID int) bool {
return isMarkedMallCell[newID(rowID, changeInRowID)][newID(columnID, changeInColumnID)] == true
}
return isMarked(0, 0) || isMarked(-1, -1) || isMarked(-1, 1) || isMarked(1, -1) || isMarked(1, 1)
}
-func movePlayer(rowID, columnID *int) bool {
+func (mall *runeMatrixDim4) lockCellsSyncronically(rowID, columnID *int, action func() bool) bool {
markCell := func(changeInRowID, changeInColumnID int) {
isMarkedMallCell[newID(*rowID, changeInRowID)][newID(*columnID, changeInColumnID)] = true
}
unmarkCell := func(changeInRowID, changeInColumnID, rowID, columnID int) {
isMarkedMallCell[newID(rowID, changeInRowID)][newID(columnID, changeInColumnID)] = false
}
lockCond.L.Lock()
for isNeighbourMoving(*rowID, *columnID) {
lockCond.Wait()
}
for _, moves := range movesByPreferenceAndStatic {
markCell(moves[0], moves[1])
}
defer func(rowID, columnID int) {
for _, moves := range movesByPreferenceAndStatic {
unmarkCell(moves[0], moves[1], rowID, columnID)
}
lockCond.L.Unlock()
lockCond.Broadcast()
}(*rowID, *columnID)
+ hasBlocked := action()
+ return hasBlocked
+}
+
+func (mall *runeMatrixDim4) movePlayer(rowID, columnID *int, logChannel chan [2][2]int) bool {
hasMoved := false
newRowID := *rowID
newColumnID := *columnID
for _, moves := range movesByPreference {
newRowID = newID(*rowID, moves[0])
newColumnID = newID(*columnID, moves[1])
if !isPlayerHere(mall[newRowID][newColumnID]) {
hasMoved = true
break
}
}
if hasMoved {
- appendToLog([2][2]int{
+ logChannel <- [2][2]int{
{*rowID, *columnID},
- {newRowID, newColumnID}})
+ {newRowID, newColumnID}}
mall[*rowID][*columnID] = '-'
mall[newRowID][newColumnID] = 'X'
*rowID = newRowID
*columnID = newColumnID
- return true
+ return false
} else {
- appendToLog([2][2]int{
+ logChannel <- [2][2]int{
{*rowID, *columnID},
- {-2, -2}})
- return false
+ {-2, -2}}
+ return true
}
}
-func appendToLog(move [2][2]int) {
- logLock.Lock()
- log = append(log, move)
- logLock.Unlock()
-}
-
-func playerLive(rowID, columnID int) {
+func (mall *runeMatrixDim4) playerLive(rowID, columnID int, logChannel chan [2][2]int) {
defer playerLifes.Done()
hasBlocked := false
for i := 0; i < 100; i++ {
- if !movePlayer(&rowID, &columnID) {
- hasBlocked = true
+ hasBlocked = mall.lockCellsSyncronically(&rowID, &columnID, func() bool {
+ return mall.movePlayer(&rowID, &columnID, logChannel)
+ })
+ if hasBlocked {
break
}
}
if !hasBlocked {
- appendToLog([2][2]int{
+ logChannel <- [2][2]int{
{rowID, columnID},
- {-1, -1}})
+ {-1, -1}}
}
}
func playMall(mall_input [4][4]rune) [][2][2]int {
- mall = mall_input
- log = make([][2][2]int, 0)
+ mall := runeMatrixDim4(mall_input)
+ log := make([][2][2]int, 0)
lockCond = sync.NewCond(new(sync.Mutex))
copy(movesByPreferenceAndStatic, movesByPreference)
movesByPreferenceAndStatic[4] = [2]int{0, 0}
- numberOfPlayers := getNumberOfplayers()
+ numberOfPlayers := mall.getNumberOfplayers()
if numberOfPlayers == 0 {
return [][2][2]int{{
{-1, -1},
{-1, -1}}}
} else {
setupWaitGroup(numberOfPlayers)
- startPlayers()
+ logChannel := make(chan [2][2]int, numberOfPlayers*101)
+
+ mall.startPlayers(logChannel)
playerLifes.Wait()
+ close(logChannel)
+
+ for move := range logChannel {
+ log = append(log, move)
+ }
return log
}
}