using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("8 4");
WillReturn.Add("0 1 0 1 0 1 1 1");
WillReturn.Add("0 1 1 0 0 1 0 0");
WillReturn.Add("1 0 1 0 1 1 1 1");
WillReturn.Add("0 1 1 0 1 0 1 0");
//64
}
else if (InputPattern == "Input2") {
WillReturn.Add("8 5");
WillReturn.Add("0 1 1 1 0 1 1 1");
WillReturn.Add("0 1 0 0 1 1 0 0");
WillReturn.Add("1 0 0 1 1 1 1 1");
WillReturn.Add("0 1 0 1 1 0 1 0");
WillReturn.Add("0 1 1 0 1 1 0 0");
//56
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static Dictionary<int, int> mHexDict = new Dictionary<int, int>();
static void Main()
{
List<string> InputList = GetInputList();
int[,] OldBanArr = CreateBanArr(InputList.Skip(1));
int Old_UB_X = OldBanArr.GetUpperBound(0);
int Old_UB_Y = OldBanArr.GetUpperBound(1);
int UB_X = Old_UB_X + 2;
int UB_Y = Old_UB_Y + 2;
// 外周を0で囲う
int[,] BanArr = new int[UB_X + 1, UB_Y + 1];
for (int LoopX = 0; LoopX <= Old_UB_X; LoopX++) {
for (int LoopY = 0; LoopY <= Old_UB_Y; LoopY++) {
BanArr[LoopX + 1, LoopY + 1] = OldBanArr[LoopX, LoopY];
}
}
for (int LoopX = 0; LoopX <= UB_X; LoopX++) {
for (int LoopY = 0; LoopY <= UB_Y; LoopY++) {
int HexHash = GetHexHash(LoopX, LoopY);
mHexDict[HexHash] = BanArr[LoopX, LoopY];
}
}
HashSet<int> VisitedSet = ExecBFS();
// 黒マスごとに6辺の中で、外周の白マスと隣接した辺を数える
int Answer = 0;
foreach (var EachPair in mHexDict) {
if (EachPair.Value != 1) continue;
int CurrHexX = EachPair.Key / Geta;
int CurrHexY = EachPair.Key % Geta;
Action<int, int> CntAct = (pRinsetuX, pRinsetuY) =>
{
int RinsetuHash = GetHash(pRinsetuX, pRinsetuY);
if (VisitedSet.Contains(RinsetuHash)) {
Answer++;
}
};
CntAct(CurrHexX - 2, CurrHexY);
CntAct(CurrHexX + 2, CurrHexY);
CntAct(CurrHexX - 1, CurrHexY - 1);
CntAct(CurrHexX + 1, CurrHexY - 1);
CntAct(CurrHexX - 1, CurrHexY + 1);
CntAct(CurrHexX + 1, CurrHexY + 1);
}
Console.WriteLine(Answer);
}
// 外周と隣接した白マスをBFSで列挙
static HashSet<int> ExecBFS()
{
var Que = new Queue<JyoutaiDef>();
JyoutaiDef WillEnqueue;
int StaHash = GetHexHash(0, 0);
WillEnqueue.CurrHexHash = StaHash;
Que.Enqueue(WillEnqueue);
var VisitedSet = new HashSet<int>();
VisitedSet.Add(StaHash);
while (Que.Count > 0) {
JyoutaiDef Dequeued = Que.Dequeue();
int CurrHexX = Dequeued.CurrHexHash / Geta;
int CurrHexY = Dequeued.CurrHexHash % Geta;
Action<int, int> EneueueAct = (pNewHexX, pNewHexY) =>
{
int NewHash = GetHash(pNewHexX, pNewHexY);
if (mHexDict.ContainsKey(NewHash) == false) {
return;
}
if (mHexDict[NewHash] == 1) {
return;
}
if (VisitedSet.Add(NewHash)) {
WillEnqueue.CurrHexHash = NewHash;
Que.Enqueue(WillEnqueue);
}
};
EneueueAct(CurrHexX - 2, CurrHexY);
EneueueAct(CurrHexX + 2, CurrHexY);
EneueueAct(CurrHexX - 1, CurrHexY - 1);
EneueueAct(CurrHexX + 1, CurrHexY - 1);
EneueueAct(CurrHexX - 1, CurrHexY + 1);
EneueueAct(CurrHexX + 1, CurrHexY + 1);
}
return VisitedSet;
}
struct JyoutaiDef
{
internal int CurrHexHash;
}
// 2次元座標のXとYを引数として、6角座標のXとYからなるハッシュ値を返す
static int GetHexHash(int pX, int pY)
{
int HexX;
int HexY = pY;
if (pY % 2 == 0) {
HexX = 2 * pX;
}
else {
HexX = 2 * pX + 1;
}
return GetHash(HexX, HexY);
}
// 6各座標のXとYを引数として、ハッシュ値を返す
const int Geta = 1000;
static int GetHash(int pHexX, int pHexY)
{
return pHexX * Geta + pHexY;
}
////////////////////////////////////////////////////////////////
// IEnumerable<string>をintの2次元配列に設定する
////////////////////////////////////////////////////////////////
static int[,] CreateBanArr(IEnumerable<string> pStrEnum)
{
var StrList = pStrEnum.ToList();
if (StrList.Count == 0) {
return new int[0, 0];
}
int[] IntArr = { };
Action<string> SplitAct = pStr =>
IntArr = pStr.Split(' ').Select(pX => int.Parse(pX)).ToArray();
SplitAct(StrList[0]);
int UB_X = IntArr.GetUpperBound(0);
int UB_Y = StrList.Count - 1;
int[,] WillReturn = new int[UB_X + 1, UB_Y + 1];
for (int Y = 0; Y <= UB_Y; Y++) {
SplitAct(StrList[Y]);
for (int X = 0; X <= UB_X; X++) {
WillReturn[X, Y] = IntArr[X];
}
}
return WillReturn;
}
}