require 'set'
f = -> a {
g = -> a {a.combination(2) {|x, y| break g.(a.tap {x.merge y; a.delete y}) if x.intersect? y}}
h = a.map {|s| s.split('=')}.flatten.uniq.map.with_index.to_h
a = a.map {|s| s.split('=').map {|k| h[k]}.to_set SortedSet}
g.(a).map {|set| set.map &h.invert.method(:[])}
}
a = ["a1=a2", "b1=b2", "b3=b2", "c1=c2", "e1=e2",
"a3=a4", "c3=c4", "e1=e3", "a2=a4", "c3=c1",
"b3=a4", "c2=d1", "a4=a5", "d2=c1", "b4=b3", "d3=c3"]
p f.(a)
cmVxdWlyZSAnc2V0JwpmID0gLT4gYSB7CiAgZyA9IC0+IGEge2EuY29tYmluYXRpb24oMikge3x4LCB5fCBicmVhayBnLihhLnRhcCB7eC5tZXJnZSB5OyBhLmRlbGV0ZSB5fSkgaWYgeC5pbnRlcnNlY3Q/IHl9fQogIGggPSBhLm1hcCB7fHN8IHMuc3BsaXQoJz0nKX0uZmxhdHRlbi51bmlxLm1hcC53aXRoX2luZGV4LnRvX2gKICBhID0gYS5tYXAge3xzfCBzLnNwbGl0KCc9JykubWFwIHt8a3wgaFtrXX0udG9fc2V0IFNvcnRlZFNldH0KICBnLihhKS5tYXAge3xzZXR8IHNldC5tYXAgJmguaW52ZXJ0Lm1ldGhvZCg6W10pfQp9CmEgPSBbImExPWEyIiwgImIxPWIyIiwgImIzPWIyIiwgImMxPWMyIiwgImUxPWUyIiwKImEzPWE0IiwgImMzPWM0IiwgImUxPWUzIiwgImEyPWE0IiwgImMzPWMxIiwKImIzPWE0IiwgImMyPWQxIiwgImE0PWE1IiwgImQyPWMxIiwgImI0PWIzIiwgImQzPWMzIl0KcCBmLihhKQo=
[["a1", "a2", "b1", "b2", "b3", "a3", "a4", "a5", "b4"], ["c1", "c2", "c3", "c4", "d1", "d2", "d3"], ["e1", "e2", "e3"]]