Function for copying arrays in Go language - arrays

Is there any built-in function in Go for copying one array to another?
Will this work in case of two (or more) dimensional arrays?

Is there any built-in function in Go language for copying one array to another?
Yes: http://play.golang.org/p/_lYNw9SXN5
a := []string{
"hello",
"world",
}
b := []string{
"goodbye",
"world",
}
copy(a, b)
// a == []string{"goodbye", "world"}
Will this work in case of two (or more) dimensional arrays?
copy will do a shallow copy of the rows: http://play.golang.org/p/0gPk6P1VWh
a := make([][]string, 10)
b := make([][]string, 10)
for i := range b {
b[i] = make([]string, 10)
for j := range b[i] {
b[i][j] = strconv.Itoa(i + j)
}
}
copy(a, b)
// a and b look the same
b[1] = []string{"some", "new", "data"}
// b's second row is different; a still looks the same
b[0][0] = "apple"
// now a looks different
I don't think there's a built-in for doing deep-copys of multi-dimensional arrays: you can do it manually like: http://play.golang.org/p/nlVJq-ehzC
a := make([][]string, 10)
b := make([][]string, 10)
for i := range b {
b[i] = make([]string, 10)
for j := range b[i] {
b[i][j] = strconv.Itoa(i + j)
}
}
// manual deep copy
for i := range b {
a[i] = make([]string, len(b[i]))
copy(a[i], b[i])
}
b[0][0] = "apple"
// a still looks the same
edit: As pointed out in the comments, I assumed by "copy an array" you meant "do a deep copy of a slice", as arrays can be deep-copied with the = operator as per jnml's answer (because arrays are value types): http://play.golang.org/p/8EuFqXnqPB

The primary "function" for copying an array in Go is the assignment operator =, as it is the case for any other value of any other type.
package main
import "fmt"
func main() {
var a, b [4]int
a[2] = 42
b = a
fmt.Println(a, b)
// 2D array
var c, d [3][5]int
c[1][2] = 314
d = c
fmt.Println(c)
fmt.Println(d)
}
Playground
Output:
[0 0 42 0] [0 0 42 0]
[[0 0 0 0 0] [0 0 314 0 0] [0 0 0 0 0]]
[[0 0 0 0 0] [0 0 314 0 0] [0 0 0 0 0]]

Use copy http://play.golang.org/p/t7P6IliMOK
a := []int{1, 2, 3}
var b [3]int
fmt.Println("A:", a)
fmt.Println("B:", b)
copy(b[:], a)
fmt.Println("A:", a)
fmt.Println("B2:", b)
b[1] = 9
fmt.Println("A:", a)
fmt.Println("B3:", b)
OUT:
A: [1 2 3]
B: [0 0 0]
A: [1 2 3]
B2: [1 2 3]
A: [1 2 3]
B3: [1 9 3]

Related

Minimum number of operations to make two arrays equal

Given 2 arrays of integers, A and B, an operation on array B is defined as follows:
B[i] = B[i]+2 and B[j] = B[j]-2, where i != j
i and j can be any indices and the above operation can be performed
any number of times such that i and j are not equal
a valid operation consists of both the addition and subtraction steps, both parts are mandatory
The array is considered equal if the frequency of all the elements is same, the array need not be ordered, find the minimum operations required
Input:
A = [ 2, 10, 14 ]
B = [ 6, 2, 18 ]
Output: 2
Explanation :
1st operation: select i=0; j=2;
B[i] += 2 i.e B[0]=8;
B[j] -= 2 i.e B[2] = 16;
B after 1st operation [8,2,16]
2nd operation: select i=0; j=2;
B[i] += 2 i.e B[0]=10;
B[j] -= 2 i.e B[2] = 14;
B after 2nd operation [10,2,14]
Order doesnt matter, so we have made the arrays equal return 2;
I am unable get an approach to solve this and couldn't find any similar questions, so posting this here, thanks in advance.
Assuming the arrays are solvable, then sort the arrays (by parity, and then by value), add up the absolute value of the deltas and divide by 4.
E.g.
A = [ 2, 10, 14 ], already sorted
B = [ 6, 2, 18 ], sorted becomes [2, 6, 18]
Sum of absolute value of deltas = 0 + 4 + 4 = 8. 8/4 = 2 so 2 moves.
A = [2, 10, 14]( % 2 == 0)
B = [2, 6, 18]( % 2 == 0)
another example
A = [1, 2, 5] -> [1, 5]( % 2 == 1) & [2]( % 2 == 0)
B = [1, 3, 4] -> [1, 3]( % 2 == 1) & [4]( % 2 == 0)
Notice that (a + k) mod k == a.
Assuming we already have a sorted array.
We divide the array into k parts, according to the mod k value of the element, then we sum all absolute differences, it's four times the answer.
k = 2
A.sort(key=lambda x: x % k)
B.sort(key=lambda x: x % k)
result = 0
n = len(A)
for i in range(n):
result += abs(A[i] - B[i])
print(result >> 2)
# A = [1, 2, 5]
# B = [1, 3, 4]
# result = 1
# A = [2, 10, 14]
# B = [6, 2, 18]
# result = 2
O(N log N) because of sorting.

Ruby Increment array from certain starting point

I feel this is a super simple query but I'm having a real tough time with immutable nums in my arrays.
I'd like to have a super simple method, which increments numbers in an array by distributing them from the max value.
eg [1,3,5,1] becomes [1,3,0,1] and then iterates upwards and back through to create [2,4,1,3]
what I currently have is the following
arr = [1,3,5,1]
with a method of
def increment_from_max_value(arr)
max = arr.max
max_index = arr.index(max)
arr[max_index] = 0
while max >= 0
arr[max_index..-1].each do |element|
element = element += 1
max = max -= 1
end
end
end
Currently the array isn't even updating and just returns the original values. Which I believe is due to the immutability of FixNums in Ruby, but with a method like map!, which is able to modify those values, I can't get it to loop back through from a certain starting point like each will.
Many thanks in advance
I'd use divmod to calculate the increase for each element and the leftover.
For a max value of 5 and array size of 4 you'd get:
5.divmod(4) #=> [1, 1]
i.e. each element has to incremented by 1 (first value) and 1 element (second value) has to be incremented by another 1.
Another example for a max value of 23 and 4 elements:
[1, 3, 23, 1]
23.divmod(4) #=> [5, 3]
each element has to be incremented by 5 and 3 elements have to be incremented by another 1:
[ 1, 3, 23, 1]
# +5 +5 +5 +5
# +1 +1 +1
# = [ 7, 9, 5, 7]
Applied to your method:
def increment_from_max_value(arr)
max = arr.max
max_index = arr.index(max)
arr[max_index] = 0
q, r = max.divmod(arr.size)
arr.each_index { |j| arr[j] += q }
r.times { |j| arr[(max_index + j + 1) % arr.size] += 1 }
end
arr.each_index { |j| arr[j] += q } simply adds q to each element.
r.times { |j| arr[(max_index + j + 1) % arr.size] += 1 } is a little more complicated. It distributes the remainder, starting from 1 after max_index. The modulo operation ensures that the index will wrap around:
0 % 4 #=> 0
1 % 4 #=> 1
2 % 4 #=> 2
3 % 4 #=> 3
4 % 4 #=> 0
5 % 4 #=> 1
6 % 4 #=> 2
# ...
I think there is something wrong with the while loop. I did not investigate but you can see that this line arr[max_index] = 0 mutates the array.
I don't know if I've understood the logic, but this should return the desired output:
def increment_from_max_value(arr)
max = arr.max
arr[arr.index(max)] = 0
indexes = (0...arr.size).to_a.reverse
max.times do
arr[indexes.first] += 1
indexes.rotate!
end
end
The value of the block variable element in arr[max_index..-1].each do |element| is changed by element = element += 1 but that has no effect on arr.
You could achieve your objective as follows.
def increment_from_max_value(arr)
mx, mx_idx = arr.each_with_index.max_by(&:first)
sz = arr.size
arr[mx_idx] = 0
arr.rotate!(mx_idx + 1).map!.with_index do |e,i|
begin_nbr = mx - i
e += (begin_nbr <= 0 ? 0 : 1 + ((begin_nbr - 1)/sz))
end.rotate!(-mx_idx - 1)
end
arr = [1,3,5,1]
increment_from_max_value(arr)
arr
#=> [2, 4, 1, 3]
arr = [1,2,3,2,1]
increment_from_max_value(arr)
arr
#=> [2, 2, 0, 3, 2]
After computing the maximum value of arr, mx, and its index, mx_idx, and setting arr[mx_idx] to zero, I rotate the array (counter-clockwise) by mx_idx + 1, making the position of mx last. That way the "allocations" of mx begin with the first element of the rotated array. After performing the allocations I then rotate the array clockwise by the same mx_idx + 1.
begin_nbr equals mx minus the number of indices that precede i; in effect, the portion of mx that remains "unallocated" at index i in the first round of allocations.
I can best explain how this works by salting the method with puts statements.
def increment_from_max_value(arr)
mx, mx_idx = arr.each_with_index.max_by(&:first)
sz = arr.size
puts "mx = #{mx}, mx_idx = #{mx_idx}, sz = #{sz}"
arr[mx_idx] = 0
arr.rotate!(mx_idx + 1).
tap { |a| puts "arr rotated to make mx position last = #{a}" }.
map!.with_index do |e,i|
begin_nbr = mx - i
puts "e before = #{e}, i = #{i}, begin_nbr = #{begin_nbr}"
e += (begin_nbr <= 0 ? 0 : 1 + ((begin_nbr - 1)/sz))
e.tap { |f| puts "e after change = #{f}" }
end.
tap { |a| puts "arr after changes = #{a}" }.
rotate!(-mx_idx - 1).
tap { |a| puts "arr after rotating back = #{a}" }
end
arr = [1,3,5,1]
increment_from_max_value(arr)
mx = 5, mx_idx = 2, sz = 4
arr rotated to make mx position last = [1, 1, 3, 0]
e before = 1, i = 0, begin_nbr = 5
e after change = 3
e before = 1, i = 1, begin_nbr = 4
e after change = 2
e before = 3, i = 2, begin_nbr = 3
e after change = 4
e before = 0, i = 3, begin_nbr = 2
e after change = 1
arr after changes = [3, 2, 4, 1]
arr after rotating back = [2, 4, 1, 3]
#=> [2, 4, 1, 3]

some question about append built-in function

package main
import (
"fmt"
)
func main() {
result := subsets([]int{9,3,0,1,2})
fmt.Println(result)
}
func subsets(nums []int) [][]int {
result := [][]int{}
var fun func([]int, int)
fun = func (preSets []int, start int) {
// fmt.Println(start, preSets, result)
result = append(result, preSets)
// fmt.Println(result)
for idx := start; idx < len(nums); idx++ {
tmp := nums[idx]
newSet := append(preSets, tmp)
fun(newSet, idx+1)
newSet = newSet[:len(newSet) - 1]
}
}
fun([]int{}, 0)
return result
}
i want to find the subsets of a slice, and think the code above should work. but it give me the following output
[[] [9] [9 3] [9 3 0] [9 3 0 2] [9 3 0 1 2] [9 3 0 2] [9 3 1] [9 3 1 2] [9 3 2] [9 0] [9 0 1] [9 0 1 2] [9 0 2] [9 1] [9 1 2] [9 2] [3] [3 0] [3 0 1] [3 0 1 2] [3 0 2] [3 1] [3 1 2] [3 2] [0] [0 1] [0 1 2] [0 2] [1] [1 2] [2]]
the fifth slice should be [9 3 0 1], but it is [9 3 0 2],and i print the result each step, i found out that the fifth slice turned from [9301] to [9302] when the seventh slice [9302] is appended,i think it should be related to the array storage under the slice, but why
i think [the problem is] related to the array storage under the slice
Yes, it is.
but why
The append function:
sometimes re-uses the original backing array, but
sometimes creates a new backing array and copies the original values to the new array.
There are no promises made about when it does one of these two.
When it re-uses the original array, you encounter the behavior you dislike. When it makes a new array, you encounter the behavior you desire. Since you want the copy behavior, you can simply write your own "always copy" code and get the behavior you want. However, a more-minimal change is to replace:
result = append(result, preSets)
with:
result = append(result, unshare(preSets))
with the function unshared defined as:
func unshare(a []int) []int {
tmp := make([]int, len(a))
copy(tmp, a)
return tmp
}
If you are trying to explain to yourself exactly why you got the exact result that you got, it's a little tricky because you're not promised anything about when append makes a new backing array and when it re-uses the existing backing array—but it is explainable, if you make the following two assumptions:
append never makes a copy of the backing array if it does not have to; and
when append does make a copy, it sometimes over-allocates the new backing array by some factor.
That is, append behaves more or less like this, except of course this one is specific to []int:
func xappend(orig []int, add []int) []int {
has := len(orig)
needed := has + len(add)
// If we can fit the added elements in, do that now.
if cap(orig) >= needed {
fmt.Println("copy in place")
orig = orig[:needed]
copy(orig[has:needed], add)
return orig
}
newSize := undocumentedFunction(has, cap(orig), needed)
fmt.Println("make new, size", newSize)
new := make([]int, needed, newSize)
copy(new, orig)
copy(new[has:needed], add)
return new
}
func undocumentedFunction(oldCap, oldLen, newCap int) int {
twiceAsMuch := oldCap + oldCap
if newCap > twiceAsMuch {
return newCap
}
// 2x old capacity is enough, but
// we'll tweak this in various ways.
// The exact tweaks might change at any time.
if oldLen < 1024 {
return twiceAsMuch
}
panic("didn't copy this part")
}
This "undocumented function" is part of the runtime system, and it collaborates with the compiler. You can see its actual code here (note: this link may break or go to the wrong line at some point).
(Sample runnable code here on the Go Playground.)

Go slice element replaced by last element

My problem is the answer should has [1 1 2 2], but it got [1 1 2 3].
I debuged this code, found that in that loop, [1 1 2 2] was appended to the array firstly, but it changed to [1 1 2 3] in next loop.
I don't understand why, the log which started with 'D', the elements in this array changed in next loop.
Here is my code:
https://play.golang.org/p/X_CU8GlMOqf
package main
import (
"fmt"
)
func main() {
nums := []int{1, 1, 2, 2, 3}
result := subsetsWithDup(nums)
fmt.Println(result)
}
func subsetsWithDup(nums []int) [][]int {
result := [][]int{{}, nums}
for i := 0; i < len(nums); i++ {
if i > 0 && nums[i] == nums[i-1] {
continue
}
for j := 1; j < len(nums); j++ {
result = append(result, dsf(nums, []int{nums[i]}, i+1, j)...)
}
}
return result
}
func dsf(nums []int, set []int, start int, length int) [][]int {
result := [][]int{}
if len(set) == length {
return append(result, set)
}
for i := start; i < len(nums); i++ {
if i != start && nums[i] == nums[i-1] {
continue
}
if len(set) == 3 {
fmt.Printf("A %v %p\n", result, &result)
}
tmp := set[:]
tmp = append(tmp, nums[i])
if len(set) == 3 {
fmt.Printf("B %v %p %v %p\n", tmp, &tmp, result, &result)
}
result = append(result, dsf(nums, tmp, i+1, length)...)
if len(tmp) == 4 {
fmt.Printf("C %v %p %v %p\n", tmp, &tmp, result, &result)
for _, r := range result {
fmt.Printf("D %v %p\n", r, &r)
}
}
}
return result
}
A [] 0xc000004960
B [1 1 2 2] 0xc0000049c0 [] 0xc000004960
C [1 1 2 2] 0xc0000049c0 [[1 1 2 2]] 0xc000004960
D [1 1 2 2] 0xc000004ae0
A [[1 1 2 2]] 0xc000004960
B [1 1 2 3] 0xc000004b60 [[1 1 2 3]] 0xc000004960
C [1 1 2 3] 0xc000004b60 [[1 1 2 3] [1 1 2 3]] 0xc000004960
D [1 1 2 3] 0xc000004ca0
D [1 1 2 3] 0xc000004ca0
A [] 0xc000004da0
B [1 2 2 3] 0xc000004de0 [] 0xc000004da0
C [1 2 2 3] 0xc000004de0 [[1 2 2 3]] 0xc000004da0
D [1 2 2 3] 0xc000004f00
You are trying to copy a slice with:
tmp := set[:]
This does not copy the slice, it re-uses the original slice. It has the same effect as tmp := set. You can use:
tmp := append([]int(nil), set...)
if you like. Here is your program with this change, and all the extra debug commented out.

How do I account for an array that doesn't exist?

So the code works fine if I'm trying to find the size of the land in the middle, but it fails when calculating the size of the small land in the corner. How do I return 0 if it starts checking for land outside of the given arrays?
M = 'land'
o = 'water'
world = [[o,o,o,o,o,o],
[o,M,M,M,o,o],
[o,o,M,M,o,o],
[o,o,o,o,o,M]]
def continent_size world, x, y
if world[x][y] != 'land'
return 0
end
size = 1
world[x][y] = 'counted land'
size = size + continent_size(world, x-1, y-1)
size = size + continent_size(world, x , y-1)
size = size + continent_size(world, x+1, y-1)
size = size + continent_size(world, x-1, y )
size = size + continent_size(world, x+1, y )
size = size + continent_size(world, x-1, y+1)
size = size + continent_size(world, x , y+1)
size = size + continent_size(world, x+1, y+1)
size
end
puts continent_size(world, 3, 5)
How about some guard clauses at the top of your method like:
# make sure we don't attempt to index into an array at less than zero
return 0 if x < 0
return 0 if y < 0
# make sure there is a value in the requested slot
return 0 unless world[x]
return 0 unless world[x][y]
def continent_size(world, row, col)
rows = ([row-1, 0].max..[row+1, world.size-1].min).to_a
cols = ([col-1,0].max..[col+1, world.first.size-1].min).to_a
rows.product(cols).count { |r,c| world[r][c] == M }
end
world.size.times { |r| world.first.size.times { |c|
puts "[#{r},#{c}] -> #{continent_size(world, r, c)}" } }
[0,0] -> 1
[0,1] -> 2
[0,2] -> 3
[0,3] -> 2
[0,4] -> 1
[0,5] -> 0
[1,0] -> 1
[1,1] -> 3
[1,2] -> 5
[1,3] -> 4
[1,4] -> 2
[1,5] -> 0
[2,0] -> 1
[2,1] -> 3
[2,2] -> 5
[2,3] -> 4
[2,4] -> 3
[2,5] -> 1
[3,0] -> 0
[3,1] -> 1
[3,2] -> 2
[3,3] -> 2
[3,4] -> 2
[3,5] -> 1
For
row = 0
col = 3
the steps are as follows. (Note world_size #=> 4 and world.first.size #=> 6.)
rows = ([row-1, 0].max..[row+1, world.size-1].min).to_a
#=> ([-1,0].max..[1,3].min).to_a
#=> (0..1).to_a
#=> [0, 1]
cols = ([col-1,0].max..[col+1,world[0].size-1].min).to_a
#=> ([2,0].max..[4,5].min).to_a
#=> (2..4).to_a
#=> [2,3,4]
a = rows.product(cols)
#=> [[0, 2], [0, 3], [0, 4], [1, 2], [1, 3], [1, 4]]
a.count { |r,c| world[r][c] == M }
#=> 2

Resources