Resetting an array of numbers by repeated subtraction from a sub-array - algorithm

There is an array of numbers between 0 and 6 (base 7). For example {0 4 6 2 2 0 3 1}. Its maximum length can be 501 elements.
Each step we can subtract a number from any number of elements. All of the elements must be adjacent (form a continuous sub-array). The number subtracted from all of the elements must be the same.
If an element (let's call it A) after subtraction doesn't fit in the range of 0 to 6, then A becomes A modulo 7. For example after subtracting 3 from the whole array {0 4 6 2 2 0 3 1}, we would get
{4 1 3 6 6 4 0 5}.
The task is to find the smallest amount of steps necessary to get an array with just zeros.
For example for the array {0 4 6 2 2 0 3 1} it would take 4 steps:
{0 4 6 2 2 0 3 1} subtract 2 from elements with indexes 2-4
{0 4 4 0 0 0 3 1} subtract 4 from elements with indexes 1 and 2
{0 0 0 0 0 0 3 1} subtract 3 from the second to last element
{0 0 0 0 0 0 0 1} subtract 1 from the last element
{0 0 0 0 0 0 0 0}
First of all finding the solution using brute force is not possible, as for an array of 501 numbers
there are 126 505 506 possible first steps.
(6x(1x501 + 2x500 + 3x499 + 4x498 +...+ 501x1) = 6x21084251 = 126505506).
There would be a lot more possibilities if we include the steps following the first one.
I noticed we can remove an element if it has the same number next to it.
So the array {0 4 6 2 2 0 3 1} becomes {0 4 6 2 0 3 1}. This should simplify the problem.
I've tried dividing the array into sections using zeros as the dividers.
So for the array {0 4 6 2 0 3 1} we could consider two separate arrays: {4 6 2} and {3 1}.
I thought I could find the answers for those arrays and add them together for the final answer.
But I discovered arrays for which this approach doesn't work.
For example, for the array {3 2 1 0 1 2 3} this approach would yield the answer 3 + 3 = 6 while it should be 4 steps:
{3 2 1 0 1 2 3} subtract 3 from the whole array
{0 6 5 4 5 6 0}subtract 6 for indexes 1 to 5
{0 0 6 5 6 0 0} subtract 6 for indexes 2 to 4
{0 0 0 6 0 0 0} subtract 6 from the middle element
{0 0 0 0 0 0 0}
Another approach I tried was looking for pairs of the same number and dividing the array accordingly.
For example the array: {0 3 1 5 3 5 6 2 1 5 1}
would divide into three arrays {3 1 5 3} and {5 6 2 1 5} and {6}.
This would allow me to shorten a sub-array by two elements in just one step:
{3 1 5 3} {5 6 2 1 5} {6} subtract from the first subarray
{0 5 2 0} {5 6 2 1 5} {6} subtract from the second subarray
{0 5 2 0} {0 1 4 3 0} {6} remove zeroes on the sides -> {5 2} {1 4 3} {6}
But I couldn't find a final solution using this approach. Also I don't know how to check whether it always would return the best answer.

Related

How to find the count of the maximum pair of a window

Today I got an interview question about finding the maximum pair window but I felt like I could solve it more efficient. I was wondering if theres any way to solve it more efficiently.
Input: nums = [1,3,-1,-3,5,3,6,7], k = 3, n = 7
Output: 3
Explanation:
Window position Max
--------------- -----
[1 3 -1] -3 5 3 6 7 4 (1,3) < 7 false
1 [3 -1 -3] 5 3 6 7 2 (3, -1) < 7 false
1 3 [-1 -3 5] 3 6 7 4 (5, -1) < 7 false
1 3 -1 [-3 5 3] 6 7 8 (5,3) > 7 true
1 3 -1 -3 [5 3 6] 7 11 (6,5) > 7 true
1 3 -1 -3 5 [3 6 7] 13 (6,7) > 7 true
just solved it by getting the subarray -> sorting then getting the last 2 element but I think theres a more efficient solution?

Sortperm for matrix sorting in Julia lang

I am using Julia 1.6.1.
B is a matrix. For example,
B =
[ 2 4 4 4 5 ;
1 2 2 3 5 ;
1 2 3 3 3 ;
1 2 2 5 6 ;
1 3 4 4 4 ; ]
I wanted to sort it forcsing on each row.
sortedB = sortslices( B, dims=1, rev=true)
Then, we get sorted B
sortedB =
[ 2 4 4 4 5 ; # 1st row of the original matrix B
1 3 4 4 4 ; # 5th row of the original matrix B
1 2 3 3 3 ; # 3rd row of the original matrix B
1 2 2 5 6 ; # 4th row of the original matrix B
1 2 2 3 5 ;] # 2nd row of the original matrix B
I would like to get the array [1 5 3 4 2].
How can I do that ?
It seems that sortperm does not work.
sortperm( sortslices( B, dims=1, rev=true) )
# ERROR: MethodError; no method matching sortperm(::Matrix{Int64})
If performance is an issue use a non-allocating version.
julia> sortperm(view.(Ref(B), 1:size(B,1), :), rev=true)
5-element Vector{Int64}:
1
5
3
4
2
Here are some benchmarks using BenchmarkTools:
julia> #btime sortperm(view.(Ref($B), 1:size($B,1), :),rev=true);
376.471 ns (3 allocations: 432 bytes)
julia> #btime sortperm(collect(eachslice($B,dims=1)),rev=true)
642.683 ns (6 allocations: 496 bytes);
you can use eachrow or eachslice:
julia> C = collect(eachslice(B,dims=1))
5-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Int64, Base.Slice{Base.OneTo{Int64}}}, true}}:
[2, 4, 4, 4, 5]
[1, 2, 2, 3, 5]
[1, 2, 3, 3, 3]
[1, 2, 2, 5, 6]
[1, 3, 4, 4, 4]
julia> sortperm(C,rev=true)
5-element Vector{Int64}:
1
5
3
4
2
although this will allocate more than necessary (collect is needed apparently)

Confused about the depth-first-search result when using Golang

I tried to solve the 'Combination Sum' on leetcode, and the result is wrong when using test case:
[7,3,2] 18
I used C++ with the same logic and passed, but when using Golang, my result is:
[[2,2,2,2,2,2,2,2,2],[2,2,2,2,2,7,3,3],[2,2,2,2,3,7],[2,2,2,3,3,3,3],[2,2,7,7],[2,3,3,3,7],[3,3,3,3,3,3]]
and the correct one should be
[[2,2,2,2,2,2,2,2,2],[2,2,2,2,2,2,3,3],[2,2,2,2,3,7],[2,2,2,3,3,3,3],[2,2,7,7],[2,3,3,3,7],[3,3,3,3,3,3]]
the code is shown below:
import "sort"
func combinationSum(candidates []int, target int) [][]int {
result := make([][]int, 0, 0)
resultp := &result
sort.Ints(candidates)
helper(candidates, 0, target, make([]int, 0, 0), resultp, len(candidates))
return *resultp
}
func helper(nums []int, index int, target int, list []int, resultp *[][]int, length int) {
if target == 0 {
*resultp = append(*resultp, list)
return
}
for i := index; i < length; i++ {
if i != index && nums[i] == nums[i - 1] {
continue
}
if (nums[i] > target) {
break
}
helper(nums, i, target - nums[i], append(list, nums[i]), resultp, length)
}
}
Can anyone tell me why the result is incorrect, I am just confused about the [2,2,2,2,2,7,3,3] in my answer, why the 7 is before the 3 since the array has been sorted? Or anyone can tell me what mistake I have made in my code
append function may or may not modify the underlying array that your slice refers to. So you are not creating a completely new list when using append. I changed helper to match your desired behavior.
for i := index; i < length; i++ {
if i != index && nums[i] == nums[i - 1] {
continue
}
if nums[i] > target {
break
}
var newList []int
newList = append(newList, list...)
newList = append(newList, nums[i])
helper(nums, i, target - nums[i], newList, resultp, length)
}
If list has capacity, then it will be modified and therefore you are modifying your argument. Instead make a copy of list, and then append nums[i] to it.
See Go Slices: usage and internals
The line
helper(nums, i, target - nums[i], append(list, nums[i]), resultp, length)
may not perform as expected. It is called within the loop, and you are probably assuming that in the each iteration the append will always add the new member to the existing slice. If has more complex behavior that you seem not caring about enough:
If the new value fits into the current capacity of the backing array withing the slice, it is added to the current backing array. All variables assigned to that slice now report the updated content with the added new value present.
If the value does not fit, a new array is allocated. In this case further modifications of the returned slice will not change the content of the initial slice if that old value is also retained.
I am under impression that you may not expect value/content disagreement between the value returned by append and the parameter list you pass to it.
This behavior is described here (scroll to "gotcha").
So you can see the behavior a bit better by adding some print output:
https://play.golang.org/p/JPmqoAJE4S
Importantly, you can see it at this point:
0694 helper [2 3 7] 1 1 [2 2 2 2 2 2 2 3] [[2 2 2 2 2 2 2 2 2]] 3
4425 calling down 1 6 [2 2 2 2 2 2] 3
8511 helper [2 3 7] 1 3 [2 2 2 2 2 2 3] [[2 2 2 2 2 2 2 2 2]] 3
8511 calling down 1 3 [2 2 2 2 2 2 3] 3
8162 helper [2 3 7] 1 0 [2 2 2 2 2 2 3 3] [[2 2 2 2 2 2 2 2 2]] 3
8162 solution [2 2 2 2 2 2 3 3] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 2 3 3]]
1318 calling down 1 8 [2 2 2 2 2] 3
5089 helper [2 3 7] 1 5 [2 2 2 2 2 3] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 3 3 3]] 3
5089 calling down 1 5 [2 2 2 2 2 3] 3
4728 helper [2 3 7] 1 2 [2 2 2 2 2 3 3] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 3 3 3]] 3
1318 calling down 2 8 [2 2 2 2 2] 7
3274 helper [2 3 7] 2 1 [2 2 2 2 2 7] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 7 3 3]] 3
This is the sequence of actions:
You recursively call with [2 2 2 2 2 2 3] and append 3. You find that this is a valid solution and add [2 2 2 2 2 2 3 3] to the result slice.
You return up a few levels until you're back to [2 2 2 2 2] (before adding the 6th 2) and start trying to add 3s. You recursively call with [2 2 2 2 2] and append 3. Unfortunately, this overwrites your existing solution [2 2 2 2 2 2 3 3]. Since it's using the same backing array, you append 3 to the first 5 items in that slice, overwriting the 6th index in the slice you previously added to your solution set. Your second solution becomes [2 2 2 2 2 3 3 3] (note the 3 in the 6th slot)
You find that this solution set isn't going to work after a couple iterations (at [2 2 2 2 2 3 3]) because the remaining target (2) is less than the last number added (3), so you return up.
You repeat this sequence with a 7 in the 6th slot, overwriting the underlying array index again. Your second solution becomes [2 2 2 2 2 7 3 3], because you're still using the same underlying array. You find this solution also won't work, and return up.
After this point, you return up to before the list slice was greater than 4 in length (which is when the slice grew, by default it grows by doubling in size), meaning you're using a different (previous) backing array, which is why further iterations do not further change the existing solutions. By luck, none of the remaining solutions collide in a similar fashion.
This alternative print version shows you where the backing array changes (by showing where the address of the first entry changes): https://play.golang.org/p/nrgtMyqwow. As you can see, it changes when you grow beyond lengths 2, 4, and 8, but as you return upwards, you end up reverting back to different backing arrays.
The easiest solution to fix your specific problem is to copy the list slice before adding it to the solution set:
if target == 0 {
sol := make([]int, len(list))
copy(sol, list)
*resultp = append(*resultp, sol)
return
}
https://play.golang.org/p/3qTKoAumj0
[[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 2 3 3] [2 2 2 2 3 7] [2 2 2 3 3 3 3] [2 2 7 7] [2 3 3 3 7] [3 3 3 3 3 3]]

How to compute all unique permutations and keep the same positive adjacent elements always adjacent?

I have a list or a vector V of n nonnegative integers. There are some positive integers that are equal and adjacent, say V=[2, 3, 3, 0, 0]. (I do not care about the zero integer.)
I would like to find all unique permutations of V such that all the same and positive integers remain adjacent. How to write an algorithm for this? (For an implementation, you can choose Python or Matlab or any other language.)
Under Matlab and for the example of V=[2, 3, 3, 0, 0], I get all the unique permuations as follows:
V = [2, 3, 3, 0, 0];
unique(perms([2, 3, 3, 0, 0]), 'rows')
and I get:
0 0 2 3 3
0 0 3 2 3
0 0 3 3 2
0 2 0 3 3
0 2 3 0 3
0 2 3 3 0
0 3 0 2 3
0 3 0 3 2
0 3 2 0 3
0 3 2 3 0
0 3 3 0 2
0 3 3 2 0
2 0 0 3 3
2 0 3 0 3
2 0 3 3 0
2 3 0 0 3
2 3 0 3 0
2 3 3 0 0
3 0 0 2 3
3 0 0 3 2
3 0 2 0 3
3 0 2 3 0
3 0 3 0 2
3 0 3 2 0
3 2 0 0 3
3 2 0 3 0
3 2 3 0 0
3 3 0 0 2
3 3 0 2 0
3 3 2 0 0
As you may know, I get 30 such permutations. Among these 30, there are 18 that do not respect the constraint of adjacency. For example, [3, 2, 3, 0, 0] can not be in the final result because 3 is no longer adjacent to 3. Finally, all unique permutations can be given by:
0 0 2 3 3
0 0 3 3 2
0 2 0 3 3
0 2 3 3 0
0 3 3 0 2
0 3 3 2 0
2 0 0 3 3
2 0 3 3 0
2 3 3 0 0
3 3 0 0 2
3 3 0 2 0
3 3 2 0 0
The first idea (and the simplest) that came to my mind is to generate all unique permutations like so and then, for each one, verify the constraint. But is there any other efficient algorithm?
We can first compress the given array so that there is just one entry for every positive number, while keeping a count of how many times each number occurred (the zeroes should be left as is).
Generate the permutations of the compressed array.
Decompress each of the permutation and retain only the unique ones.
To Compress
def compress(arr):
counts = {}
compressed = []
curr_ele = arr[0]
count_ele = 0
for ele in arr:
if ele != curr_ele or ele == 0:
counts[curr_ele] = count_ele
compressed.append(curr_ele)
count_ele = 1
curr_ele = ele
else:
count_ele += 1
counts[curr_ele] = count_ele
compressed.append(curr_ele)
return compressed, counts
To Uncompress
def uncompress(arr, counts):
res = []
for ele in arr:
if ele == 0:
res.append(0)
continue
num_reps = counts[ele]
for _ in range(num_reps):
res.append(ele)
return res
Putting it together: Compress, Permute, Uncompress and Retain Unique
import itertools
ip = [2, 3, 3, 0, 0]
ip_compressed, counts = compress(ip)
set([tuple(uncompress(perm, counts)) for perm in itertools.permutations(ip_compressed)])
Result:
{(0, 0, 2, 3, 3),
(0, 0, 3, 3, 2),
(0, 2, 0, 3, 3),
(0, 2, 3, 3, 0),
(0, 3, 3, 0, 2),
(0, 3, 3, 2, 0),
(2, 0, 0, 3, 3),
(2, 0, 3, 3, 0),
(2, 3, 3, 0, 0),
(3, 3, 0, 0, 2),
(3, 3, 0, 2, 0),
(3, 3, 2, 0, 0)}
A simple algorithm is:
1.traverse the initial table and make another table with two rows like:
input: V = [2, 3, 3, 0, 0];
new array: V2 = |2,3,0|
|1,2,2|
As you can see V2 comes from V keeping one time the elements and in second row counting how many times we have seen them.
Now generate all permutations of columns
And for every result e.g:
V2 = |3,2,0|
|2,1,2|
you have kept how many times the elements appear.

How sort this list in netlogo

I am trying to order the following list in netoglo:
[[0.1 [1 2 5 3 1]] [0.3 [1 2 1 3 1]] [0.2 [1 2 1 3 1]]]
Actually they are list lists and what I want is to sort by the first element of each sublist:
When I use sort [[0.1 [1 2 5 3 1]] [0.3 [1 2 1 3 1]] [0.2 [1 2 1 3 1]]]
It returns empty I suppose because it only sees lists and not anything so I sort.
Any ideas.
Thanks to alan the answer was show sort-by [first ?1 > first ?2][[0.1 [1 2 5 3 1]] [0.3 [1 2 1 3 1]] [0.2 [1 2 1 3 1]]]

Resources