#!/usr/bin/env tclsh9.0 namespace import ::tcl::mathop::* proc input {} { global nodes edges set nodes [dict create] ;# existence set edges [dict create] ;# maps each node to a list of neighbors while {[gets stdin line] >= 0} { if {$line eq ""} continue if {[scan $line {%[^-]-%s} a b] != 2} continue dict set nodes $a 1 dict set nodes $b 1 dict lappend edges $a $b dict lappend edges $b $a } } proc setsof3 {} { global nodes edges sets set sets [dict create] ;# existence foreach node [dict keys $nodes] { set neighbors [dict get $edges $node] if {[llength $neighbors] < 2} continue # We have at least 2 neighbors, so consider each pair. for {set i 0} {$i < [llength $neighbors] - 1} {incr i} { for {set j [+ $i 1]} {$j < [llength $neighbors]} {incr j} { set a [lindex $neighbors $i] set b [lindex $neighbors $j] # if {[string range $node 0 0] ne "t" && # [string range $a 0 0] ne "t" && # [string range $b 0 0] ne "t"} continue if {[connected3 $node $a $b]} { set tmp [lsort [list $node $a $b]] dict set sets $tmp 1 } } } } # dict for {key val} $sets { # puts $key # } # puts [dict size $sets] } # Beginning with the smaller sets we've already identified, find all sets # of n nodes. Keep increasing n until the number of sets is 1. proc findsets {n} { global edges sets puts "findsets n=$n #sets=[dict size $sets]" set newsets [dict create] foreach set [dict keys $sets] { # If n=4, then we're looking at sets of 3, so we know each node has # at least 2 neighbors. We need this node to have 3 or more. set neighbors [dict get $edges [lindex $set 0]] if {[llength $neighbors] < [llength $set]} continue # Consider each neighbor that's NOT already in the set, and see if # adding this neighbor forms a size n connected set. foreach neigh $neighbors { if {$neigh in $set} continue if {! [connected {*}$set $neigh]} continue set tmp [lsort [list {*}$set $neigh]] dict set newsets $tmp 1 } } if {[dict size $newsets] == 1} { puts [join [lindex [dict keys $newsets] 0] ,] } elseif {[dict size $newsets] == 0} { puts "error: n=$n no new sets found" } else { set sets $newsets findsets [incr n] # Yes, it's a silly recursion. No, we're not even using n, except # in debugging messages. } } proc connected3 {a b c} { global edges set aneigh [dict get $edges $a] set bneigh [dict get $edges $b] if {$c ni $aneigh || $c ni $bneigh || $a ni $bneigh} {return 0} return 1 } proc connected {args} { global edges for {set i 0} {$i < [llength $args] - 1} {incr i} { for {set j [+ $i 1]} {$j < [llength $args]} {incr j} { set a [lindex $args $i] set b [lindex $args $j] if {$a ni [dict get $edges $b]} {return 0} } } return 1 } input setsof3 findsets 4