Contar arranjos de vedação máxima

9

fundo

Eu quero construir uma cerca. Para isso, coletei vários postes e os colei no chão. Também colecionei muitas pranchas que pregarei nos bastões para fazer a cerca. Costumo me empolgar ao construir coisas, e provavelmente continuarei pregando as tábuas nos postes até que não haja mais lugar para colocá-las. Eu quero que você enumere as possíveis cercas que eu possa acabar.

Entrada

Sua entrada é uma lista de coordenadas inteiras bidimensionais que representam as posições dos polos, em qualquer formato conveniente. Você pode assumir que ele não contém duplicatas, mas não pode assumir nada sobre sua ordem.

As placas são representadas por linhas retas entre os pólos e, por simplicidade, consideramos apenas placas horizontais e verticais. Dois pólos podem ser unidos por uma placa se não houver outros pólos ou placas entre eles, o que significa que as placas não podem se cruzar. Um arranjo de postes e placas é máximo se nenhuma nova placa puder ser adicionada a ela (equivalentemente, existe um poste ou uma placa entre dois postes alinhados horizontal ou verticalmente).

Resultado

Sua saída é o número de arranjos máximos que podem ser construídos usando os pólos.

Exemplo

Considere a lista de entrada

[(3,0),(1,1),(0,2),(-1,1),(-2,0),(-1,-1),(0,-2),(1,-1)]

Visto de cima, o arranjo correspondente dos pólos é mais ou menos assim:

  o
 o o
o    o
 o o
  o

Existem exatamente três disposições máximas que podem ser construídas usando esses polos:

  o        o        o
 o-o      o|o      o-o
o----o   o||| o   o| | o
 o-o      o|o      o-o
  o        o        o

Assim, a saída correta é 3.

Regras

Você pode escrever uma função ou um programa completo. A menor contagem de bytes vence e as brechas padrão não são permitidas.

Casos de teste

[] -> 1
[(0,0),(1,1),(2,2)] -> 1
[(0,0),(1,0),(2,0)] -> 1
[(0,0),(0,1),(1,0),(1,1)] -> 1
[(1,0),(0,1),(-1,0),(0,-1)] -> 2
[(3,0),(1,1),(0,2),(-1,1),(-2,0),(-1,-1),(0,-2),(1,-1)] -> 3
[(0,0),(4,0),(1,1),(1,-2),(3,1),(3,-2),(2,-1),(4,-1)] -> 3
[(0,0),(4,0),(1,1),(1,-2),(3,1),(3,-2),(2,-1),(4,-1),(0,-1)] -> 4
[(0,0),(4,0),(1,1),(1,-2),(3,1),(3,-2),(2,-1),(0,-1),(2,2)] -> 5
[(0,0),(4,0),(1,1),(1,-2),(3,1),(3,-2),(2,-1),(4,-1),(0,-1),(2,2)] -> 8
Zgarb
fonte
11
O exemplo parece ter (-2,0) duas vezes. Um desses deve ser (2,0)?
Isaacg
@isaacg Na verdade, deveria ser (0,-2), boa captura. Mudando agora.
Zgarb 12/03

Respostas:

5

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}]])&

Esta é uma função sem nome que pega as coordenadas como aninhadas Liste retorna um número inteiro. Ou seja, você pode dar um nome e chamá-lo ou simplesmente anexá-lo

@ {{3, 0}, {1, 1}, {0, 2}, {-1, 1}, {-2, 0}, {-1, -1}, {0, -2}, {1, -1}}

Com recuo:

(
  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}
    ]
  ]
) &

Eu não posso nem começar a expressar o quão ingênua essa implementação é ... definitivamente não poderia ser mais força bruta ...

  • Obtenha todos os pares (não ordenados) de pólos.
  • Classifique cada par e todos os pares em uma ordem canônica.
  • Descarte pares que não compartilham uma coordenada (ou seja, que não são conectáveis ​​por uma linha ortogonal).
  • Os pares de descarte podem ser formados a partir de dois pares mais curtos (de modo que o--o--oproduz apenas duas cercas em vez de três).
  • Obtenha todos os subconjuntos desses pares - ou seja, todas as combinações possíveis de cercas.
  • Filtre as combinações que têm cercas que se cruzam.
  • Conte o número de conjuntos de vedações resultantes para os quais nenhum superconjunto estrito pode ser encontrado na lista.

Surpreendentemente, ele resolve todos os casos de teste praticamente imediatamente.

Um truque realmente interessante que eu descobri para isso é o uso de Orderlessreduzir o número de padrões que eu tenho que combinar. Essencialmente, quando quero abandonar conjuntos de cercas com cercas cruzadas, preciso encontrar um par de cercas verticais e horizontais e verificar a condição delas. Mas não sei em que ordem eles aparecerão. Como os padrões de lista normalmente dependem da ordem, isso resultaria em dois padrões realmente longos. Então, em vez disso, substituo pela lista circundante por uma função tcom t @@@- que não está definida, portanto é mantida como está. Mas essa função é Orderless, então eu posso verificar uma única ordem no padrão, e o Mathematica verificará todas as permutações. Depois, coloquei as listas de volta no lugar List @@@.

Eu gostaria que houvesse um interno que fosse a) Orderless, b) não Listable e c) não definido para 0 argumentos ou argumentos de lista. Então eu poderia substituir tpor isso. Mas não parece haver um operador assim.

Martin Ender
fonte
Quando você pensa se o Mathematica faz certo ou rápido o suficiente, a resposta é "sim".
seequ
Bem, isso é tão ingênuo quanto a minha implementação de referência. : P
Zgarb 13/03/2015
1

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]

Uso: p [(1,0),(0,1),(-1,0),(0,-1)]. Resultado:2

Como funciona:

  • crie todas as sublistas da lista de entrada e mantenha aquelas com dois elementos e com coordenadas x iguais ou y iguais. Esta é uma lista de todos os pares de postes onde uma cerca pode ser construída no meio.
  • criar todos os sublistas dele
  • adicione placas para todas as listas
  • remover listas onde uma coordenada xy aparece duas vezes (placas e postes)
  • remova listas duplicadas (somente placas) para lidar com várias listas vazias, devido a postes diretamente adjacentes (por exemplo, (1,0) e (1,1))
  • mantenha aqueles que não são uma sublist estrita de outra lista
  • contar listas restantes
nimi
fonte