Gridland Provinces – HackerRank Solution

In this post, we will solve Gridland Provinces HackerRank Solution. This problem (Gridland Provinces) is a part of HackerRank Problem Solving series.

Solution – Gridland Provinces – HackerRank Solution

C++

#include <cmath>
#include <cstdio>
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
#include <fstream>
#include <functional>
#include <string>
#include <cstring>
#include <cstdint>
using namespace std;

int gNPaths = 0;
const unsigned int kHashSize = 4096*16;
vector< set<unsigned int> > gHashTab;
size_t gN  = 0;
size_t gNx  = 0;

inline void checkThis(const char *knightPath, const unsigned int hashp = 0){
    auto hashx = (hashp)? hashp : std::_Hash_impl::hash(knightPath, gNx, 11); 
    auto hashy = std::_Hash_impl::hash(knightPath+gNx, gNx, 11); 
    auto hash2 = hashx^(hashy<<1); 
    auto hash  = hashx%kHashSize;
    if(gHashTab[hash].size()==0){
        gHashTab[hash].insert(hash2);
        ++gNPaths;
        return;
    }
    if(gHashTab[hash].size()!=0){
        if(gHashTab[hash].count(hash2)) return;
        gHashTab[hash].insert(hash2);
        ++gNPaths;
        return;
    }
}

void zigs(const string aS, const string bS){
    const int n = aS.size();
    string raS = aS;
    reverse(raS.begin(), raS.end());
    string rbS = bS;
    reverse(rbS.begin(), rbS.end());

    if(n<3) return;
    char a[n+1];
    char b[n+1];
    strcpy(a, aS.c_str());
    strcpy(b, bS.c_str());

    char ra[n+1];
    char rb[n+1];
    strcpy(ra, raS.c_str());
    strcpy(rb, rbS.c_str());

    a[n]='\0';
    b[n]='\0';
    ra[n]='\0';
    rb[n]='\0';

    int kStart = 0;
    for (; kStart < n; ++kStart){
        if(a[kStart]!=a[0] || b[kStart]!=a[0]) break;
    }
    kStart = max(1,kStart);
    int kEnd   = n-1;
    for (; kEnd != 0; --kEnd){
        if(a[kEnd]!=a[n-1] || b[kEnd]!=a[n-1]) break;
    }
    kEnd+=2;
    kEnd = min(n+1,kEnd);
    
    char knightPath[gN+1];
    char revKnightPath[gN+1];
    knightPath[gN]    ='\0';
    revKnightPath[gN] ='\0';

    char frontLoopTop[gN+1];
    memcpy(frontLoopTop, ra, n);
    memcpy(frontLoopTop+n, b, n);
    frontLoopTop[gN]   ='\0';

    char frontLoopBottom[gN+1];
    memcpy(frontLoopBottom, rb, n);
    memcpy(frontLoopBottom+n, a, n);
    frontLoopBottom[gN]   ='\0';

    char tailLoopTop[gN+1];
    memcpy(tailLoopTop, a, n);
    memcpy(tailLoopTop+n, rb, n);
    tailLoopTop[gN]   ='\0';

    char tailLoopBottom[gN+1];
    memcpy(tailLoopBottom, b, n);
    memcpy(tailLoopBottom+n, ra, n);
    tailLoopBottom[gN]   ='\0';
    
    char zigEvenUp[gN+1];
    char zigEvenDown[gN+1];
    bool goingEvenDown = true;
    for (int k = 0; k < n; ++k){
        if(goingEvenDown){
            zigEvenDown[2*k]   = a[k];
            zigEvenDown[2*k+1] = b[k];

            zigEvenUp[2*k]   = b[k];
            zigEvenUp[2*k+1] = a[k];
            goingEvenDown = false;
        }
        else{
            zigEvenDown[2*k]   = b[k];
            zigEvenDown[2*k+1] = a[k];
            zigEvenUp[2*k]   = a[k];
            zigEvenUp[2*k+1] = b[k];
            goingEvenDown = true;
        }
    }
    zigEvenUp[gN]   ='\0';
    zigEvenDown[gN] ='\0';

    for (int k = kStart; k < n; ++k)
    {   
        memcpy(knightPath,    frontLoopTop+n-k,    2*k);
        memcpy(revKnightPath, frontLoopBottom+n-k, 2*k);

        unsigned int hashx    = 0;
        unsigned int revHashx = 0;
        if(2*k>n){
            hashx = std::_Hash_impl::hash(knightPath, gNx, 11);
            revHashx = std::_Hash_impl::hash(revKnightPath, gNx, 11);  
        } 
        for(int i=k+1;i<kEnd;++i){
            bool zigEndsTop = true;
            if(k%2 == 1){ //loop starts at the bottom
                memcpy(knightPath+2*k,    zigEvenDown+2*k, 2*(i-k));
                memcpy(revKnightPath+2*k, zigEvenUp+2*k,   2*(i-k));
            } 
            else{//loop starts at the bottom   
                memcpy(knightPath+2*k,    zigEvenUp+2*k,   2*(i-k)); 
                memcpy(revKnightPath+2*k, zigEvenDown+2*k, 2*(i-k));
            }

            if( i<n ){
                if(i%2 == k%2){
                    memcpy(knightPath+2*i,    tailLoopBottom+i, 2*(n-i)); 
                    memcpy(revKnightPath+2*i, tailLoopTop+i, 2*(n-i)); 
                }
                else{
                    memcpy(knightPath+2*i,    tailLoopTop+i, 2*(n-i)); 
                    memcpy(revKnightPath+2*i, tailLoopBottom+i, 2*(n-i)); 
                }
            }
            checkThis(knightPath, hashx);
            checkThis(revKnightPath, revHashx);
        }
    }
}

void bigLoop(const string a, const string b){
    const int n = a.size();
    
    string knightPath = a + b;
    reverse(knightPath.begin(),knightPath.begin()+n);
    for(int i=0;i<gN;++i){
        rotate(knightPath.begin(), knightPath.begin()+1, knightPath.end());
        checkThis(knightPath.c_str());
    }
}


void paths(const string a, const string b){
    string ra = a;
    reverse(ra.begin(), ra.end());
    string rb = b;
    reverse(rb.begin(), rb.end());

    bigLoop(a, b);
    unsigned int gNPathsAux = gNPaths;

    if(ra == b) return;

    zigs(a, b);

    if(a!=ra || b!=rb){
        bigLoop(ra, rb);
        zigs(ra, rb);
    }
    
}

int main() {

    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    int nTests;
    cin >> nTests;

    for(int i=0;i<nTests;++i){
        gHashTab.clear();
        gHashTab.resize(kHashSize);
        gNPaths = 0;
        int n;
        cin >> n;
        string a,b;
        cin >> a;
        cin >> b;

        gN = a.size()*2;
        gNx = a.size();
        paths(a,b);
        cout << gNPaths << endl;
    }
      
    return 0;
}

Python

import os
import sys

PRIME = 1000000007*65535

PMAP = [int((1<<(5*i)) % PRIME) for i in range(1202)]

def chash(s, p = 0):
    for c in s:
        p = ((p<<5) + ord(c)) % PRIME
    return p

def hmap(s):
    ret = [0]
    for c in s:
        ret.append(((ret[-1]<<5)+ord(c)) % PRIME)
    return ret

def hrange(l,i,j,s):
    return (l[j] + ((s-l[i]) * PMAP[j-i])) % PRIME

def count(s1 : str, s2 : str, s1rev, s2rev):
    ret = set()
    n,n2 = len(s1),2*len(s1)
    left_to_top = s2rev + s1
    left_to_bot = s1rev + s2
    right_from_top = s1 + s2rev
    right_from_bot = s2 + s1rev
    mid_even_tb = [ord(s1[i//2]) if ((i%4) in (0,3)) else ord(s2[i//2]) for i in range(n2)]
    mid_odd_tb = [ord(s2[i//2]) if ((i%4) in (0,3)) else ord(s1[i//2]) for i in range(n2)]
    left_to_top,left_to_bot,right_from_top,right_from_bot = map(hmap,(left_to_top,left_to_bot,right_from_top,right_from_bot))
    mid_even_tb = [mid_even_tb[2*j+1] + mid_even_tb[2*j] * PMAP[1] for j in range(n)]
    mid_odd_tb = [mid_odd_tb[2*j+1] + mid_odd_tb[2*j] * PMAP[1] for j in range(n)]
    for left,mids,rights in (left_to_top,(mid_even_tb,mid_odd_tb),(right_from_top,right_from_bot)),(left_to_bot,(mid_odd_tb,mid_even_tb),(right_from_bot,right_from_top)):
        for i in range(0,n+1):
            mid = mids[i&1]
            s = hrange(left,n-i,n+i,0)
            for j in range(i, n):
                ret.add(hrange(rights[j&1],j,n2-j,s))
                s = (s * PMAP[2] + mid[j]) % PRIME
            ret.add(s)
            rights = rights[::-1]
    return ret

def gridlandProvinces(s1, s2):
    s1rev,s2rev = s1[::-1],s2[::-1]
    return len(count(s1, s2, s1rev, s2rev).union(count(s1rev, s2rev, s1, s2)))

if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    p = int(input())

    for p_itr in range(p):
        n = int(input())

        s1 = input()

        s2 = input()

        result = gridlandProvinces(s1, s2)

        fptr.write(str(result) + '\n')
    fptr.close()

Java

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Solution2 {
private final static Scanner scanner = 
new Scanner(System.in);
private final static long mod1 = 2147483607,
 f1 = 107, f2 = 101;
private final static long[] arr1 = new long[10000], 
arr2 = new long[10000]; 
private final static Set<Long> result = new HashSet<>();
public static void main(String[] args) {
for (int i = 0; i < arr1.length; ++i) {
arr1[i] = i > 0 ? arr1[i - 1] * f1 % mod1 : 1;
arr2[i] = i > 0 ? arr2[i - 1] * f2 % mod1 : 1;
}

for (int t = scanner.nextInt(); t > 0; --t) {
result.clear();
scanner.nextInt();
char[] c1 = scanner.next().toCharArray();
char[] c2 = scanner.next().toCharArray();

for (int i = 0; i < c1.length; ++i) {
process(c1, c2, i, false);
process(c2, c1, i, false); 
process(c1, c2, i, true);
process(c2, c1, i, true);
}
reverse(c1);
reverse(c2);
for (int i = 0; i < c1.length; ++i) {
process(c1, c2, i, false);
process(c2, c1, i, false); 
process(c1, c2, i, true);
process(c2, c1, i, true);
}
System.out.println(result.size());
}
}

static void process(char[] s1, char[] s2, int k, boolean b) {
long p1 = 0, p2 = 0, p3 = 0, p4 = 0;
for (int i = 0; i < k; ++i) {
p1 = (p1 + s1[i] * arr1[k - 1 - i]) % mod1;
p1 = (p1 + s2[i] * arr1[k + i]) % mod1;
p3 = (p3 + s1[i] * arr2[k - 1 - i]) % mod1;
p3 = (p3 + s2[i] * arr2[k + i]) % mod1;
}
if (b) {
p1 = (p1 + s2[k] * arr1[k * 2]) % mod1;
p1 = (p1 + s1[k] * arr1[k * 2 + 1]) % mod1;
p3 = (p3 + s2[k] * arr2[k * 2]) % mod1;
p3 = (p3 + s1[k] * arr2[k * 2 + 1]) % mod1;
char[] s = s1; s1 = s2; s2 = s;
++k;
}
for (int i = k; i < s1.length; ++i) {
p2 = (p2 + s1[i] * arr1[s1.length * 2 + k - 1 - i]) % mod1;
p2 = (p2 + s2[i] * arr1[i + k]) % mod1;
p4 = (p4 + s1[i] * arr2[s1.length * 2 + k - 1 - i]) % mod1;
p4 = (p4 + s2[i] * arr2[i + k]) % mod1;
}
result.add(((p1 + p2) % mod1) * mod1 + (p3 + p4) % mod1);

for (int i = k; i < s1.length - 1; i += 2) {
p1 = (p1 + s2[i] * arr1[i * 2]) % mod1;
p1 = (p1 + s1[i] * arr1[i * 2 + 1]) % mod1;
p1 = (p1 + s1[i + 1] * arr1[i * 2 + 2]) % mod1;
p1 = (p1 + s2[i + 1] * arr1[i * 2 + 3]) % mod1;
p2 = (p2 + s2[i] * (mod1 - arr1[i * 2])) % mod1;
p2 = (p2 + s2[i+1] * (mod1 - arr1[i * 2 + 1])) % mod1;
p2 = (p2 + s1[i] * (mod1 - arr1[s1.length * 2 - 1])) % mod1;
p2 = (p2 + s1[i+1] * (mod1 - arr1[s1.length * 2 - 2])) % mod1;
p2 = (p2 * f1 * f1) % mod1;

p3 = (p3 + s2[i] * arr2[i * 2]) % mod1;
p3 = (p3 + s1[i] * arr2[i * 2 + 1]) % mod1;
p3 = (p3 + s1[i + 1] * arr2[i * 2 + 2]) % mod1;
p3 = (p3 + s2[i + 1] * arr2[i * 2 + 3]) % mod1;
p4 = (p4 + s2[i] * (mod1 - arr2[i * 2])) % mod1;
p4 = (p4 + s2[i+1] * (mod1 - arr2[i * 2 + 1])) % mod1;
p4 = (p4 + s1[i] * (mod1 - arr2[s1.length * 2 - 1])) % mod1;
p4 = (p4 + s1[i+1] * (mod1 - arr2[s1.length * 2 - 2])) % mod1;
p4 = (p4 * f2 * f2) % mod1;

result.add(((p1 + p2) % mod1) * mod1 + (p3 + p4) % mod1);
}
}

private static void reverse(char[] str) {
for (int i = str.length / 2 - 1; i >= 0; --i) {
char t = str[i];
str[i] = str[str.length - 1 - i];
str[str.length - 1 - i] = t;
}
}

}

Note: This problem (Gridland Provinces) is generated by HackerRank but the solution is provided by CodingBroz. This tutorial is only for Educational and Learning purpose.

Leave a Comment

Your email address will not be published. Required fields are marked *