Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	io := NewIo()
	defer io.Flush()
	for {
		h := io.NextInt()
		if h == 0 {
			break
		}
		p := make([][]int, h)
		for i := 0; i < h; i++ {
			p[i] = make([]int, 5)
			for j := 0; j < 5; j++ {
				p[i][j] = io.NextInt()
			}
		}
		ans := 0
		for {
			sc := puyo(p, h)
			if sc == 0 {
				break
			}
			fall(p, h)
			ans += sc
		}
		io.Println(ans)
	}
}

func puyo(p [][]int, h int) int {
	sc := 0
	for i := 0; i < h; i++ {
		for j := 0; j < 3; j++ {
			var cnt int
			for cnt = 1; j+cnt < 5; cnt++ {
				if p[i][j] != p[i][j+cnt] {
					break
				}
			}
			if cnt > 2 {
				sc += p[i][j]*cnt
				for k := 0; k < cnt; k++ {
					p[i][j+k] = 0
				}
			}
		}
	}
	return sc
}

func fall(p [][]int, h int) {
	for j := 0; j < 5; j++ {
		for k := 1; k < h; k++ {
			for i := h - 1; i >= k; i-- {
				if p[i][j] == 0 {
					p[i][j] = p[i-1][j]
					p[i-1][j] = 0
				}
			}
		}
	}
}

// I/O template
type Io struct {
	reader    *bufio.Reader
	writer    *bufio.Writer
	tokens    []string
	nextToken int
}

func NewIo() *Io {
	return &Io{
		reader: bufio.NewReader(os.Stdin),
		writer: bufio.NewWriter(os.Stdout),
	}
}

func (io *Io) Flush() {
	err := io.writer.Flush()
	if err != nil {
		panic(err)
	}
}

func (io *Io) NextLine() string {
	var buff []byte
	for {
		line, isPrefix, err := io.reader.ReadLine()
		if err != nil {
			panic(err)
		}
		buff = append(buff, line...)
		if !isPrefix {
			break
		}
	}
	return string(buff)
}

func (io *Io) Next() string {
	for io.nextToken >= len(io.tokens) {
		line := io.NextLine()
		io.tokens = strings.Fields(line)
		io.nextToken = 0
	}
	s := io.tokens[io.nextToken]
	io.nextToken++
	return s
}

func (io *Io) NextInt() int {
	i, err := strconv.Atoi(io.Next())
	if err != nil {
		panic(err)
	}
	return i
}

func (io *Io) NextFloat() float64 {
	i, err := strconv.ParseFloat(io.Next(), 64)
	if err != nil {
		panic(err)
	}
	return i
}

func (io *Io) Println(a ...interface{}) {
	fmt.Fprintln(io.writer, a...)
}

func (io *Io) Printf(format string, a ...interface{}) {
	fmt.Fprintf(io.writer, format, a...)
}

func (io *Io) PrintIntSlice(a []int) {
	b := []interface{}{}
	for _, x := range a {
		b = append(b, x)
	}
	io.Println(b...)
}

func (io *Io) PrintStringSlice(a []string) {
	b := []interface{}{}
	for _, x := range a {
		b = append(b, x)
	}
	io.Println(b...)
}

func Log(name string, value interface{}) {
	fmt.Fprintf(os.Stderr, "%s=%+v\n", name, value)
}

func ExampleIo() {
	io := NewIo()
	defer io.Flush()
	a := make([]int, 0, 3)
	a[0], a[1], a[2] = io.NextInt(), io.NextInt(), io.NextInt()
	io.Println(a)
	io.PrintIntSlice(a)
	Log("io", a)
}

C++: #include <algorithm>
#include <cmath>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using std::cerr;
using std::cin;
using std::cout;
using std::endl;

struct Pos{
  int x,y;
  Pos(int a,int b){
    x=a;
    y=b;
  }
};

class Field{
  int cell_[10][5]={};
  int height_;

  void FallBlock(void){
    for(int col=0;col<5;col++){
      bool found_empty=false;
      int empty_row=11;
      for(int row=height_-1;row>=0;row--){
        if(!found_empty){
          if(cell_[row][col]==0){
            found_empty=true;
            empty_row=row;
          }
        }else{
          if(cell_[row][col]!=0){
            cell_[empty_row][col]=cell_[row][col];
            cell_[row][col]=0;
            empty_row--;
          }
        }
      }
    }
  }

  int EraseBlock(void){
    int result=0;
    std::vector<Pos> erased_pos;
    for(int row=0;row<height_;row++){
      for(int col_left=0;col_left<=2;col_left++){
        if(cell_[row][col_left]==cell_[row][col_left+1]&& cell_[row][col_left]==cell_[row][col_left+2]){
          erased_pos.push_back(Pos(row,col_left));
          erased_pos.push_back(Pos(row,col_left+1));
          erased_pos.push_back(Pos(row,col_left+2));
          int color=cell_[row][col_left];
          for(int add_col=col_left+3;add_col<5;add_col++){
            if(color==cell_[row][add_col]){
              erased_pos.push_back(Pos(row,add_col));
            }else break;
          }
          break;
        }
      }
    }
    for(auto tgt:erased_pos){
      result+=cell_[tgt.x][tgt.y];
      cell_[tgt.x][tgt.y]=0;

    }
    return result;
  }

public:
  Field(int h){
    height_=h;
  }
  void Set(int row,int col,int num){
    cell_[row][col]=num;
  }
  int Calc(void){
    int result=0;
    int in_turn=0;
    do{
      in_turn=EraseBlock();
      FallBlock();
      result+=in_turn;
    }while(in_turn>0);

    return result;

  }

};

int main(void) {
  cout << std::fixed << std::setprecision(10);
  cin.tie(0);
  std::ios::sync_with_stdio(false);

  while(1){
    int h;
    cin>>h;
    if(h==0) break;
    Field field(h);
    for(int i=0;i<h;i++){
      for(int j=0;j<5;j++){
        int num;
        cin>>num;
        field.Set(i,j,num);
      }
    }
    cout<<field.Calc()<<endl;
  }

  return 0;
}

C++: #include <bits/stdc++.h>
#define INF 1000000000
using namespace std;

int main()
{
  while (true)
  {
    int H;
    cin >> H;
    if (H == 0)
    {
      return 0;
    }
    vector<vector<int>> mp(5, vector<int>(H * 2, -1));
    for (int i = 0; i < H; ++i)
    {
      for (int j = 0; j < 5; ++j)
      {
        cin >> mp.at(j).at(H - 1  - i);
      }
    }
    int ans = 0;
    while (true)
    {
      bool didnt_erase = true;
      for (int i = H - 1; i >= 0; --i)
      {
        int cnt = 0;
        int now = - 1;
        for (int j = 0; j < 5; ++j)
        {
          if (mp.at(j).at(i) == -1)
          {
            if (cnt > 2)
            {
              ans += cnt * mp.at(j - 1).at(i);
              // cout << cnt * mp.at(j - 1).at(i) << endl;
              for (int k = 0; k < cnt; ++k)
              {
                mp.at(j - k - 1).erase(mp.at(j - k - 1).begin() + i);
              }
              didnt_erase = false;
            }
            now = -1;
            cnt = 0;
            continue;
          }
          else if (now == mp.at(j).at(i))
          {
            cnt += 1;
          }
          else
          {
            if (cnt > 2)
            {
              ans += cnt * mp.at(j - 1).at(i);
              // cout << cnt * mp.at(j - 1).at(i) << endl;
              for (int k = 0; k < cnt; ++k)
              {
                mp.at(j - k - 1).erase(mp.at(j - k - 1).begin() + i);
              }
              didnt_erase = false;
            }
            cnt = 1;
            now = mp.at(j).at(i);
          }
        }
        if (cnt > 2)
        {
          ans += cnt * mp.at(4).at(i);
          // cout << cnt * mp.at(4).at(i) << endl;
          for (int k = 0; k < cnt; ++k)
          {
            mp.at(4 - k).erase(mp.at(4 - k).begin() + i);
          }
          didnt_erase = false;
        }
      }
      if (didnt_erase)
      {
        break;
      }
    }
    // for (int i = 0; i < mp.size(); ++i)
    // {
    //   for (int j = 0; j < mp.at(i).size(); ++j)
    //   {
    //     cout << mp.at(i).at(j);
    //   }
    //   cout << endl;
    // }
    cout << ans << endl;
  }
}