Golang code too slow for Hackerrank - algorithm

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.

Related

How would one solve the staircase problem recursively with a variable number of steps?

The problem of determining the n amount of ways to climb a staircase given you can take 1 or 2 steps is well known with the Fibonacci sequencing solution being very clear. However how exactly could one solve this recursively if you also assume that you can take a variable M amount of steps?
I tried to make a quick mockup of this algorithm in typescript with
function counter(n: number, h: number){
console.log(`counter(n=${n},h=${h})`);
let sum = 0
if(h<1) return 0;
sum = 1
if (n>h) {
n = h;
}
if (n==h) {
sum = Math.pow(2, h-1)
console.log(`return sum=${sum}, pow(2,${h-1}) `)
return sum
}
for (let c = 1; c <= h; c++) {
console.log(`c=${c}`)
sum += counter(n, h-c);
console.log(`sum=${sum}`)
}
console.log(`return sum=${sum}`)
return sum;
}
let result = counter (2, 4);
console.log(`result=${result}`)
but unfortunately this doesn't seem to work for most cases where the height is not equal to the number of steps one could take.
I think this could be solved with recursive DP.
vector<vector<int>> dp2; //[stair count][number of jumps]
int stair(int c, int p) {
int& ret = dp2[c][p];
if (ret != -1) return ret; //If you've already done same search, return saved result
if (c == n) { //If you hit the last stair, return 1
return ret = 1;
}
int s1 = 0, s2 = 0;
if (p < m) { //If you can do more jumps, make recursive call
s1 = stair(c + 1, p + 1);
if (c + 2 <= n) { //+2 stairs can jump over the last stair. That shouldn't happen.
s2 = stair(c + 2, p + 1);
}
}
return ret = s1 + s2; //Final result will be addition of +1 stair methods and +2 methods
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> m; dp2 = vector<vector<int>>(n + 1, vector<int>(m + 1, -1));
for (int i = 1; i <= m; i++) {
dp2[n][i] = 1; //All last stair method count should be 1, because there is no more after.
}
cout << stair(0, 0) << "\n";
return 0;
}
Example IO 1
5 5
8
// 1 1 1 1 1
// 1 1 1 2
// 1 1 2 1
// 1 2 1 1
// 2 1 1 1
// 1 2 2
// 2 1 2
// 2 2 1
Example IO 2
5 4
7
// 1 1 1 2
// 1 1 2 1
// 1 2 1 1
// 2 1 1 1
// 1 2 2
// 2 1 2
// 2 2 1
Example IO 3
5 3
3
// 1 2 2
// 2 1 2
// 2 2 1

last iteration gets skipped and not printed in a for loop

Im trying to build a code that when the user inputs a sequence of numbers it will go through the sequence comparing each numbers and for every new biggest number in the sequence it will sum all the previous ones
func main() {
var numeri []int
numeri = GetInputSlice()
fmt.Println(numeri)
var sum int
num := len(numeri)
for i := 0; i < num - 1 ; i++ {
sum += numeri[i]
if numeri[i] > numeri[i+1] || numeri[i] == num - 1 {
fmt.Println(sum)
sum = 0
}
}
}
full code over here: https://go.dev/play/p/13ljQPmKaRA
if I input this sequence of numbers [1 2 13 0 7 8 9 -1 0 2] I would like to get 16, 24 and 1.
But in my code I only get 16 and 24 without getting the last 1 and I can't figure out a way to fix this.
Only numeri[i] is ever added to sum, and your loop never visits the last item (i < num - 1), so how could the last item be ever added?
Range through the whole slice, perform the addition, but only compare to the next element if you're not at the last one. If we're at the last one, we also want to print, so we may use a single condition
i == max || numeri[i] > numeri[i+1]
Where the comparison to the next element will not be executed if i == max (short circuit evaluation).
For example:
max := len(numeri) - 1
for i, v := range numeri {
sum += v
if i == max || v > numeri[i+1] {
fmt.Println(sum)
sum = 0
}
}
This will output (try it on the Go Playground):
[1 2 13 0 7 8 9 -1 0 2]
16
24
1

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");
}

Unable to find error sement tree : minimum in subarray

I am new to data structures and algo, and unable to find error in my code for the question
Range Minimum Query
Given an array A of size N, there are two types of queries on this array.
q l r: In this query you need to print the minimum in the sub-array A[l:r].
u x y: In this query you need to update A[x]=y.
Input: First line of the test case contains two integers, N and Q, size of array A and number of queries.
Second line contains N space separated integers, elements of A.
Next Q lines contain one of the two queries.
Output:
For each type 1 query, print the minimum element in the sub-array A[l:r].
Constraints:
1 ≤ N,Q,y ≤ 10^5
1 ≤ l,r,x≤N
#include<bits/stdc++.h>
using namespace std;
long a [100001];
//global array to store input
long tree[400004];
//global array to store tree
// FUNCTION TO BUILD SEGMENT TREE //////////
void build(long i,long start,long end) //i = tree node
{
if(start==end)
{
tree[i]=a[start];
return;
}
long mid=(start+end)/2;
build(i*2,start,mid);
build(i*2+1,mid+1,end);
tree[i] = min(tree[i*2] , tree[i*2+1]);
}
// FUNCTION TO UPDATE SEGMENT TREE //////////
void update (long i,long start,long end,long idx,long val)
//idx = index to be updated
// val = new value to be given at that index
{
if(start==end)
tree[i]=a[idx]=val;
else
{
int mid=(start+end)/2;
if(start <= idx and idx <= mid)
update(i*2,start,mid,idx,val);
else
update(i*2+1,mid+1,end,idx,val);
tree[i] = min(tree[i*2] , tree[i*2+1]);
}
}
// FUNCTION FOR QUERY
long query(long i,long start,long end,long l,long r)
{
if(start>r || end<l || start > end)
return INT_MAX;
else
if(start>=l && end<=r)
return tree[i];
long mid=(start+end)/2;
long ans1 = query(i*2,start,mid,l,r);
long ans2 = query(i*2+1,mid+1,end,l,r);
return min(ans1,ans2);
}
int main()
{
long n,q;
cin>>n>>q;
for(int i=0 ; i<n ; i++)
cin>>a[i];
//for(int i=1 ; i<2*n ; i++) cout<<tree[i]<<" "; cout<<endl;
build(1,0,n-1);
//for(int i=1 ; i<2*n ; i++) cout<<tree[i]<<" "; cout<<endl;
while(q--)
{
long l,r;
char ch;
cin>>ch>>l>>r;
if(ch=='q')
cout<<query(1,0,n-1,l-1,r-1)<<endl;
else
update(1,0,n-1,l,r);
}
return 0;
}
Example :input
5 15
1 5 2 4 3
q 1 5
q 1 3
q 3 5
q 1 5
q 1 2
q 2 4
q 4 5
u 3 1
u 3 100
u 3 6
q 1 5
q 1 5
q 1 2
q 2 4
q 4 5
Expected output:
1
1
2
1
1
2
3
1
1
1
4
3
It appears that all given values assume 1 based indexing: 1 ≤ l,r,x ≤ N
You chose to build your segment tree with 0 based indexing, so all queries and updates also should use same indexing.
So this part is wrong, because you need to set A[x]=y, and because you use 0 based indexing your code actually sets A[x+1]=y
update(1,0,n-1,l,r);
To fix change it to this:
update(1,0,n-1,l-1,r);

Partitioning a no. N into M partitions

I'm trying a problem in which I have to partition a no. N into M partitions as many as possible.
Example:
N=1 M=3 , break 1 into 3 parts
0 0 1
0 1 0
1 0 0
N=3 M=2 , break 3 into 2 parts
2 1
1 2
3 0
0 3
N=4 M=4 , break 4 into 4 parts
0 0 0 4
0 0 4 0
0 4 0 0
4 0 0 0
0 0 1 3
0 1 0 3
0 1 3 0
.
.
.
and so on.
I did code a backtrack algo. which produce all the possible compositions step by step, but it chokes for some larger input.Because many compositions are same differing only in ordering of parts.I want to reduce that.Can anybody help in providing a more efficient method.
My method:
void backt(int* part,int pos,int n) //break N into M parts
{
if(pos==M-1)
{
part[pos]=n;
ppart(part); //print part array
return;
}
if(n==0)
{
part[pos]=0;
backt(part,pos+1,0);
return;
}
for(int i=0;i<=n;i++)
{
part[pos]=i;
backt(part,pos+1,n-i);
}
}
In my algo. n is N and it fill the array part[] for every possible partition of N.
What I want to know is once generating a composition I want to calculate how many times that composition will occur with different ordering.For ex: for N=1 ,M=3 ::: composition is only one : <0,0,1> ,but it occurs 3 times. Thats what I want to know for every possible unique composition.
for another example: N=4 M=4
composition <0 0 0 4> is being repeated 4 times. Similarly, for every unique composition I wanna know exactly how many times it will occur .
Looks like I'm also getting it by explaining here.Thinking.
Thanks.
You can convert an int to a partitioning as follows:
vector<int> part(int i, int n, int m)
{
int r = n; // r is num items remaining to be allocated
vector<int> result(m, 0); // m entries inited to 0
for (int j = 0; j < m-1; j++)
{
if (r == 0) // if none left stop
break;
int k = i % r; // mod out next bucket
i /= r; // divide out bucket
result[j] = k; // assign bucket
r -= k; // remove assigned items from remaining
}
result[m-1] = r; // put remainder in last bucket
return result;
}
So you can use this as follows:
for (int i = 0; true; i++)
{
vector<int> p = part(i, 3, 4);
if (i != 0 && p.back() == 3) // last part
break;
... // use p
};
It should be clear from this how to make an incremental version of part too.
A much simpler and mathematical approach:
This problem is equivalent to finding the co-efficient of x^N in the expression f(x) = (1+x+x^2+x^3+....+x^N)^M
f(x) = ((x^(N-1) - 1)/(x-1))^M
differentiate it M times(d^Nf(x)/dx^N) and the co-efficient will be (1/n!)*(d^Nf(x)/dx^N) at x = 0;
differentiation can be done using any numerical differentiation technique. So the complexity of the algorithm is O(N*complexity_of_differentiation)..

Resources