Y a-t-il plus d'objets durs ou d'objets mous

19

Inspiré tangentiellement par l'ouverture du livre What-If.

L'entrée est un rectangle d'espaces sous forme de chaîne, liste de chaînes, etc., avec des objets constitués de #'s à l'intérieur:

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

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

Les objets seront toujours des rectangles sans intersection et sans contact. Un objet mou est défini comme un objet qui n'est pas rempli de #'s au milieu et n'est qu'une bordure, un objet dur est celui qui est rempli. Un objet de largeur ou de hauteur <=2est considéré comme dur. Tous les objets sont durs ou mous.

S'il y a plus d'objets durs dans l'entrée, sortez "Hard", si plus doux, sortez "Soft", s'ils sont égaux, sortez "Equal".

C'est le , donc le code le plus court en octets gagne!

Cas de test

Ces cas ne sont pas des entrées complètes, mais plutôt ce que chaque objet doit être caractérisé. L'entrée réelle sera comme l'art ascii en haut de la question.

Difficile

#

####

##
##

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

Doux

###
# #
###

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

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

Cas de test réels

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

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

Hard

###                
###                
###                

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

Equal

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


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

Soft
Maltysen
la source
2
Les sorties sont-elles strictes, ou peut-on utiliser 3 sorties non ambiguës (telles que H / S / E ou -1/0/1)?
trichoplax
@trichoplax ils sont stricts
Maltysen
3
Méta-réponse sur les formats d'E / S encombrants (pour ne pas dire que vous ne pouvez pas faire ce que vous choisissez, mais simplement pour donner aux gens la possibilité d'exprimer une opinion plus fine s'ils le souhaitent).
trichoplax
@DLosc bien sûr, ajoute-t-il.
Maltysen
@LuisMendo non, en ajoutant.
Maltysen

Réponses:

8

MATL , 105 104 58 50 49 octets

Merci à @Neil pour une suggestion qui m'a permis de supprimer 46 octets!

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

L'entrée est un tableau de caractères 2D, avec des lignes séparées par ;. L'exemple du défi est

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

Voici un autre exemple:

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

Cela correspond à

###                
###                
###                

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

et devrait donc donner 'Equal'.

Comme troisième exemple, correspondant à 'Soft',

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

C'est,

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


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

Essayez-le en ligne!

Explication

Cela utilise la convolution 2D pour détecter les formes. L'entrée est convertie en un tableau 2D avec 1indication #et -1pour l'espace; et est rembourré avec un cadre de -1valeurs. Cela garantit que les formes au bord du champ d'origine sont également détectées.

Un objet mou est détecté par le masque

 1   1
 1  -1

qui correspond au coin supérieur gauche de l'objet avec un point intérieur vide. Notez que la convolution inverse le masque, il est donc défini comme [-1 1; 1 1]dans le code. Le nombre S de positions dans lesquelles la convolution 4est égale est le nombre total d'objets mous.

Un objet (mou ou dur) est détecté par le masque

-1  -1
-1   1

qui correspond au coin supérieur gauche de l'objet avec quelques points extérieurs vides. Ce masque est la version annulée du précédent, donc le résultat de convolution précédent peut être réutilisé. Plus précisément, le nombre T de positions dans lesquelles ce résultat -4est égal est le nombre total d'objets.

Le nombre H d'objets durs est T - S . La chaîne de sortie est déterminé par le signe 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
la source
1
Donc, je n'ai aucune idée de ce qu'est une convolution, mais ne pourriez-vous pas simplement compter tous les objets (en trouvant par exemple le coin supérieur gauche) et en comparant avec le double du nombre d'objets mous?
Neil
@Neil qui semble très prometteur, merci! De cette façon, je pourrais réduire de 5 à 2 circonvolutions. (Une convolution consiste essentiellement à voir si un motif spécifique correspond à une certaine position). Je vais l'essayer plus tard
Luis Mendo
... ou même juste 1 convolution! Merci beaucoup! 46 octets de réduction :-) @Neil
Luis Mendo
3
C'était presque à égalité avec JS ... @Neil de quel côté êtes-vous ;-)
edc65
6

JavaScript (ES6), 123 121 118 octets

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"

Enregistré 2 octets grâce à @ edc65!

Prend l'entrée sous la forme d'une chaîne multiligne remplie d'espaces pour former une grille.

Explication / test

Très proche de la longueur MATL! Fondamentalement, il recherche la ligne supérieure de #s de chaque objet, et si la longueur de la ligne supérieure est inférieure à 2 ou si les 2 premiers caractères sous la ligne supérieure sont identiques, c'est difficile, sinon doux.

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
la source
Il semble y avoir un problème avec l'entrée sur une seule ligne; ###retourne Equal.
Dennis
@Dennis Tu as raison. Il semble que pour la saisie sur une seule ligne, mon code précédent reposait sur le bug que j'ai corrigé. Fixé maintenant.
user81655
IMHO ~g.search(/$/m)est légèrement plus lisible que ~g.search`\n`||-1.
Neil
@Neil True. Il y avait un bogue, j'ai donc hâté de ||-1le corriger, mais votre suggestion m'a fait réaliser que l'ajout |$à l'expression régulière économiserait de toute façon 2 octets. Merci!
user81655
Vous ne pouvez utiliser qu'un seul compteurn=l=... n>l?...:n<l?...:...
edc65
4

Gelée, 50 49 46 43 38 34 33 32 octets

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

Essayez-le en ligne! ou vérifiez tous les cas de test .

Contexte

Il y a 16 différents 2 × 2 modèles de blocs et espaces:

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

Parmi ceux-ci, puisque deux objets ne se toucheront jamais,

| #|# |
|# | #|

ne se produira jamais dans l'entrée, nous laissant avec 14 modèles possibles.

En attribuant    une valeur de 0 et #une valeur de 1 , nous pouvons encoder un motif 2 × 2

|ab|
|cd|

comme 2 (2a + c) + (2b + d) = 4a + 2b + 2c + d , laissant les valeurs suivantes pour les 14 motifs.

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

Pour les motifs partiels 2 × 1 , 1 × 2 ou 1 × 1 sur la bordure inférieure et / ou droite, nous les traiterons comme s'ils étaient remplis d'espaces, en les codant respectivement en 4a + 2b , 4a + 2c et 4a . .

De cette façon, chaque objet (doux ou dur) aura exactement un motif 4 (son coin inférieur droit); chaque objet souple aura exactement deux 7 motifs (son coin inférieur gauche et son coin supérieur droit).

Ainsi, en soustrayant la quantité de 4 motifs du nombre de 7 motifs rencontrés dans l'entrée, vous obtiendrez (s + h) - 2s = h - s: = d , où h et s sont la quantité d'objets durs et mous qu'ils forment.

Nous imprimons dur si d> 0 , doux si d <0 et égal si d = 0 .

Comment ça fonctionne

Ḥ+Ḋ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
la source
1

Julia, 99 95 93 octets

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

!attend un tableau Char bidimensionnel comme argument. Essayez-le en ligne!

Comment ça fonctionne

Cela utilise presque exactement la même idée que ma réponse Jelly , avec une amélioration:

Au lieu de compter le nombre de 4 et de 7 , nous supprimons tous les autres nombres, puis soustrayons 5,5 pour mapper (4, 7) à (-1,5, 1,5) . De cette façon, le signe de la somme des différences résultantes détermine la sortie correcte.

Dennis
la source
0

TSQL, 328 249 octets

Déclaration des variables et des données de test:

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)

Code:

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)

Code dégonflé:

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)

Explication:

Le script analyse le texte du motif:

      space
space x

Chacun d'eux est le début d'une boîte

Pour ces positions, le script vérifie ensuite le motif, pas besoin de vérifier le premier x:

  x
x space 

Quand cela existe, c'est un objet mou, sinon c'est un objet dur.

t-clausen.dk
la source