| Bytes | Lang | Time | Link |
|---|---|---|---|
| 462 | Python3 | 240831T172859Z | Ajax1234 |
| 318 | Haskell | 150316T200017Z | nimi |
| 301 | Mathematica | 150312T203045Z | Martin E |
Python3, 462 bytes
R=range
def f(p):
q,s,F=[({*p},{*p},[])],[],[]
for p,P,O in q:
T=1
for x,y in p:
for X,Y in p-{(x,y)}:
if(x==X or y==Y)and(S:=sorted([(x,y),(X,Y)]))not in O and not P&(K:={*{(x,min(y,Y)+i)for i in R(1,abs(y-Y))},*{(min(x,X)+i,y)for i in R(1,abs(x-X))}})and not any(len(I)>len(O)and all(w in I for w in O+[S])for I in s):q+=[(p,P|K,O+[S])];T=0;s+=[O+[S]]
if T:F+=[O]
return sum(not any(len(I)>len(i)and all(w in I for w in i)for I in F)for i in F)
Haskell, 318 bytes
import Data.List
s=subsequences
k[(_,a,b),(_,c,d)]|a==c=f(\w->(1,a,w))b d|1<2=f(\w->(2,w,b))a c
f t u v=[t x|x<-[min u v+1..max u v-1]]
q l=nub[x|x<-map(k=<<)$s[a|a@[(_,n,m),(_,o,p)]<-s l,n==o||m==p],x++l==nubBy(\(_,a,b)(_,c,d)->a==c&&b==d)(x++l)]
m=q.map(\(a,b)->(0,a,b))
p l=sum[1|x<-m l,all(\y->y==x||x\\y/=[])$m l]
Usage: p [(1,0),(0,1),(-1,0),(0,-1)]. Output: 2
How it works:
- create all sublists of the input list and keep those with two elements and with either equal x or equal y coordinates. This is a list of all pairs of poles where a fence can be build in between.
- create all sublists of it
- add boards for every list
- remove lists where a x-y coordinate appears twice (boards and poles)
- remove duplicate lists (boards only) to handle multiple empty lists, because of directly adjacent poles (e.g. (1,0) and (1,1))
- keep those which are not a strict sublist of another list
- count remaining lists
Mathematica, 301 bytes
(t~SetAttributes~Orderless;u=Subsets;c=Complement;l=Select;f=FreeQ;Count[s=List@@@l[t@@@u[Sort@l[Sort/@#~u~{2},!f[#-#2&@@#,0]&]//.{a___,{x_,y_},{x_,z_},b___,{y_,z_},c___}:>{a,{x,y},b,{y,z},c}],f[#,t[{{a_,b_},{a_,c_}},{{d_,e_},{f_,e_}},___]/;d<a<f&&b<e<c]&],l_/;f[s,k_List/;k~c~l!={}&&l~c~k=={},{1}]])&
This is an unnamed function which takes the coordinates as a nested List and returns an integer. That is, you can either give it a name and call it, or just append
@ {{3, 0}, {1, 1}, {0, 2}, {-1, 1}, {-2, 0}, {-1, -1}, {0, -2}, {1, -1}}
With indentation:
(
t~SetAttributes~Orderless;
u = Subsets;
c = Complement;
l = Select;
f = FreeQ;
Count[
s = List @@@ l[
t @@@ u[
Sort @ l[
Sort /@ #~u~{2},
!f[# - #2 & @@ #, 0] &
] //. {a___, {x_, y_}, {x_, z_}, b___, {y_, z_}, c___} :>
{a, {x, y}, b, {y, z}, c}
],
f[
#,
t[{{a_, b_}, {a_, c_}}, {{d_, e_}, {f_, e_}}, ___]
/; d < a < f && b < e < c
] &
],
l_ /; f[
s,
k_List /; k~c~l != {} && l~c~k == {},
{1}
]
]
) &
I can't even begin to express how naive this implementation is... it definitely couldn't be more brute force...
- Get all (unordered) pairs of poles.
- Sort each pair and all pairs into a canonical order.
- Discard pairs which don't share one coordinate (i.e. which aren't connectible by an orthogonal line).
- Discard pairs can be formed from two shorter pairs (so that
o--o--oyields only two fences instead of three). - Get all subsets of those pairs - i.e. all possible combinations of fences.
- Filter out combinations which have fences crossing each other.
- Count the number of resulting fence sets for which no strict superset can be found in the list.
Surprisingly it does solve all the test cases virtually immediately.
A really neat trick I discovered for this is the use of Orderless to cut down on the number of patterns I have to match. Essentially, when I want to ditch fence sets with crossing fences, I need to find a pair of vertical and horizontal fence and check the condition on them. But I don't know what order they'll appear in. Since list patterns are normally order dependent, this would result in two really long patterns. So instead I replace with surrounding list with a function t with t @@@ - which isn't defined so it is held as it is. But that function is Orderless, so I can just check a single order in the pattern, and Mathematica will check it against all permutations. Afterwards, I put the lists back in place with List @@@.
I wish there was a built-in that is a) Orderless, b) not Listable and c) not defined for 0 arguments or list arguments. Then I could replace t by that. But there doesn't seem to be such an operator.