My code can pass through 3 usage but I don't know why I can't pass the other - go

The question is:
Little Code has recently been playing Ice Adventure, an n-line m-column grid game. There are some impassable obstacles on some of the grids, and the rest of the grids are smooth ice.
The player is in it,ally on one of the non-obstacle grids, and remains stationary. Then he will following the character to move up and down, left and right; when he holds the characters move in one direction, the character will be on the ice surface to slide. The nature have for you here top moving until the next grid in the direction the character is moving is an obstacle or beyond the map boundary, then the surface will continue to wait for the next action of the little yard brother.
Now given the positions of all the obstacles in the map, the initial position of Little Yard and the sequence of Little Yard's actions, please find the position where Little Yard finally stays.
And here is my code
package main
import "fmt"
func yi(x,y int, s byte, a [][]int) (x1,y1 int){
switch(s){
case 'L':
for{
if y==0 || a[x][y-1]==1{
return x,y
}
y--
}
case 'R':
for{
if y==4 || a[x][y+1]==1{
return x,y
}
y++
}
case 'U':
for{
if x==0 || a[x-1][y]==1{
return x,y
}
x--
}
case 'D':
for{
if x==4 || a[x+1][y]==1{
return x,y
}
x++
}
}
return x1,y1
}
func main() {
var x,y,xc,yc,count int
fmt.Scanf("%d %d",&x,&y)
fmt.Scanf("%d %d",&xc,&yc)
fmt.Scanf("%d",&count)
// s:= make([]int,1,1)
i:=count
// }
arr := make([][]int, x)
for i := 0; i < x; i++ {
arr[i] = make([]int, y)
}
// var arr [6][6]int
for j:=0;j<i;j++{
var xt,yt int
fmt.Scanf("%d %d",&xt,&yt)
arr [xt-1][yt-1]=1
}
// for i:=0;i<x;i++{
// for j:=0;j<y;j++{
// fmt.Print(arr[i][j]," ")
// }
// fmt.Println()
// }
var kong string
fmt.Scanf("%s",&kong)
xf,yf:=xc-1,yc-1
// xf,yf=yi(xf,yf,'R',arr)
// fmt.Println(string(kong[7]))
for i:=0; i<8; i++{
xf,yf=yi(xf,yf,kong[i],arr)
// fmt.Println(xf,yf)
// func yi(x,y int, i int, s string, a *[5][5]int) (x1,y1 int){
}
fmt.Println(xf+1,yf+1)
}
I try to figure it out, but I need to find out where the problem is. Can you help me to figure it out(I don't know about the usage the professor used)

If I understand you correctly, I think maybe your code forget to use the variety. In the code, you write,
for i:=0; i<8; i++{
xf,yf=yi(xf,yf,kong[i],arr)
// fmt.Println(xf,yf)
// func yi(x,y int, i int, s string, a *[5][5]int) (x1,y1 int){
}
I think 8 is a subjective const and I think it should be changed.
Here is my solution, hope to help you
package main
import "fmt"
func yi(x,y int, s byte, a [][]int) (x1,y1 int){
switch(s){
case 'L':
for{
if y==0 || a[x][y-1]==1{
return x,y
}
y--
}
case 'R':
for{
if y==4 || a[x][y+1]==1{
return x,y
}
y++
}
case 'U':
for{
if x==0 || a[x-1][y]==1{
return x,y
}
x--
}
case 'D':
for{
if x==4 || a[x+1][y]==1{
return x,y
}
x++
}
}
return x1,y1
}
func main() {
var x,y,xc,yc,count int
fmt.Scanf("%d %d",&x,&y)
fmt.Scanf("%d %d",&xc,&yc)
fmt.Scanf("%d",&count)
// s:= make([]int,1,1)
i:=count
// }
arr := make([][]int, x)
for i := 0; i < x; i++ {
arr[i] = make([]int, y)
}
// var arr [6][6]int
for j:=0;j<i;j++{
var xt,yt int
fmt.Scanf("%d %d",&xt,&yt)
arr [xt-1][yt-1]=1
}
// for i:=0;i<x;i++{
// for j:=0;j<y;j++{
// fmt.Print(arr[i][j]," ")
// }
// fmt.Println()
// }
var kong string
fmt.Scanf("%s",&kong)
xf,yf:=xc-1,yc-1
// xf,yf=yi(xf,yf,'R',arr)
// fmt.Println(string(kong[7]))
for i:=0; i<count; i++{
xf,yf=yi(xf,yf,kong[i],arr)
// fmt.Println(xf,yf)
// func yi(x,y int, i int, s string, a *[5][5]int) (x1,y1 int){
}
fmt.Println(xf+1,yf+1)
}

Related

Why does this goroutine behave like it's call by reference?

I'm trying to learn the basics of Go and I'm a bit confused about the difference between call by value and call by reference in a code snippet I tested.
I tried to solve a coding game puzzle in which a solution for a tic-tac-toe field is to be calculated.
The code I'm using
Because I'm learning Go, I wanted to use a goroutine to test every field of the tic-tac-toe board, check whether this field is the solution and then put a pointer to this field in a channel for the main method to have the result. The code I used looks like this:
package main
import "fmt"
import "os"
var player int = int('O')
var opponent int = int('X')
var empty int = int('.')
type board struct {
fields [][]int
}
func main() {
lines := [3]string {"OO.", "...", "..."}
var b board
b.fillBoard(lines)
fmt.Fprintln(os.Stderr, "input board:")
b.printBoard(true)
resultChannel := make(chan *board)
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
go tryField(b, [2]int{i, j}, resultChannel) // goroutine call that isn't working as expected
}
}
fmt.Fprintln(os.Stderr, "\nresult:")
for i := 0; i < 9; i++ {
resultBoard := <- resultChannel
if (resultBoard != nil) {
resultBoard.printBoard(false)
return
}
}
// fmt.Fprintln(os.Stderr, "Debug messages...")
fmt.Println("false")// Write answer to stdout
}
func tryField(b board, field [2]int, result chan *board) {
b.printBoard(true)
fmt.Fprintln(os.Stderr, "add O to field: ", field)
fmt.Fprint(os.Stderr, "\n")
if (b.fields[field[0]][field[1]] != empty) {
result <- nil
}
b.fields[field[0]][field[1]] = player
if (b.isWon()) {
result <- &b
} else {
result <- nil
}
}
func (b *board) fillBoard(lines [3]string) {
b.fields = make([][]int, 3)
for i := 0; i < 3; i++ {
b.fields[i] = make([]int, 3)
}
for i, line := range lines {
for j, char := range line {
b.fields[i][j] = int(char)
}
}
}
func (b *board) printBoard(debug bool) {
var stream *os.File
if (debug) {
stream = os.Stderr
} else {
stream = os.Stdout
}
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Fprint(stream, string(b.fields[i][j]))
}
fmt.Fprint(stream, "\n")
}
}
func (b *board) isWon() bool {
for i := 0; i < 3; i++ {
rowFull := true
colFull := true
for j := 0; j < 3; j++ {
rowFull = rowFull && b.fields[i][j] == player
colFull = rowFull && b.fields[j][i] == player
}
if (rowFull || colFull) {
return true
}
}
diagonal1Full := true
diagonal2Full := true
for i := 0; i < 3; i++ {
diagonal1Full = diagonal1Full && b.fields[i][i] == player
diagonal2Full = diagonal2Full && b.fields[i][2-i] == player
}
if (diagonal1Full ||diagonal2Full) {
return true
}
return false
}
You can run it in the go playground.
The problem
Since the last function in the snippet is declared as func tryField(b board, field [2]int, result chan *board) I assume the board b to be an indipendent copy, each time I call the method, because it's call by value. So changing this board should not affect the other boards in the other goroutines. But unfortunately changing the board in one goroutine does affect the boards in the other goroutines as the output of the programm is the following:
input board:
OO.
...
...
result:
OO.
...
...
add O to field: [1 0]
OO.
O..
...
add O to field: [2 1]
OO.
O..
.O.
As you can see the initial field has two O's at the first and the second col in the first line. Adding an O to the position [1 0] works like expected, but when adding an O to the field [2 1] the there is also an O at [1 0], which was added in the previous goroutine and shouldn't be there since it's call by value.
The question
Why does the code in my snippet behave like it's call by reference although the function doesn't use a pointer?
Thanks in advance !
Slices are references to arrays. When modifying a slice without copying it, the underlaying array will be modified. Therefore, all slices that point to the same underlaying array will see this change.

How to recursively loop through map using different data structures

I'm trying to figure out the best way to recursively go through a [string]int map in Go. I'm building a game in which multiple countries are involved, and grouped together by teams of two in the end.
The goal is to match the first two countries with the lowest 'score' into its own group of two, and add it back to the collection giving the new map a total value of the scores of those countries.
Then recursively doing that to all the groups, ending up with one group and one total value in the end.
For example, if you had:
score := map[string]int{
"Canada": 7,
"US": 2,
"Germany": 3,
"Korea": 4,
}
group1 = {[US:2] [Germany:3]} with a total of 5
group1 would now be put back into the initial collection with a 'score' of 5 since it takes the two lowest scores. We would now have:
score := map[string]int{
"Canada": 7,
"Korea": 4,
group1: `US:2 Germany:3` with a total of 5
}
If this was now the lowest score in the collection, the next iteration would be:
group2 = {[Korea:4] [group1:5]}
score := map[string]int{
"Canada": 7,
group2: `Korea:4 group1:5` with a total of 9
}
And so on until you're left with one.. I think the basic structure should be something like this. However, I'm unsure of the proper way to do this since the data structure is now encompassing a [string]int map, as well as this new map.
I realize this is not such a generic question, but could an interface be used for this? I'm very new to Go, so advice would be helpful.
Here is an example to further illustrate what I mean:
https://play.golang.org/p/cnkTc0HBY4
Your problem can "easy" be solved using a heap data structure.
package main
import (
"container/heap"
"fmt"
)
// Something that has a score
type Scoreable interface {
fmt.Stringer
Score() int
}
// A country has a name and a score
type Country struct {
name string
score int
}
// Country implements Scoreable
func (c Country) Score() int {
return c.score
}
// ... and fmt.Stringer
func (c Country) String() string {
return fmt.Sprintf("%s [%d]", c.name, c.score)
}
// A team consists of two Scoreable's and has itself a score
type Team struct {
team1, team2 Scoreable
score int
}
// Team implements Scoreable
func (t Team) Score() int {
return t.score
}
// ... and fmt.Stringer
func (t Team) String() string {
return fmt.Sprintf("(%s + %s)", t.team1.String(), t.team2.String())
}
// The heap will be implemented using a slice of Scoreables
type TeamHeap []Scoreable
// TeamHeap implements heap.Interface
func (th TeamHeap) Len() int {
return len(th)
}
func (th TeamHeap) Less(i, j int) bool {
return th[i].Score() < th[j].Score()
}
func (th TeamHeap) Swap(i, j int) {
th[i], th[j] = th[j], th[i]
}
func (th *TeamHeap) Push(t interface{}) {
*th = append(*th, t.(Scoreable))
}
func (th *TeamHeap) Pop() interface{} {
old := *th
n := len(old)
t := old[n-1]
*th = old[0 : n-1]
return t
}
// The main function
func main() {
// Create a heap and initialize it
teams := &TeamHeap{}
heap.Init(teams)
// Push the countries (NB: heap.Push(), not teams.Push())
heap.Push(teams, Country{"Canada", 7})
heap.Push(teams, Country{"US", 2})
heap.Push(teams, Country{"Germany", 3})
heap.Push(teams, Country{"Korea", 4})
// Take the two teams with lowest score and make a new team of them
// Repeat this until there's only one team left
for teams.Len() > 1 {
t1 := heap.Pop(teams).(Scoreable)
t2 := heap.Pop(teams).(Scoreable)
heap.Push(teams, Team{t1, t2, t1.Score() + t2.Score()})
}
// Print the teams that we now have in the heap
for teams.Len() > 0 {
t := heap.Pop(teams).(Team)
fmt.Println(t)
}
}
You can find runnable code on the Go Playground.
package main
import (
"container/heap"
"fmt"
)
//Recursive data structure may looks something like
type Group struct {
Score int
Left *Group
Right *Group
Country string
}
//You can use slice to hold them organized in tree
type GrHeap []Group
//To implement your logic you can use stdlib/container/heap Heap interface
//you must implement Heap interface for your slice
func (h GrHeap) Len() int { return len(h) }
func (h GrHeap) Less(i, j int) bool { return h[i].Score < h[j].Score }
func (h GrHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *GrHeap) Push(x interface{}) {
// Push and Pop use pointer receivers because they modify the slice's length,
// not just its contents.
*h = append(*h, x.(Group))
}
func (h *GrHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
func main() {
//you most likely already have a map
//anyway it will be handy to keep it for convenient access to individual country
score := map[string]int{
"Canada": 7,
"US": 2,
"Germany": 3,
"Korea": 4,
}
//here we allocate heap
gr := make(GrHeap, 0)
//populate it from map
for k, v := range score {
g := Group{v, nil, nil, k}
gr = append(gr, g)
}
//and initialize
heap.Init(&gr)
//and here we use heap magic to implement your logic
for len(gr) > 2 {
l := heap.Pop(&gr).(Group)
r := heap.Pop(&gr).(Group)
ng := Group{l.Score + r.Score, &l, &r, ""}
heap.Push(&gr, ng)
}
fmt.Println(gr)
fmt.Println(gr[1].Left)
fmt.Println(gr[1].Right.Left)
//and you can see it works https://play.golang.org/p/gugJxJb7rr
}
You can try map[string]interface{} with Type assertion。
Here is the demo
package main
import "fmt"
const total = "total"
func GetValue(i interface{}) int {
value, ok := i.(int)
if ok {
return value
}
return i.(map[string]interface{})[total].(int)
}
func main() {
score := map[string]interface{}{
"Canada": 7,
"US": 2,
"Germany": 3,
"Korea": 4,
}
groupCount := 0
for len(score) > 2 {
var (
firstMin = math.MaxInt32
secondMin = math.MaxInt32
firstKey = ""
secondKey = ""
)
for k, v := range score {
iv := GetValue(v)
if iv < firstMin {
secondMin = firstMin
secondKey = firstKey
firstMin = iv
firstKey = k
continue
}
if iv < secondMin {
secondMin = iv
secondKey = k
continue
}
}
groupCount++
score[fmt.Sprintf("Group%d", groupCount)] = map[string]interface{}{
firstKey: score[firstKey],
secondKey: score[secondKey],
total: GetValue(score[firstKey])+ GetValue(score[secondKey]),
}
delete(score, firstKey)
delete(score, secondKey)
}
fmt.Println(score)
}
Here is the link https://play.golang.org/p/qq5qwAsh1m

Writing a nested iterator of depth d

How to realize a nested iterator that takes a depth argument. A simple iterator would be when depth = 1. it is a simple iterator which runs like a simple for loop.
func Iter () chan int {
ch := make(chan int);
go func () {
for i := 1; i < 60; i++ {
ch <- i
}
close(ch)
} ();
return ch
}
Output is 1,2,3...59
For depth = 2 Output would be "1,1" "1,2" ... "1,59" "2,1" ... "59,59"
For depth = 3 Output would be "1,1,1" ... "59,59,59"
I want to avoid a nested for loop. What is the solution here ?
I don't know if it is possible to avoid nested loops, but one solution is to use a pipeline of channels. For example:
const ITER_N = 60
// ----------------
func _goFunc1(out chan string) {
for i := 1; i < ITER_N; i++ {
out <- fmt.Sprintf("%d", i)
}
close(out)
}
func _goFuncN(in chan string, out chan string) {
for j := range in {
for i := 1; i < ITER_N; i++ {
out <- fmt.Sprintf("%s,%d", j, i)
}
}
close(out)
}
// ----------------
// create the pipeline
func IterDepth(d int) chan string {
c1 := make(chan string)
go _goFunc1(c1)
var c2 chan string
for ; d > 1; d-- {
c2 = make(chan string)
go _goFuncN(c1, c2)
c1 = c2
}
return c1
}
You can test it with:
func main() {
c := IterDepth(2)
for i := range c {
fmt.Println(i)
}
}
I usually implement iterators using closures. Multiple dimensions don't make the problem much harder. Here's one example of how to do this:
package main
import "fmt"
func iter(min, max, depth int) func() ([]int, bool) {
s := make([]int, depth)
for i := range s {
s[i] = min
}
s[0] = min - 1
return func() ([]int, bool) {
s[0]++
for i := 0; i < depth-1; i++ {
if s[i] >= max {
s[i] = min
s[i+1]++
}
}
if s[depth-1] >= max {
return nil, false
}
return s, true
}
}
func main() {
// Three dimensions, ranging between [1,4)
i := iter(1, 4, 3)
for s, ok := i(); ok; s, ok = i() {
fmt.Println(s)
}
}
Try it out on the Playground.
It'd be a simple change for example to give arguments as a single int slice instead, so that you could have per-dimension limits, if such a thing were necessary.

Indirectly change a value in a struct in Go

I have the following code, feel free to offer pointers if you wish:
package main
import (
"fmt"
)
type Grid struct {
rows int
cols int
tiles []Tile
}
type Tile struct {
x int
y int
contents int
}
func (g Grid) AddTile(t Tile) {
g.tiles = append(g.tiles, t)
}
func (g *Grid) Row(num int) []Tile {
numTiles := len(g.tiles)
row := []Tile{}
for i := 0; i < numTiles; i++ {
tile := g.tiles[i]
if (tile.y == num) {
row = append(row, tile)
}
}
return row
}
/*
HERE IS WHERE I NEED HELP
*/
func (g *Grid) SetRow(num, val int) {
row := g.Row(num)
rowLength := len(row)
for i := 0; i < rowLength; i++ {
tile := &row[i]
tile.contents = val
}
}
func (g Grid) Col(num int) []Tile {
numTiles := len(g.tiles)
col := []Tile{}
for i := 0; i < numTiles; i++ {
tile := g.tiles[i]
if (tile.x == num) {
col = append(col, tile)
}
}
return col
}
func MakeTile(x, y int) Tile {
tile := Tile{x: x, y: y}
return tile
}
func MakeGrid(rows, cols int) Grid {
g := Grid{ rows: rows, cols: cols}
for r := 1; r <= rows; r++ {
for c := 1; c <= cols; c++ {
g.tiles = append(g.tiles, MakeTile(r, c))
}
}
return g
}
func main() {
g := MakeGrid(256, 256)
g.SetRow(100, 5)
fmt.Println(g.Row(100))
}
I am doing this, more than anything, as a simple project to help me learn Go. The problem that is have run in to is here
/*
HERE IS WHERE I NEED HELP
*/
func (g *Grid) SetRow(num, val int) {
row := g.Row(num)
rowLength := len(row)
for i := 0; i < rowLength; i++ {
tile := &row[i]
tile.contents = val
}
}
Somewhere it seems like I need to be making a pointer to the actual Tiles that I'm trying to modify. As it is the SetRow function doesn't actually modify anything. What am I doing wrong? Keep in mind I just started learning Go 2 days ago, so this is a learning experience :)
One way to accomplish your goal is to use pointers to tiles throughout the code. Change the Grid tiles field to:
tiles []*Tile
and several related changes through the code.
Also, change all the methods to use pointer receivers. The AddTile method as written in the question discards the modification to the grid on return.
playground example

How to remove repeated element in a slice?

I have made a code to generate random numbers and delete the repeated ones like below:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
list := [7]int{}
for i := 0; i < 7; i++ {
here:
rand.Seed(time.Now().UnixNano())
s := rand.Intn(16)
fmt.Println(s)
if s != list[0] && s != list[1] && s != list[2] && s != list[3] && s != list[4] && s != list[5] && s != list[6] {
list[i] = s
} else {
goto here
}
}
fmt.Println("list:", list)
}
I noticed that there were a lot repeated code like:
s!=list[0]&&list[1]
But when I write it to:
s!=list[0:6]
It is wrong, how can I do this properly?
Store it in map.
like that
rndmap := make(map[int]bool)
for len(rndmap) < YOUR_LEN {
rndmap[rand.Intn(YOUR_MAX_RAND)] = true
}
Result map will never store repeated indexes.
You can convert it into slice like this
rndslice := make([]int,0)
for i, _ := range rndmap {
rndslice = append(rndslice, i)
}
You can use the standard library to generate the random elements without any repetition in the first place.
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println(rand.Perm(16)[:7])
}
If you want a way to check a slice of ints for a value, try this function (play.golang.org):
func InSlice (arr []int, val int) (bool){
for _, v := range(arr) {
if v == val { return true; }
}
return false;
}
You can use this like below, but you won't be able to run it succesfully on play.golang.org because play.golang.org has a deterministic response to math/rand (In my case, it's 0), which will keep it from giving more than one answer, forcing this code into an infinite loop.
func main() {
list := [7]int{}
for i := 0; i < 7; i++ {
here:
rand.Seed(time.Now().UnixNano())
s := rand.Intn(16)
fmt.Println(s)
if !InSlice(list[:], s) {
list[i] = s
} else {
goto here
}
}
The following program will pick the array passed in the function findDuplicates() and returns repeated / duplicate values in another array as output. Also if there are no duplicates the function will return -1.
package main
import "fmt"
func findDuplicates(arr []int) []int {
foundMap := make(map[int]bool, 0)
respArray := []int{}
for i := 0; i < len(arr); i++ {
if foundMap[arr[i]] == true {
respArray = append(respArray, arr[i])
} else {
foundMap[arr[i]] = true
}
}
if len(respArray) == 0 {
respArray = append(respArray, -1)
}
return respArray
}
func main() {
fmt.Println(findDuplicates([]int{19, 22, 22, 100, 1, 1, 1, 22, 88}))
}
// Output [22 1 1 22]

Resources