Le tapis d'alphabet de mes enfants est-il correctement groupé par couleurs?

14

Mes enfants ont un tapis d'alphabet avec lequel jouer, quelque chose comme ceci:

Tapis Alphabet

Après des mois avec les carreaux du tapis placés au hasard, je me suis fatigué et j'ai placé tous les carreaux du tapis regroupés par sections en fonction de leurs couleurs de fond. Donc, si les lettres représentent la couleur d'arrière-plan, j'ai un tapis comme celui-ci:

AABBCDDDE
ABBCCCDEE
ABCCCCDDE
AACCCDDEE
AAAACCCCE
AAAAAACCC

Ainsi, pour les couleurs A, B, C, D et E, il existe toujours un moyen de connecter toutes les tuiles avec la même couleur de fond horizontalement ou verticalement dans le passe-partout. C'est ce que j'appelle un tapis correctement groupé par couleurs . Vous pouvez voir les groupes de l'exemple précédent dans les tableaux suivants:

AA
A
A
AA
AAAA
AAAAAA

  BB
 BB
 B

    C
   CCC
  CCCC
  CCC
    CCCC
      CCC

     DDD
      D
      DD
     DD

        E
       EE
        E
       EE
        E

De plus, il n'y a qu'un seul groupe pour chaque couleur, donc ce ne serait pas valide:

ABA
ABA

Parce que les tuiles de couleur A ne sont pas regroupées dans un seul groupe. Cela ne serait pas non plus valide car les tuiles ne se connectent pas horizontalement ou verticalement:

AB
BA

Le défi

Étant donné un tableau bidimensionnel de caractères dans la plage ASCII imprimable (n'a pas besoin d'être carré tant que la taille des deux dimensions est égale ou supérieure à 1), vérifiez si le tableau représente un tapis correctement groupé par couleurs (chaque caractère différent du tableau représente une couleur différente). L'entrée peut être dans n'importe quel format raisonnable tant qu'elle représente un tableau de caractères à 2 dimensions (tableau de caractères 2D, tableau de chaînes de même longueur, etc.), et la sortie doit être une paire de valeurs true et falsey (0 / 1, 't' / 'f', true / false, peu importe tant que quelque chose est retourné et que les valeurs de retour sont cohérentes entre les entrées).

Il s'agit de code-golf, donc le programme / fonction / méthode / lambda le plus court pour chaque langue peut gagner!

Exemples

A    truthy

AB
AB   truthy

AB
BA   falsey

ABCDE    truthy

ABCDC    falsey

**::dd22
***:d222
*:::::22    truthy

$$$%%%&&
$$%%&&&&
&&$$$%&&    falsey

AABBCDDDE
ABBCCCDEE
ABCCCCDDE
AACCCDDEE
AAAACCCCE
AAAAAACCC   truthy

AABB
ABBA
AAAA    truthy

AAAB
AAAA
AAAA    truthy

Mon tapis correctement regroupé par couleurs

Mon tapis correctement regroupé par couleurs

(Je dois encore fixer ces frontières ...)

Charlie
la source
1
Par curiosité, pourquoi ne rangeriez-vous pas le tapis dans l'ordre alphanumérique? Rien à voir avec le défi bien sûr, je me demande juste
Cairn Coinheringaahing
4
@cairdcoinheringaahing car alors mon OCD particulier ne serait pas satisfait. :-)
Charlie
3
Vos enfants continuent d'être une source d'inspiration pour les défis de golf de code :-)
Luis Mendo
2
Pourquoi les couleurs doivent-elles être représentées par des caractères plutôt que par une autre entrée (comme des entiers ou même des pixels peut-être)?
Jonathan Allan
2
en parlant d'ocd, ce défi ne sera pas complet sans une photo du tapis correctement groupé
Jonah

Réponses:

6

MATL , 16 15 octets

1e"G@=4&1ZI1>vzg

L'entrée est un tableau de caractères 2D (avec des lignes séparées par ;). La sortie est 0si l'entrée est qualifiée, ou 1autrement.

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

Explication

Le code vérifie essentiellement si chaque caractère dans l'entrée n'a qu'un seul composant connecté, compte tenu de la connectivité 4 (c'est-à-dire pas de diagonales).

Les caractères répétés sont traités à plusieurs reprises (ce qui est plus golfique que la déduplication).

1e       % Implicit input. Reshape into a row vector of chars
"        % For each char
  G      %   Push input again
  @      %   Push current char
  =      %   Equal (element-wise)? Gives a matrix of zeros and ones, where one
         %   represents the presence of the current char
  4      %   Push 4. This will indicate 4-connectivity
  &1ZI   %   Matrix with labels of connected componnents. Inputs are a number (4)
         %   to indicate connectivity, and a binary matrix. The output is a matrix
         %   the same size as the input where each connected componnent of ones
         %   in the input is replaced by a different integer starting at 1
  1>     %   Greater than 1 (element-wise)? The result is a matrix. If the result 
         %   is true for some entry the input doesn't qualify
  v      %   Concatenate vertically with results from previous iterations
  z      %   Number of nonzero/true values
  g      %   Logical. Converts nonzero to true
         % Implicit end. Implicit display. False / true are displayed as 0 / 1
Luis Mendo
la source
3

Befunge-93, 317 octets

Modifier: corrigé pour un décompte d'octets correct. Peut également être joué plus loin

93+:10pv  +93p01+1g01_  [email protected]<
gp00g1+>00p~1+:93+`!#^_1-00g10
50p93+:vv_v#!:gg03:p02:<>40p#
!`g01: <>\ 1+:vvp05:+<@^p03_^#
v93$_v# !- g00<4v04g<^1<vp06:<
>+\!\>\ 3v> 40v0>g-v^<.g>:70vp
07_v#:<^ >#+0# g#\<  10\v4gg<^
!#v _$^  g03p <\ v1_#:^5>0g  -
   <    ^ g02p1< >-:#^_^#:g05
-1<   ^p\g06\0\+1:\g06\-1:\g06:\+1g06:g07

Imprime 1 comme véridique, 0 comme falsey

Essayez-le en ligne

Voici une visualisation du chemin emprunté par le pointeur

Couleurs fantaisie!

Remarque: c'est pour une ancienne version


Comment ça fonctionne

Voici un pseudocode rapide et sale

a = 2Darray() # from 12,12 down and to the right
arrayLocation = 12
x = arrayLocation #stored at 0,0
y = arrayLocation #stored at 1,0
i = input()       #stored in the stack
while (i != 0):
    if (i == 10):
        y++
        x = init
    else
        a[x][y] = i
        x++
    i = input

new.x = init    #stored at 2,0
new.y = init    #stored at 3,0

currentChar = 0    #stored at 4,0
chars = array()    #stored at 1,1 onwards
charnum = 0        #stored 5,0
ToCheck = array()  #stored in the stack

current.x = null   #stored at 6,0
current.y = null   #stored at 7,0

while (new.y < y):
    if (a[new] != 0)
        currentChar = a[new]
        toCheck[] = new
        while (toCheck)
            current = toCheck.pop()
            if (a[current] == currentChar)
                toCheck.append(adjacent(current))
                a[current] = 0
        foreach (chars as char)
            if (char == currentChar)
                return 0
        charNum++
        chars[charNum] = char
    new.x++
    if (new.x > x)
        new.x = init
        new.y++

return 1

Fondamentalement, après avoir stocké l'entrée, elle passe par le tout, vérifiant chaque espace. Lorsqu'il trouve un espace contenant un personnage, il ajoute les coordonnées à la pile. Ensuite, il vérifie récursivement les espaces autour de lui pour le même caractère, en définissant chaque espace à 0. Lorsqu'il a épuisé la section de ce personnage, il vérifie si ce personnage a déjà eu une section. Si tel est le cas, retournez 0. Sinon, ajoutez-le au tableau de caractères. Une fois qu'il a parcouru toute la grille sans doublons, il renvoie 1.

Pour les personnes familiarisées avec Befunge, voici une version espacée du code

96+:10p    v    +69p01+1g01_v
`+96:+1~p00<+1g00pg01g00-1_^#
v                           <
>40p50p96+:v                ^
v    @.1<  >
>:10g `#^_30p:20p:30gg:#v_$>1+:00g-!#v_0   >30g+
v                       <  ^         >$96+1^
>40p30gv                   ^
       >:!#v_70p:60p:70gg40 g-!#v_$>
           v               ^     > ^
1:\g06\+1:g 07\g07\-1:\g07\ +1: <^p\g06\0\-
v          <               ^
>50gv   >5\g1+:50p40g\1p20g^
    >:!#^_:1g40g-!#v_1-
                   >0.@
Jo King
la source
pour être honnête, je pense que vous devriez le compter comme 337 octets. Sinon, comment spécifiez-vous les dimensions du code dans le fichier lui-même? Les nouvelles lignes devraient également compter.
NieDzejkob
@NieDzejkob Oui, j'ai depuis changé la façon dont je compte les octets et me suis conformé à tout ce que dit TIO. De plus, le nombre de lignes était mauvais de toute façon? Peut-être que demain j'essaierai de le raccourcir un peu plus
Jo King
2

J, 66 octets

c=.1=+/@,+.]-:]*[:*@+/((,|."1)0,.1 _1)&(|.!.0)
[:*/[:c"2[="_ 0~.@,

cdéfinit un verbe qui vous indique si une matrice de uns et de zéros est c onnected. Il traite les singleton comme un cas spécial de vrai. Sinon, il prend un nombre de voisins orthogonaux de chaque cellule, puis le signe de ce nombre, puis multiplie cela avec la matrice d'origine: si ce produit est égal à la matrice d'origine, alors il est connecté.

Le décompte des voisins est obtenu en décalant dans les 4 directions, puis en additionnant. Le décalage dans 4 directions est obtenu en utilisant la fonction " x-arg can by a table" de rotation / décalage|.

Enfin, la réponse elle-même a été obtenue en créant une matrice uns / zéros pour chaque élément unique ~. de l'entrée, puis en s'assurant que toutes ces matrices sont connectées. Ceci est le verbe à la deuxième ligne.

Essayez-le en ligne!

Jonas
la source
2

JavaScript (ES6), 114 octets

Prend l'entrée comme un tableau de chaînes. Renvoie 0ou 1.

a=>(C={},F=x=>!C[c=a[y][x]]|(g=v=>(a[y+v]||[])[x]==c)(-1)|g(1)|g(0,x--)|g(0,x+=2)?a[y+=!c]?F(C[c]=c?x:0):1:0)(y=0)

Cas de test

Formaté et commenté

a => (                            // given an array of strings a
  C = {},                         // C = object holding encountered characters
  F = x =>                        // F = recursive function taking x:
    !C[c = a[y][x]]               //   c = current character; is it a new one?
    | (g = v =>                   //   g = helper function taking v
        (a[y + v] || [])[x] == c  //       and testing whether a[y + v][x] == c
      )(-1)                       //   test a[y - 1][x]
    | g(1)                        //   test a[y + 1][x]
    | g(0, x--)                   //   test a[y][x - 1]
    | g(0, x += 2) ?              //   test a[y][x + 1]; if at least one test passes:
      a[y += !c] ?                //     increment y if c is undefined; if a[y] exists:
        F(C[c] = c ? x : 0)       //       update C, update x and do a recursive call
      :                           //     else:
        1                         //       all characters have been processed -> success
    :                             //   else:
      0                           //     invalid character detected -> failure
)(y = 0)                          // initial call to F, starting with x = y = 0
Arnauld
la source
1

Wolfram Language (Mathematica) , 96 octets

And@@(ConnectedGraphQ@Subgraph[GridGraph@Dimensions[t],Tr/@Position[c,#]]&/@(c=Join@@(t=#)))&

Essayez-le en ligne!

Prend la saisie sous forme de liste 2D de caractères: par exemple {{"A","B"},{"C","D"}},.

Le personnage est \[Transpose].

Comment ça fonctionne

Pour chaque caractère cdans l'entrée, prend le Subgraphde la GridGraphmême chose Dimensionsque l'entrée qui correspond à chaque Positiondans lequel cse produit, et vérifie si c'est un ConnectedGraphQ.

Misha Lavrov
la source
1

Python 2 , 247 octets

def f(a):
 b=map(list,a.split('\n'));l=len(b[0])
 for c in set(a):i=a.find(c);g(b,i/l,i%l,c)
 print all(set(l)<={0}for l in b)
def g(a,i,j,c):
 if len(a)>i>-1<j<len(a[0])and a[i][j]==c:
	for x,y in(0,1),(0,-1),(1,0),(-1,0):g(a,i+x,j+y,c);a[i][j]=0

Essayez-le en ligne!

TFeld
la source
1

JavaScript (ES6), 181 octets

(d,o={})=>{f=(i,j,c,l=d[i])=>{if(c&&l&&l[j]==c){l[j]='';f(i-1,j,c);f(i+1,j,c);f(i,j-1,c);f(i,j+1,c);o[c]=1}};d.map((e,i)=>e.map((c,j)=>o[c]||f(i,j,c)));return!d.some(e=>e.join(''))}

Chaque fois qu'une nouvelle tuile de couleur est trouvée, remplissez celles connectées avec des chaînes vides. Si le tapis est correctement groupé par couleurs, toutes les tuiles doivent être remplies de chaînes vides.

Code de test

yetirs
la source
Comment votre programme prend-il en compte?
Stan Strum