Can this Scottish village have a wedding?

Python 2, 399 393 390 388 385 bytes

def f(s):
 V=S(''.join(s))-S(' |+-^');P={v:[]for v in V}
 for j,r in E(s):
	for i,c in E(r):
	 if'+'==c:
		p,q=a=h(r,i);A=a+P[p][:2]+P[q][:2];V-=S(a);v=j;b='|'
		while'z'<b:v+=1;b=s[v][i]
		if'^'==b:w,x=h(s[v],i);P[w]=P[x]=A
		else:P[b]=A
 return 1-all((b>'Z')==(c>'Z')or S(P[b])&S(P[c])for b in V for c in V)
h=lambda r,i:[x.strip('-')[0]for x in r[i-1::-1],r[i+1:]]
E=enumerate;S=set

Try it online!

2 bytes thx to Jitse; 3 bytes thanks to isaacg.

Jeez! I think I could golf this a bit more; but at least I got it under 400 bytes :).

The input s is a list of strings. The encoding is A-Z for males, a-z for females, + to indicate a marriage, ^ for when a marriage produces 2 children (instead of =, 'cause I liked the look better :) ). Then - for horizontal extensions, | for vertical extensions.

Output is 1 for truthy, 0 for falsey.

V is the set of all villagers, initially; then as we scan, we will remove from V those who are already married. So at the end, V will be the set of un-mated villagers.

P is a dictionary with keys for all villagers v. P[v] will be the list of those parents of v, followed those grandparents of v, who are also villagers. Note that then P[v][:2] are the parents of v (assuming they are villagers).

h is a helper function to skip over any horizontal extensions (runs of -). Useful both for extracting a pair of parent villagers as well as dual children.


Jelly, 155 153 bytes

Ø.UAƭN,Ɗ⁺+Ṫ¥+œị⁾+|yⱮ$ɼ=⁾|=⁼Ø.Ɗɗ¡ƬṪ¥ƒ⁸’1¦⁺œị®⁼”|ƊпṖṪ+2¦œị®⁻1Ɗ¡ƬṪ¥ⱮØ+$“”¹?
o@e¥€€ØẠ“-=“==”;U¤œṣjƭƒ$€ƬṪ©=1ŒṪ+2¦œị®ɗⱮØ+f⁾-+ƊÐḟWÇ€Ẏ$Ƭḣ3ẎƲ€Œcf/ÐḟḢ€€ȧœị¥>”ZIFẸ

Try it online!

Minor modification of my Cyrillic version.

A monadic link that takes a list of Jelly strings and returns 1 for true and 0 for false. I’m sure this could be golfed more. Full explanation to follow.