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<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 1e9;
const ll mod = 1e9+7;
typedef pair<int,int> P;
#define rep(i,N) for(int i=0;i<N;i++)
#define rep2(i,m,N) for(int i=m;i<N;i++)
#define mm(n,m) memset(n,m,sizeof(n))

int main(){
  int h;
  while(cin>>h){
    if(h==0)return 0;
    int m[h][5];
    int dm[h][5];
    rep(i,h){
      rep(j,5){
        cin>>m[i][j];
      }
    }
    int res = 0;
    mm(dm,0);
    bool OK = true;
    while(OK){ //dmが全部0になるまで
      rep(i,h){
        int c[5];
        mm(c,0);
        rep(j,5){
          if(m[i][j]==0)continue;
          queue<int> que;
          que.push(j);
          int cnt = 0;
          int dx[2] = {1,-1};
          int v[5]= {0,0,0,0,0};
          while(que.size()){
            int p = que.front(); que.pop();
            v[p] = 1;
            for(int k=0;k<2;k++){
              int nx = p + dx[k];

              if(nx<0||nx>4){
                continue;
              }
              if(m[i][nx] != m[i][j] || v[nx]!=0){
                continue;
              }
              //cout<<"aA"<<endl;
              que.push(nx);
            }
            cnt++;
          }
          //cout<<cnt<<endl;
          if(cnt > 2){
            dm[i][j] = 1;
          }
        }
      }

      
      rep(i,h){
        rep(j,5){
          //cout<<dm[i][j]<<" ";
        }
        //cout<<endl;
      }

      int cnt = 0;
      //ここから消滅処理
      rep(i,h){
        rep(j,5){
          if(dm[i][j]==1){
            dm[i][j]=0;
            res += m[i][j];
            m[i][j] = 0;
          }else{
            cnt++;
          }
        }
      }
      if(cnt == h*5){
        OK = false;
      }

      //ここから落下処理
      for(int i = 1; i<h; i++){
        for(int j = 0; j < 5; j++){
          int k = i;
          while(m[k][j]==0){
            m[k][j] = m[k-1][j];
            m[k-1][j] = 0;
            k--;
            if(k<1)break;
          }
        }
      }

      //cout<<"res:"<<res<<endl;
      
      rep(i,h){
        rep(j,5){
          //cout<<m[i][j]<<" ";
        }
        //cout<<endl;
      }
      //cout<<endl;

    }

      cout<<res<<endl;
    }
  }

C++: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define REP(i,n) for(int i=0; i<(n); i++)
#define REP2(i,x,n) for(int i=x; i<(n); i++)
#define PRINT(x) cout<<(x)<<endl
#define INF 1000000000000 // 10^12
#define MOD 1000000007 // 10^9+7
#define PB push_back
#define MP make_pair

const int MAX_H = 10;
const int W = 5;

int H, stone[MAX_H][W];

bool to_disappear[MAX_H][W];
int next_stone_row[MAX_H][W];

bool detect_chain();
void make_next_stone_row();
void update_stone();
void print_stone();
int solve();

int main() {
    while (true) {
        cin >> H;
        if (H == 0) break;
        REP(i, H) REP(j, W) cin >> stone[i][j];

        int score = solve();
        PRINT(score);
    }
    return 0;
}

bool detect_chain() {
    bool exist_chain = false;
    REP(i, H) REP(j, W) to_disappear[i][j] = false;

    REP(i, H) { // i行目
        for (int j = W; j >= 3; j--) { // j個連続
            for (int k = 0; k + j - 1 < W; k++)  { // k列目を起点
                bool is_chain = true;
                if (stone[i][k] == -1) is_chain = false;
                REP(l, j-1) { // k+l列目とk+l+1列目の比較
                    if (stone[i][k+l] != stone[i][k+l+1]) is_chain = false;
                }

                if (is_chain) {
                    exist_chain = true;
                    REP(l, j) to_disappear[i][k+l] = true;
                }
            }
        }
    }
    return exist_chain;
}

void make_next_stone_row() {
    for (int i = H-1; i >= 0; i--) {
        REP(j, W) {
            if (i == H-1) next_stone_row[i][j] = H-1;
            else next_stone_row[i][j] = max(next_stone_row[i+1][j] - 1, -1);
            while (true) {
                if (next_stone_row[i][j] == -1) break;
                if (to_disappear[next_stone_row[i][j]][j] == false) break;
                next_stone_row[i][j]--;
            }
        }
    }
    return;
}

void update_stone() {
    for (int i = H-1; i >= 0; i--) {
        REP(j, W) {
            if (next_stone_row[i][j] == -1) stone[i][j] = -1;
            else stone[i][j] = stone[next_stone_row[i][j]][j];
        }
    }
    return;
}

void print_stone() {
    REP(i, 32) printf("-");
    printf("\n");
    REP(i, H) {
        REP(j, W) printf("%d\t", stone[i][j]);
        printf("\n");
    }
}

int solve() {
    int score = 0;
    REP(i, H) REP(j, W) score += stone[i][j];
    while (true) {
        // print_stone();
        if (!detect_chain()) break;
        make_next_stone_row();
        update_stone();
    }
    REP(i, H) REP(j, W) if (stone[i][j] != -1) score -= stone[i][j];
    return score;
}