Magnus decided to play a classic chess game. Though what he saw in his locker shocked him! His favourite chessboard got broken into 4 pieces, each of size n by n, n is always odd. And what's even worse, some squares were of wrong color. j-th square of the i-th row of k-th piece of the board has color ak, i, j; 1 being black and 0 being white. 

Now Magnus wants to change color of some squares in such a way that he recolors minimum number of squares and obtained pieces form a valid chessboard. Every square has its color different to each of the neightbouring by side squares in a valid board. Its size should be 2n by 2n. You are allowed to move pieces but not allowed to rotate or flip them.

Input

The first line contains odd integer n (1 ≤ n ≤ 100) — the size of all pieces of the board. 

Then 4 segments follow, each describes one piece of the board. Each consists of n lines of n characters; j-th one of i-th line is equal to 1 if the square is black initially and 0 otherwise. Segments are separated by an empty line.

Output

Print one number — minimum number of squares Magnus should recolor to be able to obtain a valid chessboard.

Examples

Input

1
0

0

1

0


Output

1


Input

3
101
010
101

101
000
101

010
101
011

010
101
010


Output

2
//package mar18;

import java.io.*;
import java.util.*;

public class HR27 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";
	//boolean codechef=true;
	boolean codechef=true;
	
	void solve()
	{
		
		int n=ni();
		int[][][] mat=new int[4][n][n];
		for(int i=0;i<4;i++)
		{
			for(int j=0;j<n;j++)
			{
				String s=ns();
				for(int k=0;k<n;k++)
				{
					mat[i][j][k]=(int)(s.charAt(k)-'0');
				}
			}
		}
		
		//System.out.println("jk");
		int[][] cr1=makeMat(n,0);
		int[][] cr2=makeMat(n,1);
		int[] diff1=new int[4];
		int[] diff2=new int[4];
		for(int i=0;i<4;i++)
		{
			diff1[i]=diff(cr1, mat[i]);
			diff2[i]=diff(cr2,mat[i]);
		}
		int[] f=new int[6];
		f[0]=diff1[0]+diff1[1]+diff2[2]+diff2[3];
		f[1]=diff1[0]+diff1[2]+diff2[1]+diff2[3];
		f[2]=diff1[0]+diff1[3]+diff2[1]+diff2[2];
		f[3]=diff2[0]+diff2[1]+diff1[2]+diff1[3];
		f[4]=diff2[0]+diff2[2]+diff1[1]+diff1[3];
		f[5]=diff2[0]+diff2[3]+diff1[1]+diff1[2];
		Arrays.sort(f);
		out.println(f[0]);
		
		
	}
	
	void solveD()
	{
		int n=ni();
		
		Pair[] pr=new Pair[n];
		for(int i=0;i<n;i++)
		{
			pr[i]=new Pair(ni(),ni());
		}
		if(n==1)
		{
			out.println("YES");return;
		}
		long num=(pr[1].y-pr[0].y);
		long den=(pr[1].x-pr[0].x);
		Arrays.sort(pr,new Comparator<Pair>() {

			@Override
			public int compare(Pair o1, Pair o2) {
				// TODO Auto-generated method stub
				long currn=(o2.y-o1.y);
				long currd=(o2.x-o1.x);
				if(currn*den-currd*num==0)return 0;
				return 1;
			}});
		for(Pair p:pr)
		{
			out.println(p.x+" "+p.y);
		}
	}
	
	void solveB()
	{
		int n=ni(),k=ni();
		int[] a=na(n);
		int[] t=na(n);
		int[] onwake=new int[n];
		if(t[0]==1)onwake[0]=a[0];
		for(int i=1;i<n;i++)
		{
			if(t[i]==1)
			{
				onwake[i]=onwake[i-1]+a[i];
			}
			else onwake[i]=onwake[i-1];
		}
		int[] kcont=new int[n];
		for(int i=0;i<k;i++)
		{
			kcont[0]+=a[i];
		}
		for(int i=1;i<=n-k;i++)
		{
			kcont[i]=kcont[i-1]+a[k-1+i]-a[i-1];
		}
		int max=onwake[n-1];
		for(int i=0;i<n-k;i++)
		{
			max=Math.max(max, onwake[i]+kcont[i+1]);
		}
		out.println(max);
	}
	
	void solveA()
	{
		int n=ni(),m=ni();
		int[] c=na(m);
		int[] f=new int[n];
		int cnt=0;
		for(int i=0;i<m;i++)
		{
			f[c[i]-1]++;
			boolean ch=false;
			for(int j=0;j<n;j++)
			{
				if(f[j]==0)
				{
					ch=true;break;
				}
			}
			if(!ch)
			{
				for(int j=0;j<n;j++)
				{
					f[j]--;
				}
				cnt++;
			}
		}
		out.println(cnt);
	}
	
	static int[][] makeMat(int n,int st)
	{
		int[][] mat=new int[n][n];
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				if(st==0)
				{
					if((i+j)%2!=0)mat[i][j]=1;
				}
				else
				{
					if((i+j)%2==0)mat[i][j]=1;
				}
			}
		}
		return mat;
	}

	
	static int diff(int[][] a1,int[][] a2)
	{
		int n=a1.length,cnt=0;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				if(a1[i][j]!=a2[i][j])cnt++;
			}
		}
		return cnt;
	}
	
	static class Pair
	{
		long x;
		long y;
		public Pair(long x,long y)
		{
			this.x=x;
			this.y=y;
		}
	}

	
	static long lcm(int a,int b)
	{
		long val=a;
		val*=b;
		return (val/gcd(a,b));
	}
	
	static int gcd(int a,int b)
	{
		if(a==0)return b;
		return gcd(b%a,a);
	}
	
	static int pow(int a, int b, int p)
	{
		long ans = 1, base = a;
		while (b!=0)
		{
			if ((b & 1)!=0)
			{
				ans *= base;
				ans%= p;
			}
			base *= base;
			base%= p;
			b >>= 1;
		}
		return (int)ans;
	}

	static int inv(int x, int p)
	{
		return pow(x, p - 2, p);
	}

	
	void run() throws Exception
	{
		if(codechef)oj=true;
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);
		
		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}
	
	public static void main(String[] args) throws Exception {new HR27().run();}
	
	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;
	
	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}
	
	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }
	
	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }
	
	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}
	
	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}
	
	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}
	
	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}
	
	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}
		
		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}
	
	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}
		
		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}
	
	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}