Existem mais objetos rígidos ou objetos flexíveis

19

Inspirado tangencialmente pela abertura do livro What-If.

A entrada é um retângulo de espaços como uma string, lista de strings, etc., com objetos feitos de #dentro:

########          
#      #          
########          

   ###        ####
   ###        ####
   ###             

Os objetos sempre serão retângulos sem interseção, sem toque. Um objeto flexível é definido como um objeto que não é preenchido com #s no meio e é apenas uma borda; um objeto rígido é aquele que é preenchido. Um objeto com largura ou altura <=2é considerado rígido. Todos os objetos são rígidos ou flexíveis.

Se houver mais objetos rígidos na entrada, saída "Hard", se mais suave, saída "Soft", se forem iguais, saída "Equal".

Isso é , então o código mais curto em bytes vence!

Casos de teste

Esses casos não são entradas completas, mas como cada objeto deve ser caracterizado. A entrada real será como a arte ASCII no topo da questão.

Difícil

#

####

##
##

##########
##########
##########

Suave

###
# #
###

###################
#                 #
#                 #
#                 #
###################

####
#  #
#  #
#  #
#  #
#  #
#  #
#  #
####

Casos de teste reais

########          
#      #          
########          

   ###        ####
   ###        ####
   ###             

Hard

###                
###                
###                

###################
#                 #
#                 #
#                 #
###################

Equal

   ######    
   #    #    
   ######    
          ###
   ##  #  # #
          ###


 ########    
 #      #    
 ########  

Soft
Maltysen
fonte
2
As saídas são rigorosas ou podem ser usadas quaisquer 3 saídas não ambíguas (como H / S / E ou -1/0/1)?
Trichoplax
@trichoplax eles são rigorosos
Maltysen
3
Meta-resposta em formatos de E / S complicados (para não dizer que você não pode fazer o que escolher, mas apenas para permitir que as pessoas expressem uma opinião mais refinada, se assim o desejarem).
Trichoplax
@ DLosc certeza de que está tudo bem, adicionando.
Maltysen
@LuisMendo não, adicionando.
Maltysen

Respostas:

8

MATL , 105 104 58 50 49 bytes

Obrigado a @ Neil por uma sugestão que me permitiu remover 46 bytes!

2\TTYaEq4:HeqgEqZ+K/Zot0>+ss'Soft Hard Equal'Ybw)

Entrada é uma matriz de caracteres 2D, com linhas separadas por ;. O exemplo do desafio é

['########          ';'#      #          ';'########          ';'                  ';'   ###        ####';'   ###        ####';'   ###            ']

Aqui está outro exemplo:

['###                ';'###                ';'###                ';'                   ';'###################';'#                 #';'#                 #';'#                 #';'###################']

Isso corresponde a

###                
###                
###                

###################
#                 #
#                 #
#                 #
###################

e assim deve dar 'Equal'.

Como um terceiro exemplo, correspondente a 'Soft',

['   ######    ';'   #    #    ';'   ######    ';'          ###';'   ##  #  # #';'          ###';'             ';'             ';' ########    ';' #      #    ';' ########    ']

isso é,

   ######    
   #    #    
   ######    
          ###
   ##  #  # #
          ###


 ########    
 #      #    
 ########  

Experimente online!

Explicação

Isso usa convolução 2D para detectar formas. A entrada é convertida em uma matriz 2D com 1indicação #e -1espaço; e é preenchido com uma moldura de-1 valores. Isso garante que as formas na borda do campo original também sejam detectadas.

Um objeto macio é detectado pela máscara

 1   1
 1  -1

que corresponde ao canto superior esquerdo do objeto com um ponto interior vazio. Observe que a convolução inverte a máscara, portanto é definida como [-1 1; 1 1]no código. O número S de posições nas quais a convolução 4é igual é o número total de objetos flexíveis.

Um objeto (macio ou rígido) é detectado pela máscara

-1  -1
-1   1

que corresponde ao canto superior esquerdo do objeto, juntamente com alguns pontos exteriores vazios. Essa máscara é a versão negada da anterior, portanto, o resultado da convolução anterior pode ser reutilizado. Especificamente, o número T de posições em que esse resultado é igual-4 é é o número total de objetos.

O número H de objectos duros é T - S . A cadeia de saída é determinada pelo sinal de S - H = 2 * S - T .

2\                 % Input. Modulo 2: '#' gives 1, ' ' gives 0
TTYa               % Add a frame of zeros
Eq                 % Convert 0 to -1
4:HeqgEq           % Generate mask [-1 1; 1 1], for soft objects
Z+                 % 2D convolution, preserving size
K/Zo               % Divide by 4 and round towards 0. Gives 1 or -1 for 4 or -4
t0>                % Duplicate. 1 for positive entries (soft objects), 0 otherwise
+                  % Add. This corresponds to the factor 2 that multiplies number S
ss                 % Sum of 2D array. Gives 2*S-T
'Soft Hard Equal'  % Push this string
Yb                 % Split by spaces. Gives cell array
w)                 % Swap. Apply (modular) index to select one string
Luis Mendo
fonte
11
Então, eu não tenho idéia do que é uma convolução, mas você não pode apenas contar todos os objetos (encontrando, por exemplo, o canto superior esquerdo) e comparando com o dobro do número de objetos flexíveis?
Neil
@ Neil que parece muito promissor, obrigado! Dessa forma, eu poderia reduzir de 5 para 2 convoluções. (Uma convolução é essencialmente ver se um padrão específico corresponde em alguma posição). Vou tentar mais tarde
Luis Mendo
... ou até apenas 1 convolução! Muito obrigado! 46 bytes off :-) @Neil
Luis Mendo
3
Era quase a par com JS ... @Neil que lado você está ;-)
edc65
6

JavaScript (ES6), 123 121 118 bytes

s=>s.replace(/#+/g,(m,i)=>s[i+l]>" "?0:n+=!m[1]|s[i-l+1]==s[i-l]||-1,n=l=~s.search`
|$`)|n>l?"Hard":n<l?"Soft":"Equal"

Economizou 2 bytes graças a @ edc65!

Recebe entrada como uma cadeia de linhas multilinha preenchida com espaços para formar uma grade.

Explicação / Teste

Muito perto do comprimento do MATL! Basicamente, ele procura a linha superior de #s de cada objeto e, se o comprimento da linha superior for menor que 2 ou os 2 primeiros caracteres abaixo da linha superior forem iguais, é difícil, caso contrário é suave.

var solution =

s=>
  s.replace(/#+/g,(m,i)=>        // for each run of consecutive # characters
    s[i+l]>" "?                  // if the position above the match contains a #
      0                          // do nothing (this object has already been counted)
    :n+=                         // add 1 to the counter (hard) if
      !m[1]                      // the match is only 1 # wide
      |s[i-l+1]==s[i-l]          // or the characters below are the same
      ||-1,                      // else decrement the counter (soft)
    n=                           // n = counter, hard objects increase n, soft decrease
    l=~s.search`\n|$`            // l = (negative) line length
  )
  |n>l?"Hard":n<l?"Soft":"Equal" // return the result string

// Test
document.write("<pre>" + [`

########          
#      #          
########          
                  
   ###        ####
   ###        ####
   ###            

`,`

###                
###                
###                
                   
###################
#                 #
#                 #
#                 #
###################

`,`

   ######    
   #    #    
   ######    
          ###
   ##  #  # #
          ###
             
             
 ########    
 #      #    
 ########    

`,`

########          
#      #          
########          
                  
   ###        ####
   # #        ####
   ###            

`,`

########          
#      #          
########          
                  
   ###  ###   ####
   ###  # #   ####
   ###  ###       

`,`

#

`,`

##

`,`

#
#

`,`

###
# #
###

`].map((test) => solution(test.slice(2, -2))).join("\n")
)

user81655
fonte
Parece haver um problema com a entrada de linha única; ###retorna Equal.
Dennis
@Dennis Você está certo. Parece que, para entrada em linha única, meu código anterior contava com o bug que eu corrigi. Corrigido agora.
precisa saber é o seguinte
IMHO ~g.search(/$/m)é um pouco mais legível do que ~g.search`\n`||-1.
19416 Neil
@Neil True. Houve um erro, então eu apressei ||-1-me a corrigi-lo, mas sua sugestão me fez perceber que adicionar |$ao regex economizaria 2 bytes de qualquer maneira. Obrigado!
precisa saber é o seguinte
Você poderia usar apenas 1 contadorn=l=... n>l?...:n<l?...:...
edc65
4

Geléia, 50 49 46 43 38 34 33 32 bytes

Ḥ+ḊZ
>⁶ÇÇFµċ7_ċ4$Ṡị“¤Ỵf“¢*ɦ“¡⁺ƒ»

Experimente online! ou verifique todos os casos de teste .

fundo

Existem 16 padrões 2 × 2 diferentes de blocos e espaços:

|  |  |  | #|  | #| #|# | #|# |# |##|# |##|##|##|
|  | #|# |  |##| #|# |  |##| #|# |  |##| #|# |##|

Destes, como dois objetos nunca se tocam,

| #|# |
|# | #|

nunca ocorrerá na entrada, deixando-nos com 14 padrões possíveis.

Atribuindo    um valor de 0 e #um valor de 1 , podemos codificar um padrão 2 × 2

|ab|
|cd|

como 2 (2a + c) + (2b + d) = 4a + 2b + 2c + d , deixando os seguintes valores para os 14 padrões.

|  |  |  | #|  | #|# | #|# |##|# |##|##|##|
|  | #|# |  |##| #|  |##|# |  |##| #|# |##|
  0  1  2  2  3  3  4  5  6  6  7  7  8  9

Para padrões parciais 2 × 1 , 1 × 2 ou 1 × 1 na borda inferior e / ou direita, nós os trataremos como se estivessem preenchidos com espaços, codificando-os como 4a + 2b , 4a + 2c e 4a , respectivamente .

Dessa forma, cada objeto (macio ou rígido) terá exatamente um padrão 4 (seu canto inferior direito); cada objeto macio terá exatamente dois padrões 7 (seu canto inferior esquerdo e seu canto superior direito).

Assim, subtrair a quantidade de 4 padrões do número de 7 padrões encontrados na entrada produzirá (s + h) - 2s = h - s: = d , em que h e s são a quantidade de objetos rígidos e flexíveis que eles formam.

Imprimimos Hard se d> 0 , Soft se d <0 e Igual se d = 0 .

Como funciona

Ḥ+ḊZ                         Helper link. Input: M (n×m matrix)

Ḥ                            Unhalve; multiply all entries of M by 2.
  Ḋ                          Dequeue; remove the first row of M.
 +                           Perform vectorized addition.
                             This returns 2 * M[i] + M[i + 1] for each row M[i].
                             Since the M[n] is unpaired, + will not affect it,
                             as if M[n + 1] were a zero vector.
   Z                         Zip; transpose rows with columns.


>⁶ÇÇFµċ7_ċ4$Ṡị“¤Ỵf“¢*ɦ“¡⁺ƒ»  Main link. Input: G (character grid)

>⁶                           Compare each character with ' ', yielding 1 for '#'
                             and 0 for ' '.
  Ç                          Call the helper link.
                             This will compute (2a + c) for each pattern, which is
                             equal to (2b + d) for the pattern to its left.
   Ç                         This yields 2(2a + c) + (2b + d) for each pattern.
    F                        Flatten; collect all encoded patterns in a flat list.

     µ                       Begin a new, monadic link. Argument: A (list)
      ċ7                     Count the amount of 7's.
         ċ4$                 Count the amount of 4's.
        _                    Subtract the latter from the former.
            Ṡ                Yield the sign (1, -1 or 0) of the difference.
              “¤Ỵf“¢*ɦ“¡⁺ƒ»  Yield ['Hard', 'Soft', Equal'] by indexing into a
                             built-in dictionary.
             ị               Retrieve the string at the corresponding index.
Dennis
fonte
1

Julia, 99 95 93 bytes

~=t->2t'+[t[2:end,:];0t[1,:]]'
!x=("Hard","Equal","Soft")[sign(~~(x.>32)∩(4,7)-5.5|>sum)+2]

!espera uma matriz Char bidimensional como argumento. Experimente online!

Como funciona

Isso usa quase exatamente a mesma idéia da minha resposta Jelly , com uma melhoria:

Em vez de contar a quantidade de 4 e 7 , removemos todos os outros números e subtraímos 5,5 para mapear (4, 7) para (-1,5, 1,5) . Dessa forma, o sinal da soma das diferenças resultantes determina a saída correta.

Dennis
fonte
0

TSQL, 328 249 bytes

Declarando variáveis ​​e dados de teste:

DECLARE @l int = 20
DECLARE @ varchar(max)=''
SELECT @+=LEFT(x + replicate(' ', @l), @l)
FROM (values
(' xxxx'),
(' xxxx'),
(' xxxx'),
('x'),
(''),
('xxx'),
('x x  xxx'),
('xxx  x x'),
('     xxx    ')) x(x)

Código:

SELECT substring('Soft EqualHard',sign(sum(iif(substring(@,N,@l+2)like'xx'+replicate('_', @l-2)+'x ',-1,1)))*5+6,5)FROM(SELECT row_number()OVER(ORDER BY Type)N FROM sys.all_objects)x WHERE n<=len(@)AND' x'=substring(@,N-1,2)AND''=substring(@,N-@l,1)

Código desinflado:

SELECT
  substring('Soft EqualHard',
    sign(sum(iif(substring(@,N,@l+2)like'xx'+replicate('_', @l-2)+'x ',-1,1)))*5+6,5)
FROM(SELECT row_number()OVER(ORDER BY Type)N FROM sys.all_objects)x
WHERE n<=len(@)AND' x'=substring(@,N-1,2)AND''=substring(@,N-@l,1)

Explicação:

O script está varrendo o texto para o padrão:

      space
space x

Cada um desses é o começo de uma caixa

Para essas posições, o script está verificando o padrão, não precisa verificar o primeiro x:

  x
x space 

Quando isso existe, é um objeto flexível, caso contrário, é um objeto rígido.

t-clausen.dk
fonte