For a struct vertex, what's the difference between map[int]vertex and map[int]*vertex? - go

To define a map from int to struct vertex, should I define map[int]vertex or map[int]*vertex? Which one is preferred?
I extended Chickencha's code:
package main
type vertex struct {
x, y int
}
func main() {
a := make(map[int]vertex)
b := make(map[int]*vertex)
v := &vertex{0, 0}
a[0] = *v
b[0] = v
v.x, v.y = 4, 4
println(a[0].x, a[0].y, b[0].x, b[0].y)
//a[0].x = 3 // cannot assign to (a[0]).x
//a[0].y = 3 // cannot assign to (a[0]).y
b[0].x = 3
b[0].y = 3
println(a[0].x, a[0].y, b[0].x, b[0].y)
u1 := a[0]
u1.x = 2
u1.y = 2
u2 := b[0]
u2.x = 2
u2.y = 2
println(a[0].x, a[0].y, b[0].x, b[0].y)
}
The output:
0 0 4 4
0 0 3 3
0 0 2 2
From the output, my understanding is, if I want to change the struct member in place, I must use pointer to the struct.
But I'm still not sure the underlying reasons. Especially, why I cannot assign to a[0].x?

The main difference is that map[int]vertex stores vertex values and map[int]*vertex stores vertex references (pointers). The output of the following program should help illustrate:
package main
type vertex struct {
x, y int
}
func main() {
a := make(map[int]vertex)
b := make(map[int]*vertex)
v := &vertex{0, 0}
a[0] = *v
b[0] = v
v.x, v.y = 4, 4
println(a[0].x, a[0].y, b[0].x, b[0].y)
}
Output:
0 0 4 4
The vertex stored in b is modified by the v.x, v.y = 4, 4 line, while the vertex stored in a is not.

The answer to this question is likely to be dependent on how Go maps are implemented. For the current implementation, I would take a look the Go map runtime header, hashmap.h, and code, hashmap.c, files. It's also going to depend on how you use the map e.g. what type and volume of activities against the map, key and element data structures, etc.
To update a vector element value in place, read the vector element value from the map, update the element value, write the updated element value to the map. For example
package main
type vertex struct {
x, y int
}
func main() {
a := make(map[int]vertex)
a[0] = vertex{0, 0}
println(a[0].x, a[0].y)
v0 := a[0]
v0.x = 1
a[0] = v0
println(a[0].x, a[0].y)
}
Output:
0 0
1 0

Related

What is there in the data structure tree's value?

I am studying algorithm union find.
But I don't mind with the value.
Example,
0 to 3 are connected on the one line.
So, we draw the line like this.
0 - 1 - 2 - 3
In this case, where I found the 3's parent? Where is the 3's parent the 2?
int parent[1000001];
int Find(int x){
if(x == parent[x]){
return x;
}
else{
int y = Find(parent[x]);
parent[x] = y;
return y;
}
}
void Union(int x, int y){
x = Find(x);
y = Find(y);
parent[y] = x;
}
Which value actually becomes the parent of 3 depends on the order in which you unite pairs of values.
But first of all your code should initialise parent before connecting any points. When there are no connections yet, you must have for every i:
parent[i] = i
Then, if for instance your calls are like follows:
Union(0, 1)
Union(1, 2)
Union(2, 3)
...the parent relationship will evolve like this (pseudo code):
Union(0, 1)
x := 0
y := 1
parent[1] := 0
Union(1, 2)
x := 0 // because Find looks up the "root" of 1
y := 2
parent[2] := 0
Union(2, 3)
x := 0 // because Find looks up the "root" of 2
y := 3
parent[3] := 0
Remark
Your implementation of Union Find has path compression, but does not improve tree-balancing with a size or rank attribute. The implementation becomes most efficient if it uses both strategies. See Wikipedia on this topic.

Finding pair arrangement in Go

Here I'm trying to form an arrangement that contains pairs of numbers that each pair of m's are separated by m elements. for example:
for [0,2], the pair arrangement is [2,0, 0,2] such that m=2, hence the number 2 is separated by 2 elements.
for [0,1] = there is no valid arrangement
I still can't figure out the pattern or algorithm for the arrangement as I need to find the arrangement up to [0,1,2,3,4,5,6,7,8]. however the valid arrangement for this list is [3,7,8,2,3,1,2,1,6,7,5,8,4,0,0,6,5,4] by doing it manually.
In the codes below, I could only rearrange the numbers in the list by getting the largest number in the list first. I want to know how to separate the pair according to the number of the pair (e.g if the pair is 2, hence separation number is 2)
how can i do the separation and pattern for the list of numbers?
package main
import "fmt"
func MagicPairs(list []int) {
//length := len(list) * 2
magicPair := []int{}
magicPair = append(list, list...)
for i := 0; i <len(magicPair); i++{
if len(magicPair) == 0 {
//do nothing
}else{
m := max(list)
for p, x := range magicPair{
if magicPair[len(magicPair)-1] == m {
magicPair = append([]int{m}, (magicPair)[:len(magicPair)-1]...)
fmt.Println(magicPair)
return
}
if x == m{
magicPair = append([]int{m}, append((magicPair)[:p], (magicPair)[p+1:]...)...)
}
previousPair := magicPair[x]
if x == previousPair{
}
}
}
}
fmt.Println("1", magicPair)
}
func max(list[] int) int{
max := list[0]
for _, value := range list{
if value > max {
max = value
}
}
return max
}
func main(){
list := [] int {0,1,2,3,4,5,6,7,8}
MagicPairs(list)
}
You seem to try to find the optimal solution by doubling up the source list and then shuffling the numbers around by repeatedly slicing and concatenating the array.
I think this problem lends itself to a recursive approach. Create thze target array with 2 * len(list) empty slots. (Whether a slot is empty or not must be marked with a special value, for example -1.) Then recursively try to fit the elements of the original array into the target array.
Let's look at your example {0, 1, 3}. Create the target array:
. . . . . .
Try all possible poitions for the 0. The first is
0 0 . . . .
Now try to fit the 1. There are two possibilities
0 0 . . . .
0 0 1 . 1 .
but that won't accomodate the next element, 3. Go back one step:
0 0 . . . .
0 0 . 1 . 1
The 3 won't fit in here, either. We've exhausted our search for that position of zeros, so let's take the next viable position of zeros:
. 0 0 . . .
There's only one way to place the one:
. 0 0 . . .
. 0 0 1 . 1
Now let's try to fit the 3 and, bingo!, it fits:
. 0 0 . . .
. 0 0 1 . 1
3 0 0 1 3 1
Now you can stop the search or try to find other solutions. In this case, there's only one other solution, namely the reflection of this one, but there are 300 ways to place the numbers from 1 to 8, foe example.
That approach is pretty much brute force, but in practice, there aren't many valid ways to fill the array, so that wrong paths are detected early. Perhaps placing the big numbers first gives better performance. You can play with that and measure it.
Here's a program that does that. (It probably looks more like C than Go. never mind.)
package main
import "fmt"
func fit_r(res[] int, a[] int, i int) int {
n := len(a);
if i == n {
fmt.Printf("%v\n", res);
return 1;
} else {
count := 0;
m := a[i];
for j := 0; j < 2*n - 1 - m; j++ {
if res[j] == -1 && res[j + 1 + m] == -1 {
// place values
res[j] = m;
res[j + 1 + m] = m;
// test further values
count += fit_r(res, a, i + 1);
// clean up and remove values again
res[j] = -1;
res[j + 1 + m] = -1;
}
}
return count;
}
}
func fit(a[] int) int {
res := make([] int, 2 * len(a));
for i := range res {
res[i] = -1;
}
return fit_r(res, a, 0);
}
func main() {
list := [] int {0, 1, 2, 3};
n := fit(list);
fmt.Println(n, "solutions");
}

How do I pass an array of C.double's to a Cgo function?

I'm just getting started with CGo and I'm trying to send data to a C library that performs statistical computations on arrays of floats/doubles. What I'm trying to figure out right now is how to send an array of floats, or C.double's, to a CGo function that has a signature like this:
double pop_mean(int numPoints, double a[])
I've figured out how to get in the C.int in there, but I'm having trouble figuring out how to send in an array of doubles.
I haven't yet seen any blog posts or SO Questions about this exact thing, so I thought I'd ask.
The following is my best effort so far.
// Get a basic function to work, while passing in an ARRAY arr := make([]C.double, 0)
arr = append(arr, C.double(10.0))
arr = append(arr, C.double(20.0))
arr = append(arr, C.double(30.0))
var fixedArray [3]C.double = arr[:]
// ptr := C.CBytes(arr)
// defer C.free(unsafe.Pointer(ptr))
coolMean := C.pop_mean(3, &fixedArray)
fmt.Println("pop_mean (10, 20, 30): ", coolMean)
And this is the error I'm getting:
./main.go:64:6: cannot use arr[:] (type []_Ctype_double) as type [3]_Ctype_double in assignment
./main.go:69:35: cannot use &fixedArray (type *[3]_Ctype_double) as type *_Ctype_double in argument to _Cfunc_pop_mean
How should I be passing an array of C.double to the code?
When an array name is passed to a function, what is passed is the
location of the initial element. Within the called function, this
argument is a local variable, and so an array name parameter is a
pointer, that is, a variable containing an address.
C Programming Language, 2nd Edition
Slice types
A slice is a descriptor for a contiguous segment of an underlying
array and provides access to a numbered sequence of elements from that
array.
Like arrays, slices are indexable and have a length. The length of a
slice s can be discovered by the built-in function len; unlike with
arrays it may change during execution. The elements can be addressed
by integer indices 0 through len(s)-1. The slice index of a given
element may be less than the index of the same element in the
underlying array.
A slice, once initialized, is always associated with an underlying
array that holds its elements.
The Go Programming Language Specification
Reference: Go Command cgo
For a slice a, the arguments to the pop_mean(int numPoints, double a[]) C function are len(a), the length of the slice underlying array, and &a[0], the address of the first element of the slice underlying array.
In Go, we often hide details in a function. For example, a popMean function,
package main
import (
"fmt"
)
/*
double pop_mean(int numPoints, double a[]) {
if (a == NULL || numPoints == 0) {
return 0;
}
double mean = 0;
for (int i = 0; i < numPoints; i++) {
mean+=a[i];
}
return mean / numPoints;
}
*/
import "C"
func popMean(a []float64) float64 {
// This is the general case, which includes the special cases
// of zero-value (a == nil and len(a) == 0)
// and zero-length (len(a) == 0) slices.
if len(a) == 0 {
return 0
}
return float64(C.pop_mean(C.int(len(a)), (*C.double)(&a[0])))
}
func main() {
a := make([]float64, 10)
for i := range a {
a[i] = float64(i + 1)
}
// slice
fmt.Println(len(a), a)
pm := popMean(a)
fmt.Println(pm)
// subslice
b := a[1:4]
fmt.Println(len(b), b)
pm = popMean(b)
fmt.Println(pm)
// zero length
c := a[:0]
fmt.Println(len(c), c)
pm = popMean(c)
fmt.Println(pm)
// zero value (nil)
var z []float64
fmt.Println(len(z), z, z == nil)
pm = popMean(z)
fmt.Println(pm)
}
Output:
10 [1 2 3 4 5 6 7 8 9 10]
5.5
3 [2 3 4]
3
0 []
0
0 [] true
0
I figured out that you have to send a pointer to the first value in the array, rather than sending a pointer to the first element of the slice, or to the slice itself.
AND I also ran into the problem where I had created a new variable that was assigned the value of the first item in the slice and later created a pointer to that variable (which was no longer a part of the original array), instead of creating a pointer to the first item in the array (like I wanted).
Below is the working code, with comments to help avoid the problem in the paragraph above.
// Get a basic function to work, while passing in an ARRAY
// Create a dummy array of (10,20,30), the mean of which is 20.
arr := make([]C.double, 0)
arr = append(arr, C.double(10.0))
arr = append(arr, C.double(20.0))
arr = append(arr, C.double(30.0))
firstValue := &(arr[0]) // this notation seems to be pretty important... Re-use this!
// if you don't make it a pointer right away, then you make a whole new object in a different location, so the contiguous-ness of the array is jeopardized.
// Because we have IMMEDIATELY made a pointer to the original value,the first value in the array, we have preserved the contiguous-ness of the array.
fmt.Println("array length: ", len(arr))
var arrayLength C.int
arrayLength = C.int(len(arr))
// arrayLength = C.int(2)
fmt.Println("array length we are using: ", arrayLength)
arrayMean := C.pop_mean(arrayLength, firstValue)
fmt.Println("pop_mean (10, 20, 30): ", arrayMean)
This produces the following result:
array length: 3
array length we are using: 3
pop_mean (10, 20, 30): 20
Or if we uncomment the line that changes the arrayLength to be 2, we get this result:
array length: 3
array length we are using: 2
pop_mean (10, 20, 30): 15

Golang code too slow for Hackerrank

I've been trying to solve this Hackerrank challenge: Link
This is what you have to do:
You have one large matrix:
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 0 1 1
and one small matrix:
1 1 1
1 1 1
1 1 0
You have to find out if the small matrix is present in the large matrix.
There are up to 5 testcases and each matrix can be of max 1000x1000 size and I need to solve this in under 4 seconds.
My code timeouts for the largest possible input, I thought that maybe how I'm scanning the matrix is too slow.
This is my code:
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
var t, rL, cL, rS, cS, temp int
var s string
var sl []string
var mxL, mxS [][]int
var found bool
fmt.Scanf("%d", &t)
for ; t > 0; t-- {
// Start scanning input
// Scanning large matrix
fmt.Scanf("%d%d", &rL, &cL)
mxL = make([][]int, rL)
for i := range mxL {
mxL[i] = make([]int, cL)
}
for i := 0; i < rL; i++ {
fmt.Scanf("%s", &s)
sl = strings.Split(s, "")
for j, v := range sl {
temp, _ = strconv.Atoi(v)
mxL[i][j] = temp
}
}
// Scanning small matrix
fmt.Scanf("%d%d", &rS, &cS)
mxS = make([][]int, rS)
for i := range mxS {
mxS[i] = make([]int, cS)
}
for i := 0; i < rS; i++ {
fmt.Scanf("%s", &s)
sl = strings.Split(s, "")
for j, v := range sl {
temp, _ = strconv.Atoi(v)
mxS[i][j] = temp
}
}
// Stop scanning input
// Start searching for small matrix in large matrix
found = true
for iL := 0; iL <= rL-rS; iL++ {
for jL := 0; jL <= cL-cS; jL++ {
found = true
if mxL[iL][jL] == mxS[0][0] {
for iS := 0; iS < rS; iS++ {
for jS := 1; jS < cS; jS++ {
if mxS[iS][jS] != mxL[iS+iL][jS+jL] {
found = false
break
}
}
if !found {
break
}
}
if found {
break
}
} else {
found = false
}
}
if found {
fmt.Println("YES")
break
}
}
if !found {
fmt.Println("NO")
}
// Stop searching for small matrix in large matrix
}
}
I'm using a slice of slices of ints to store the input.
mxL is the large matrix and mxS is the small matrix.
rL and cL stand for row and column of the large matrix.
rS and cS stand for row and column of the small matrix.
Well I am gonna point out an idea to you and then you can try to implement it. So create a new 2d array as large as your large array. Call it sumArray. Now let each cell in this sumArray represent the sum where the current cell is the most bottom-left cell. Now what you do is check only the cells that has the same sum as your small array instead of checking every element in the array.
So if those are your inputs
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 0 1 1
1 1 1
1 1 1
1 1 0
First sum your small array --> 8
Now let me show you how your sum array would look like
-1 -1 -1 -1 -1 -1 -1 means that we can't sum at this point because
-1 -1 -1 -1 -1 -1 the dimensions are just smaller than your small array
-1 -1 9 9 9 9 each other cell represent the sum of your original
9 9 9 9 9 9 matrix values.
9 9 9 8 9 9
Now if you scan trough this array only you can see that you will reduce your search space from every possible position to only the position where your sum is equal. This doesn't guarantee that the array are in this position you still have to add a verification step but it reduce your search space.

Why DFS isn't fast enough in checking if a graph is a tree

I tried to solve this problem
Problem Description
It seems correct idea is to check if given graphs have cycles (whether is a tree). However, my code couldn't pass Test 7, (Always Time Limit Exceeded), any idea how to make this faster? I used DFS. Many thanks
Yes, finally got accepted. The problem is dfs on each vertex, which is unnecessary.
the dfs function should be like this.
function dfs(idx: integer; id: integer): boolean;
begin
if (visited[idx] = id) then
begin
Result := false;
Exit;
end;
if (tree[idx] <> 0) then
begin
visited[idx] := id;
Result := dfs(tree[idx], id);
Exit;
end;
Result := true;
end;
program Project2;
{$APPTYPE CONSOLE}
var
i, m, j, n, k: integer;
tree: array [1 .. 25001] of integer;
visited: array [1 .. 25001] of boolean;
function dfs(idx: integer): boolean;
label
fin;
var
buf: array[1 .. 25001] of integer;
i, cnt: integer;
begin
cnt := 1;
while (true) do
begin
if (visited[idx]) then
begin
Result := false;
goto fin;
end;
if (tree[idx] <> 0) then
begin
visited[idx] := true;
buf[cnt] := idx;
Inc(cnt);
idx := tree[idx];
end
else
begin
break;
end;
end;
Result := true;
fin:
for i := 1 to cnt - 1 do
begin
visited[buf[i]] := false;
end;
end;
function chk(n: integer): boolean;
var
i: integer;
begin
for i := 1 to n do
begin
if (tree[i] = 0) then continue;
if (visited[i]) then continue;
if (dfs(i) = false) then
begin
Result := false;
Exit;
end;
end;
Result := true;
end;
begin
Readln(m);
for i := 1 to m do
begin
Readln(n);
k := 0;
for j := 1 to n do
begin
Read(tree[j]);
if (tree[j] = 0) then
begin
Inc(k);
end;
end;
if (k <> 1) then
begin
Writeln('NO');
end
else
if (chk(n)) then
begin
Writeln('YES');
end
else
begin
Writeln('NO');
end;
Readln;
end;
//Readln;
end.
I know next to nothing about Pascal, so I could be misinterpreting what you are doing, but I think the main culprit is at fin where you unmark visited vertices. This forces you into doing a DFS from each vertex, whereas you only need to do one per component.
In the case where there is more than one connected component the movement will either halt
because a vertex points to a vertex already marked, in which case we just halt due to a cycle having been found
because the vertex points to no one (but itself), in which case we need to find the next unmarked vertex and start another DFS again from there
You need not worry about bookkeeping for backtracking as each vertex at most points to one other vertex in this problem. There is also no need to worry about which DFS did which marking, as each will only work within its connected component anyway.
In the case where a vertex that points to itself is encountered first, it should not be marked yet, but skipped over.
Alternate Solution Using Set Union and Vertex/Edge Count
Since a tree has the property that the number of edges is one less than the number of vertices, there is another way to think about the problem -- determine (1) the connected components and (2) compare the edge and vertex count in each component.
In many languages you have a Set data structure with near-constant time Union/Find methods readily available. In this case the solution is easy and fast - near-linear in the number of edges.
Create an Set for each vertex representing its connected component. Then process your edge list. For each edge, Union the Sets represented by the two vertices. As you go, keep track of the number of vertices in each Set and the number edges. Same example:
Initial Sets
Vertex 1 2 3 4 5
Belongs to S1 S2 S3 S4 S5
Set S1 S2 S3 S4 S5
Has # vertices 1 1 1 1 1
And # edges 0 0 0 0 0
Process edge from 1 to 2
Vertex 1 2 3 4 5
Belongs to S1 S1 S3 S4 S5
Set S1 S3 S4 S5
Has # vertices 2 1 1 1
And # edges 1 0 0 0
Process edge from 2 to 3
Vertex 1 2 3 4 5
Belongs to S1 S1 S1 S4 S5
Set S1 S4 S5
Has # vertices 3 1 1
And # edges 2 0 0
Process edge from 3 to 4
Vertex 1 2 3 4 5
Belongs to S1 S1 S1 S1 S5
Set S1 S5
Has # vertices 4 1
And # edges 3 0
Process edge from 4 to 1
Vertex 1 2 3 4 5
Belongs to S1 S1 S1 S1 S5
Set S1 S5
Has # vertices 4 1
And # edges 4 0
And we can stop here because S1 at this point violates the vertex versus edge count of trees. There is a cycle in S1. It does not matter if vertex 5 points to itself or to someone else.
For posterity, here is an implementation in c. It's been a while, so forgive the sloppiness. It is not the fastest, but it does pass all tests within the time limit. The disjoint set coding is straight from Wikipedia's pseudocode.
#include <stdio.h>
struct ds_node
{
struct ds_node *parent;
int rank;
};
struct ds_node v[25001];
void ds_makeSet(struct ds_node *x)
{
x->parent = x;
x->rank = 0;
}
struct ds_node* ds_find(struct ds_node *x)
{
if (x->parent != x) x->parent = ds_find(x->parent);
return x->parent;
}
int ds_union(struct ds_node *x, struct ds_node *y)
{
struct ds_node * xRoot;
struct ds_node * yRoot;
xRoot = ds_find(x);
yRoot = ds_find(y);
if (xRoot == yRoot) return 0;
if (xRoot->rank < yRoot->rank)
{
xRoot->parent = yRoot;
}
else if (xRoot->rank > yRoot->rank)
{
yRoot->parent = xRoot;
}
else
{
yRoot->parent = xRoot;
xRoot->rank++;
}
return 1;
}
int test(int n)
{
int i, e, z = 0;
for(i=1;i<=n;i++)
{
ds_makeSet(&v[i]);
}
for(i=1;i<=n;i++)
{
scanf("%d",&e);
if (e)
{
if ( !ds_union(&v[i],&v[e]) )
{
for(i++;i<=n;i++) scanf("%d",&e);
return 0;
}
}
else
{
z++;
}
}
return (z == 1);
}
int main()
{
int runs; int n;
scanf("%d", &runs);
while(runs--)
{
scanf("%d", &n);
getc(stdin);
test(n) ? puts("YES") : puts("NO");
}
}

Resources