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):
s = (s * PMAP[2] + mid[j]) % PRIME
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.