Posso morar aqui?

16

No jogo Terraria , uma das mecânicas do jogo envolve a construção de casas para que um NPC possa se mudar. Existe um conjunto estrito de regras para o que conta como uma casa válida ou não. Aqui está a lista de regras:

  1. A área total da casa deve ter pelo menos 60 azulejos quadrados, mas menos de 750. Além disso, o tamanho da casa, incluindo a estrutura externa, deve ser pelo menos um destes:

    5x12
    6x10
    7x9
    8x8
    9x7
    10x6
    12x5
    15x4
    

    por uma questão de simplicidade, você pode assumir com segurança que: a) Todas as casas de entrada serão retângulos eb) nenhum bloco sólido #estará dentro da casa. Aqui está o nosso quadro 12x6 (desenhado em belo ASCII):

    ############
    #          #
    #          #
    #          #
    #          #
    ############
    
  2. A casa deve ser coberta por paredes de fundo. Não são ladrilhos sólidos, mas uma parede atrás da casa na terceira dimensão. Os furos são permitidos, mas nenhum furo pode ser maior que 4x4. Se houver uma linha ou coluna de 5 ou mais caracteres de espaço seguidos, esse é um buraco maior que 4x4 e a casa é inválida. Vários orifícios também são permitidos, mas deve haver pelo menos uma única parede.

    ############
    #**********#
    #**********#
    #**********#
    #**********#
    ############
    
    ############
    #*    *    #
    #*    *    #
    #*    *    #
    #******    #
    ############  (Still acceptable since neither hole is larger than 4x4 and there is a separator)
    
    ############
    #    ******#
    #***    ***#
    #    ******#
    #***    ***#
    ############  (Also still valid. No row or column of blank spaces is longer or taller than 4.)
    
  3. Deve haver uma entrada. Pode ser uma porta |lateral ou uma plataforma -no chão ou no teto. Se a única entrada estiver em uma esquina, o NPC não poderá entrar. Além disso, se você tiver uma plataforma como base, deverá ter pelo menos um único bloco sólido para o NPC permanecer. Este bloco sólido não pode ser diretamente adjacente às paredes laterais à esquerda ou à direita. Estas são todas as casas válidas com entradas:

    ############
    #**********#
    |**********#
    #**********#
    #**********|
    ############  (Multiple doors, or doors up high are okay)
    
    ############
    #**********#
    #**********#
    #**********#
    #**********#
    #######----#
    
    #----#######
    #**********#
    #**********#
    #**********#
    #**********#
    ############
    
  4. Deve haver pelo menos uma fonte de luz $, mesa Te cadeira C, embora mais seja permitido. A fonte de luz pode estar no ar ou no chão, mas a mesa e a cadeira devem estar no chão, por exemplo, na linha mais baixa.

    ############
    #**********#
    #**********#
    #***$******|
    #****TC****|
    ############
    

    Além disso, você pode supor que haja uma parede atrás de qualquer móvel, para que uma tocha, cadeira ou mesa possa contar como um separador entre dois orifícios.

    ############
    #*    *    #
    #*    *    #
    #*    $    #
    #**TC******|
    ############
    

O desafio

Você deve escrever a função mais curta que leva uma casa como uma sequência ASCII e retorna verdadeiro / falso, independentemente de ser um alojamento válido. Você pode considerar isso como uma sequência delimitada por nova linha, uma lista de sequências ou qualquer outra maneira, desde que seja razoável. Por minha causa, inclua um programa curto para que eu possa testar se funciona corretamente ou não.

Para referência, estas são todas entradas inválidas:

############
-**********#
-****$*****#
-**********#
-******TC**#
############  (You can't have platforms on the sidewalls)

###########-
#**********#
#**********#
#****$*****#
#**T***C***#
###########|  (NPC can't enter because the only entrances are on the corner)

############
#**********#
#******$***#
#**********#
#T****C****#
##--------##  (NPC has nowhere to stand)

############
#**********#
#**********#
#**********#
#**$**TC***#
##########|#  (Door cannot be in the floor or ceiling)

############
#**********#
#**********#
#**********#
|**   T C  #
############  (Since table and chair do not count as a background wall, the hole in background is too wide)

####### ####
#**********#
#**********#
#****$*****#
#**T***C***|
############  (There's a hole in the frame.)


###########################################################################
#                                                                         #
#                                                                         #
#                                                                         #
#                                                                         #
#                                                                         #
#                                                                         #
#                                                                         #
#                                                                         #
#                                                                         #
###########################################################################  (House is 75x11, which is too big.)

Entre os melhores

DJMcMayhem
fonte
6
Desafio legal, companheiro de Terraria.
Rɪᴋᴇʀ
Podemos assumir que os buracos serão retangulares? Caso contrário, isso poderia usar um caso de teste em que o todo não se encaixa em 4x4, mas que nunca contém mais de 4 espaços seguidos.
Martin Ender
Há muitos pontos que acho incertos. 1. O quadro precisa ser retangular? " todas as casas serão retângulos " sugere que sim, mas não descarta claramente os quadros que não são retangulares, mas entram nos quatro cantos da caixa delimitadora alinhada aos eixos. E, possivelmente, buracos podem ser cercados #. 2. Como Martin perguntou, o que exatamente " nenhum buraco pode ser maior que 4x4 " significa? (Observe também que não foi até a terceira leitura que eu entendi qual era o buraco. Você deve escrever as especificações para as pessoas que não jogaram o jogo).
Peter Taylor
1
3. " Este bloco sólido não pode ser diretamente adjacente às paredes " - o que é uma parede? Do ponto 2, parece ser *, mas isso excluiria os exemplos de portas válidas. 4. " no chão " significa "na penúltima linha" ou "acima de um #"? 5. " Isso não se aplica a mesas e cadeiras. " Isso significa que um orifício 4x4 com um Tou Cdiretamente abaixo dele é muito grande? 6. " NPC não pode entrar porque as únicas entradas estão na esquina " Eu não acho que a especificação tenha dito algo sobre as esquinas. Podem existir -ou |se existem outras portas?
Peter Taylor
7. Se as entradas em uma esquina são um problema porque não admitem acesso, isso significa que cada uma *deve ser alcançável a partir de uma entrada? Ou são isolados *no meio de buracos permitidos, buracos que cortam a sala inteira em dois, com apenas um lado com uma entrada permitida e entradas que vão diretamente para um buraco permitido?
Peter Taylor

Respostas:

2

Python 2, 503 439 bytes

Não é super curto, mas é uma solução. Deixe-me saber se você vê algo para jogar golfe. Eu recomendo olhar também para a minha versão não-gasta, pois é realmente legível.

Edit: Todos os ifs fora de um loop foram combinados na parte inferior.

def f(s):
 s=s.split("\n");e=l=0;h=len(s);w=len(s[0])
 for c in s[0][1:-1]+s[-1][1:-1]:
    if(c in"#-")<1:return 0
    if"-"==c:e=1
 for r in s[1:-1]:
    if(r[0]in"#|")*(r[-1]in"#|")<1or" "*5in r:return 0
    if"$"in r:l=1
 for r in zip(*s):
    if" "*5in`r`[2::5]:return 0
 if(h*w<60)+(h*w>749)+(w<5)+(h<4)or" "in s[0][0]+s[0][-1]+s[-1][0]+s[-1][-1]or("T"in s[-2])*("C"in s[-2])*l<1or("#"in s[-1][2:-2])<1or"|"in"".join(s[1:-1])<1>e:return 0
 return 1

Experimente online

Ungolfed:

Também mostra o motivo pelo qual o resultado é False, para fins de depuração.

def f(s):

    # check dimensions
    s=s.split("\n")
    h=len(s)
    w=len(s[0])
    if h*w < 60 or h*w > 749 or w<5 or h<4: return False,"Size"

    # top / bottom
    e=0
    for c in s[0][1:-1]+s[-1][1:-1]:
        if(c in"#-")<1:return False,"T/B"

        # entrance
        if"-"==c:e=1

    # no spaces in corners -_-
    if" "in s[0][0]+s[0][-1]+s[-1][0]+s[-1][-1]: return False,"Corner"

    # light, table, chair
    l=t=c=0

    # left / right
    for r in s[1:-1]:
        if(r[0]in"#|")*(r[-1]in"#|")<1: return False,"L/R"

        # walls, put above
        if" "*5in r: return False,"Walls"

        # light
        if"$"in r:l=1

    # table, chair
    if"T"in s[-2]:t=1
    if"C"in s[-2]:c=1

    if l*t*c<1: return False,"L/T/C"

    # wall columns
    for r in zip(*s): # Transpose
        if" "*5in`r`[2::5]: # Tuple to string
            return False,"Walls"

    # entrance
    if"|"in"".join(s[1:-1])<1>e: return False,"Entrance"

    # place to stand
    if("#"in s[-1][2:-2])<1: return False,"Stand"

    return True

Versão não destruída online

mbomb007
fonte