#!/usr/bin/env tclsh9.0
namespace import ::tcl::mathop::*

# Put a margin of ... around the input.
# Legit garden plot tiles will therefore be 1..rows and 1..cols.
proc input {} {
    global rows cols grid
    set grid [list]
    set rows 0
    while {[gets stdin line] >= 0} {
        if {$line eq ""} continue
        if {$rows == 0} {
            set margin [list .]
            foreach c [split $line ""] {lappend margin .}
            lappend margin .
            lappend grid $margin
            set cols [string length $line]
        }
        set row [list .]
        lappend row {*}[split $line ""]
        lappend row .
        lappend grid $row
        incr rows
    }
    lappend grid $margin
}

proc show {} {
    global rows cols grid
    for {set r 0} {$r <= [+ $rows 1]} {incr r} {
        for {set c 0} {$c <= [+ $cols 1]} {incr c} {
            puts -nonewline [lindex $grid $r $c]
        }
        puts ""
    }
    puts "rows=$rows cols=$cols"
}

proc count {} {
    global rows cols grid
    global region

    set total 0
    for {set r 1} {$r <= $rows} {incr r} {
        for {set c 1} {$c <= $cols} {incr c} {
            if {[lindex $grid $r $c] eq "."} continue

            # Find the region starting here.
            set region [dict create]
            flood $r $c
            # puts "region=$region"
            set area [dict size $region]
            set p [perimeter $region]
            incr total [* $area $p]
            # puts "area=$area p=$p"

            # Mark the region as dots so we won't re-find it.
            foreach rc [dict keys $region] {
                lassign $rc r1 c1
                lset grid $r1 $c1 .
            }
        }
    }
    puts $total
}

proc flood {r c} {
    global grid region
    if {[dict exists $region [list $r $c]]} return
    set plant [lindex $grid $r $c]
    dict set region [list $r $c] 1
    foreach {dr dc} {0 1 0 -1 1 0 -1 0} {
        set r1 [+ $r $dr]
        set c1 [+ $c $dc]
        if {[lindex $grid $r1 $c1] eq $plant} {flood $r1 $c1}
    }
}

# My stupid idea: generate a list of all the individual pieces of fence.
# We can't store these as simple {r c} integer pairs because of the O and E
# cases.  But we can say that {r c} with a non-matching north neighbor would
# have a piece of fence at {r c-0.25}.  Then, if the tile two spots north has
# a southern piece of fence, that would be {r c-2+0.25}.

# In theory, then, we can somehow reduce the list of fence pieces,
# collecting adjoining pieces into one big piece.  First guess: let's
# sort the fences by row, and then by col, and then we can eliminate
# pieces that are exactly 1 step away.

proc perimeter {region} {
    global grid
    set fences [list]
    set plant ""
    foreach rc [dict keys $region] {
        lassign $rc r c
        if {$plant eq ""} {set plant [lindex $grid $r $c]}

        foreach {dr dc} {0 1 0 -1 1 0 -1 0} {
            set r1 [+ $r $dr]
            set c1 [+ $c $dc]
            if {[lindex $grid $r1 $c1] ne $plant} {
                lappend fences [list [expr {$r+$dr/4.0}] [expr {$c+$dc/4.0}]]
            }
        }
    }

    # puts "region=$region"
    # puts "fences=$fences"
    # puts "sorted1=[lsort -real -index 0 $fences]"
    # puts "sorted2=[lsort -real -index 1 $fences]"

    # First, the horizontal fences.  Sort by row (primary) and col (secondary)
    # and iterate over the result, discarding any piece that's exactly one
    # col away from the next piece.
    set prev [list]
    set discard [dict create]
    foreach curr [lsort -real -index 0 [lsort -real -index 1 $fences]] {
        if {! [llength $prev]} {
            set prev $curr
            continue
        }
        lassign $prev pr pc
        lassign $curr cr cc
        if {$cr == $pr && $cc == [+ $pc 1]} {
            dict set discard $prev 1
        }
        set prev $curr
    }

    # Now, do it again for the vertical fences.
    set prev [list]
    foreach curr [lsort -real -index 1 [lsort -real -index 0 $fences]] {
        if {! [llength $prev]} {
            set prev $curr
            continue
        }
        lassign $prev pr pc
        lassign $curr cr cc
        if {$cc == $pc && $cr == [+ $pr 1]} {
            dict set discard $prev 1
        }
        set prev $curr
    }

    # puts "region=$region"
    # puts "fences=$fences"
    # puts "discard=$discard"

    return [- [llength $fences] [dict size $discard]]
}

input
# show
count