lambda w,h:len({min(I(D(H(V(x)))for x in o)for H,V,D in Q((lambda p:(w+~p[0],p[1]),I),(lambda p:(p[0],h+~p[1]),I),(lambda p:p[::-1],I)))for o in permutations(Q(range(w),range(h)))for s in[[*zip(o,o[1:])]]if any(x-~X-w|y+Y-h+1for(x,y),(X,Y)in zip(o,o[::-1]))+any(gcd(x-X,y-Y)>1for(x,y),(X,Y)in s)+any((len({*u,*v})>3)*intersection(S(*u),S(*v))for u,v in Q(s,s))<1})
from math import*
from sympy import*
from itertools import*
Q=product
S=Segment
I=tuple
Try it online!
Inlined version of the previous answer below. -3 bytes thanks to Kevin Cruijssen's tip.
from math import*
from sympy import*
from itertools import*
Q=product
S=Segment
I=tuple
def f(w,h):
a={1}
for o in permutations(Q(range(w),range(h))):
s=[*zip(o,o[1:])]
if any(x+X-w+1|y+Y-h+1for(x,y),(X,Y)in zip(o,o[::-1]))+any(gcd(x-X,y-Y)>1for(x,y),(X,Y)in s)+any((len({*u,*v})>3)*intersection(S(*u),S(*v))for u,v in Q(s,s))<1:a.add(min(I(D(H(V(x)))for x in o)for H,V,D in Q((lambda p:(w-1-p[0],p[1]),I),(lambda p:(p[0],h-1-p[1]),I),(lambda p:p[::-1],I))))
return~-len(a)
Try it online!
The golfed version takes too long to check the nontrivial answers. The version below has a shortcut in the conditional, so you can check that the results up to (2,4)
are correct.
from math import*
from sympy import*
from itertools import*
Q=product
S=Segment
I=tuple
def f(w,h):
a={1}
for o in permutations(Q(range(w),range(h))):
s=[*zip(o,o[1:])]
if(any(x+X-w+1|y+Y-h+1for(x,y),(X,Y)in zip(o,o[::-1]))or any(gcd(x-X,y-Y)>1for(x,y),(X,Y)in s)+any((len({*u,*v})>3)*intersection(S(*u),S(*v))for u,v in Q(s,s)))<1:a.add(min(I(D(H(V(x)))for x in o)for H,V,D in Q((lambda p:(w-1-p[0],p[1]),I),(lambda p:(p[0],h-1-p[1]),I),(lambda p:p[::-1],I))))
return~-len(a)
Try it online!
Ungolfed, with comments
from math import*
from sympy import*
from itertools import*
def pass_point(p1,p2): # test if the segment passes through another point
return gcd(p1[0]-p2[0],p1[1]-p2[1]) > 1
def f(w,h):
pts = [(i,j) for i in range(w) for j in range(h)]
ans = set()
for orders in permutations(pts):
# test if the ordering has 180 degrees rotational symmetry
if any(x1+x2!=w-1or y1+y2!=h-1for (x1,y1),(x2,y2) in zip(orders, orders[::-1])):continue
segments = [*zip(orders, orders[1:])]
# test if a segment passes through another point or two segments intersect
if any(pass_point(*p)for p in segments)+any(len({*s1,*s2})==4and intersection(Segment(*s1),Segment(*s2))for s1 in segments for s2 in segments):continue
# take minimum of 8 possible rotations/reflections
flipH = lambda p:(w-1-p[0],p[1]); flipV = lambda p:(p[0],h-1-p[1]); flipD = lambda p:p[::-1]; nop = lambda p:p
flipmin = min(tuple(map(lambda o:d(h(v(o))),orders))for h in (flipH,nop)for v in (flipV,nop) for d in (flipD, nop))
ans.add(flipmin)
print(len(ans))
Try it online!
SymPy has Geometry module that includes an intersection checker intersection
that works for line segment Segment
objects. This is much shorter than rolling a hand-written intersection checker based on coordinates. The intersection
of two Segment
s is either an empty array (if they don't intersect) or an array that contains a single object (either Point
or Segment
, depending on the input).