¿Hay más objetos duros u objetos blandos?

19

Tangencialmente inspirado por la apertura del libro What-If.

La entrada es un rectángulo de espacios como una cadena, lista de cadenas, etc., con objetos hechos de #'s dentro:

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

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

Los objetos siempre serán rectángulos que no se crucen ni se crucen. Un objeto blando se define como un objeto que no se llena con #'s en el medio y es solo un borde, un objeto duro es uno que se llena. Un objeto con ancho o alto <=2se considera duro. Todos los objetos son duros o blandos.

Si hay más objetos duros en la entrada, salida "Hard", si es más suave, salida "Soft", si son iguales, salida "Equal".

Este es el , por lo que gana el código más corto en bytes

Casos de prueba

Estos casos no son entradas completas, sino cómo se debe caracterizar cada objeto. La entrada real será como el arte ascii en la parte superior de la pregunta.

Difícil

#

####

##
##

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

Suave

###
# #
###

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

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

Casos de prueba reales

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

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

Hard

###                
###                
###                

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

Equal

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


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

Soft
Maltysen
fuente
2
¿Son estrictas las salidas o se pueden usar 3 salidas no ambiguas (como H / S / E o -1/0/1)?
trichoplax
@trichoplax son estrictos
Maltysen
3
Meta responde en formatos de E / S engorrosos (no quiere decir que no puede hacer lo que elige, sino solo para dar un lugar para que las personas expresen una opinión más fina si lo desean).
trichoplax
@DLosc seguro que está bien, agregando.
Maltysen
@LuisMendo no, agregando.
Maltysen

Respuestas:

8

MAT , 105 104 58 50 49 bytes

¡Gracias a @Neil por una sugerencia que me permitió eliminar 46 bytes!

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

La entrada es una matriz de caracteres 2D, con filas separadas por ;. El ejemplo en el desafío es

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

Aquí hay otro ejemplo:

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

Esto corresponde a

###                
###                
###                

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

y así debería dar 'Equal'.

Como tercer ejemplo, correspondiente a 'Soft',

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

es decir,

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


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

Pruébalo en línea!

Explicación

Esto utiliza convolución 2D para detectar formas. La entrada se convierte en una matriz 2D con 1indicación #y -1para espacio; y se rellena con un marco de -1valores. Esto asegura que también se detecten formas en el borde del campo original.

La máscara detecta un objeto blando

 1   1
 1  -1

que corresponde a la esquina superior izquierda del objeto con un punto interior vacío. Tenga en cuenta que la convolución invierte la máscara, por lo que se define como [-1 1; 1 1]en el código. El número S de posiciones en las cuales la convolución 4es igual es el número total de objetos blandos.

La máscara detecta un objeto (blando o duro)

-1  -1
-1   1

que corresponde a la esquina superior izquierda del objeto junto con algunos puntos exteriores vacíos. Esta máscara es la versión negada de la anterior, por lo que el resultado de convolución anterior se puede reutilizar. Específicamente, el número T de posiciones en las que ese resultado -4es igual es el número total de objetos.

El número H de objetos duros es T - S . La cadena de salida se determina por el signo 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
fuente
1
Entonces, no tengo idea de qué es una convolución, pero ¿no podría simplemente contar todos los objetos (al encontrar, por ejemplo, la esquina superior izquierda) y comparar con el doble de objetos blandos?
Neil
@Neil que se ve muy prometedor, ¡gracias! De esa manera podría reducir de 5 a 2 convoluciones. (Una convolución es esencialmente ver si un patrón específico coincide en alguna posición). Lo intentaré más tarde
Luis Mendo
... o incluso solo 1 convolución! ¡Muchas gracias! 46 bytes de descuento :-) @Neil
Luis Mendo
3
Estaba casi a la par con JS ... @Neil de qué lado estás ;-)
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"

¡Ahorré 2 bytes gracias a @ edc65!

Toma la entrada como una cadena multilínea rellenada con espacios para formar una cuadrícula.

Explicación / Prueba

Muy cerca de la longitud MATL! Básicamente, busca la línea superior de #s de cada objeto, y si la longitud de la línea superior es inferior a 2 o los primeros 2 caracteres debajo de la línea superior son iguales, es difícil, de lo contrario 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")
)

usuario81655
fuente
Parece haber un problema con la entrada de una sola línea; ###vuelve Equal.
Dennis
@ Dennis Tienes razón. Parece que para la entrada de una sola línea, mi código anterior dependía del error que solucioné. Corregido ahora.
user81655
En mi humilde opinión ~g.search(/$/m)es un poco más legible que ~g.search`\n`||-1.
Neil
@Neil True. Hubo un error, por lo que lo agregué rápidamente ||-1para solucionarlo, pero su sugerencia me hizo darme cuenta de que agregar |$a la expresión regular ahorraría 2 bytes de todos modos. ¡Gracias!
user81655
Puede usar solo 1 contadorn=l=... n>l?...:n<l?...:...
edc65
4

Gelatina, 50 49 46 43 38 34 33 32 bytes

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

Pruébalo en línea! o verificar todos los casos de prueba .

Antecedentes

Hay 16 diferentes 2 x 2 patrones de bloques y espacios:

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

De estos, dado que dos objetos nunca se tocarán,

| #|# |
|# | #|

nunca ocurrirá en la entrada, dejándonos con 14 patrones posibles.

Asignando    un valor de 0 y #un valor de 1 , podemos codificar un patrón 2 × 2

|ab|
|cd|

como 2 (2a + c) + (2b + d) = 4a + 2b + 2c + d , dejando los siguientes valores para los 14 patrones.

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

Para patrones parciales 2 × 1 , 1 × 2 o 1 × 1 en el borde inferior y / o derecho, los trataremos como si estuvieran rellenados con espacios, codificándolos como 4a + 2b , 4a + 2c y 4a , respectivamente .

De esta manera, cada objeto (blando o duro) tendrá exactamente un patrón 4 (su esquina inferior derecha); cada objeto blando tendrá exactamente dos 7 patrones (su esquina inferior izquierda y su esquina superior derecha).

Por lo tanto, restando la cantidad de 4 patrones del número de 7 patrones encontrados en la entrada dará (s + h) - 2s = h - s: = d , donde h y s son la cantidad de objetos duros y blandos que forman.

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

Cómo 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
fuente
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 una matriz de Char bidimensional como argumento. Pruébalo en línea!

Cómo funciona

Esto usa casi exactamente la misma idea que mi respuesta de Jelly , con una mejora:

En lugar de contar la cantidad de 4 'y 7 ' s, eliminamos todos los demás números, luego restamos 5.5 al mapa (4, 7) a (-1.5, 1.5) . De esta manera, el signo de la suma de las diferencias resultantes determina la salida correcta.

Dennis
fuente
0

TSQL, 328 249 bytes

Declaración de variables y datos de prueba:

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)

Explicación:

Script está escaneando el texto para el patrón:

      space
space x

Cada uno de esos es el comienzo de una caja

Para esas posiciones, el script verifica el patrón, no es necesario verificar la primera x:

  x
x space 

Cuando eso existe es un objeto blando, de lo contrario es un objeto duro.

t-clausen.dk
fuente