Validador de buzones

28

The New York Times tiene un juego en línea diario llamado Letter Boxed (el enlace está detrás de un muro de pago; el juego también se describe aquí ), presentado en un cuadrado de la siguiente manera:

Ejemplo de Letter Boxed del New York Times

Te dan 4 grupos de 3 letras (cada grupo corresponde a un lado de la imagen); ninguna carta aparece dos veces. El objetivo del juego es encontrar palabras hechas de esas 12 letras (y solo esas letras) de modo que:

  • Cada palabra tiene al menos 3 letras de largo;
  • Las cartas consecutivas no pueden ser del mismo lado;
  • La última letra de una palabra se convierte en la primera letra de la siguiente palabra;
  • Todas las letras se usan al menos una vez (las letras se pueden reutilizar).

En este desafío, te dan las letras y una lista de palabras. El objetivo es verificar si la lista de palabras es una solución válida de Letter Boxed.

Entrada

La entrada consta de (1) 4 grupos de 3 letras y (2) una lista de palabras. Puede estar en cualquier formato adecuado.

Salida

Un valor verdadero si la lista de palabras es una solución válida para el desafío Letter Boxed para esas letras 4 × 3, y un valor falso de lo contrario.

Casos de prueba

Grupos de letras = {{I,C,O}, {M,R,E}, {G,N,S}, {A,P,L}}.

Valores de verdad

  • PEREGRINACIÓN, CERRAR
  • CULTIVOS, VELA, LEAN, NOPE, ENIGMA

Valores de Falsey

  • PEREGRINACIÓN, ECONOMÍAS (no pueden tener CO ya que están del mismo lado)
  • CULTIVOS, VELA, LEAN, NOPE (G y M no se han utilizado)
  • PEREGRINACIÓN, RECUBRIMIENTO (U no es una de las 12 letras)
  • CERRAR, PEREGRINACIÓN (la última letra de la primera palabra no es la primera letra de la segunda palabra)
  • SCAMS, SO, ORGANIZE, ELOPE (todas las palabras deben tener al menos 3 letras de largo).

Tenga en cuenta que en este desafío, no nos importa si las palabras son válidas (parte de un diccionario).

Tanteo:

¡Este , el puntaje más bajo en bytes gana!

Robin Ryder
fuente
44
@TFeldno letter appears twice
feersum
Un valor verdadero si la lista de palabras es una solución válida para el desafío Letter Boxed para esas letras 4 × 3, y un valor falso de lo contrario. Para Python (y la mayoría de otros idiomas, espero), ambos []y 0son Falsey-. ¿Podemos generar resultados o nuestro rendimiento debe ser consistente?
Artemisa apoya a Mónica el
@ArtemisFowl Cualquiera está bien.
Robin Ryder
Pensé que sí, pero mi pregunta era: ¿podemos mezclarlos ?
Artemisa apoya a Mónica el
@ArtemisFowl Sí, puedes mezclarlos.
Robin Ryder

Respuestas:

6

Javascript (ES6),  130  126 bytes

Toma entrada como (letters)(words). Devuelve 0 0 o 1 .

L=>W=>L.every(a=>a.every(x=>(W+'').match(x,a.map(y=>s+='|'+x+y))),p=s=1)&W.every(w=>w[2]&&p|w[0]==p&!w.match(s,p=w.slice(-1)))

Pruébalo en línea!

Paso 1

En primer lugar, iterar sobre L a construir una cadena de tubos separados por s que consiste en todos los pares de letras no válidos. Al hacerlo, también nos aseguramos de que cada letra aparezca al menos una vez en alguna palabra.

L.every(a =>              // for each group of letter a[] in L[]:
  a.every(x =>            //   for each letter x in a[]:
    (W + '')              //     coerce W[] to a string
    .match(               //     and test whether ...
      x,                  //       ... x can be found in it
      a.map(y =>          //       for each letter y in a[]:
        s += '|' + x + y  //         append '|' + x + y to s
      )                   //       end of map()
    )                     //     end of match()
  ),                      //   end of inner every()
  p = s = 1               //   start with p = s = 1
)                         // end of outer every()

Paso 2

W

W.every(w =>              // for each word w in W[]:
  w[2] &&                 //   is this word at least 3 characters long?
  p |                     //   is it the first word? (p = 1)
  w[0] == p &             //   or does it start with the last letter of the previous word?
  !w.match(               //   and finally make sure that ...
    s,                    //     ... it doesn't contain any invalid pair of letters
    p = w.slice(-1)       //     and update p to the last letter of w
  )                       //   end of match()
)                         // end of every()
Arnauld
fuente
6

Jalea , 30 29 bytes

FQṢ=Ṣ},i@€€’:3Iʋ,Ẉ>2ɗ,U=ḢɗƝ{Ȧ

Pruébalo en línea!

Un enlace diádico que toma la lista de palabras como argumento izquierdo y la lista aplanada de letras en el cuadro como argumento correcto. Vuelve 1por verdadero y0 por falso.

Explicación

F                               | Flatten the word list
 Q                              | Unique
  Ṣ                             | Sort
   =                            | Is equal to
    Ṣ}                          |   The sorted letterbox letters
      ,        ʋ                | Pair this with the following:
       i@€€                     |   The index of each letter of each word in the letterbox            
           ’                    |   Decrease by 1
            :3                  |   Integer divide by 3
              I                 |   Differences between consecutive ones (will be zero if any two consecutive letters in a word from same side of box)
                ,   ɗ           | Pair everything so far with the following:
                 Ẉ>2            |   Whether length of each input word is greater than 2
                     ,   ɗƝ{    | Pair everything so far with the following, applied to each neighbouring pair of the input word list
                      U         |   Upend (reverse) first word
                       =        | Compare characters to second
                        Ḣ       |   Take first (i.e. last character of first word equals first character of second)
                            Ȧ   | Flatten all of the above and check there are no false values
Nick Kennedy
fuente
6

05AB1E , 37 35 33 32 31 29 28 bytes

εk3÷üÊ}DO2@¹ü«εüQO}²{¹˜êQ)˜P

-2 bytes inspirándose en el êenfoque que @Emigna usó en su respuesta 05AB1E .
-3 bytes gracias a @Grimy .

Toma una lista de la lista de caracteres para las palabras como primera entrada, y la lista aplanada de doce letras como segunda entrada.

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

Explicación:

ε         # Map over the character-lists `y` of the (implicit) input-list of words:
 k        #  Get the index of each character in the (implicit) input-list of letters
  3÷      #  Integer-divide each index by 3
    üÊ    #  Check for each overlapping pair of integers that they are NOT equal
}D        # After the map: duplicate the resulting list
  O       #  Get the sum of each inner list of truthy/falsey values
   2@     #  And check that each is larger than 2 (so all words had at least 3 letters)
¹ü        # Get all overlapping pairs of character-lists from the input-list of words:
  «       #  And merge them together to a flattened list of characters
   ε   }  # Map over those merged character lists:
    üQ    #  Check for each overlapping pair of characters in the list that they are equal
      O   #  And take the sum of this (where we'd expect 1/truthy if the last character of
          #  the first word and the first character of the second word are equal)
          #  (NOTE: This could fail for inputs with identical adjacent characters,
          #   but the earlier check of `εk3÷üÊ}` already covers for this)
²{        # Push the input-list of letters, and sort them
  ¹˜      # Push the input-list of list of word-letters, flattened,
    ê     # and then uniquified and sorted as well
     Q    # And check if both lists of characters are the same
        # Then wrap everything on the stack into a list, and deep flatten it
  P       # And check if everything is truthy by taking the product
          # (which is output implicitly as result)
Kevin Cruijssen
fuente
1
@ Grimy Ah, ese primer comentario es realmente obvio. Lo acabo de cambiar a una matriz de caracteres, por lo que ahora sí funciona donde no lo hacía antes cuando las palabras seguían siendo cadenas. Sin embargo, ese segundo enfoque de fusión, comprobar igualdad de pares, suma es bastante brillante. : D Gracias (como siempre).
Kevin Cruijssen
1
Otro -1: ¹€g3@-> DO2@después del primer control ( TIO )
Grimmy
1
@ Grimy Otra buena, gracias. Ahora estamos por debajo de la respuesta Jelly de 29. :)
Kevin Cruijssen
5

05AB1E , 42 bytes

εg2›}P¹εεUIεXå}ƶO}üÊP}P¹ü‚ε`нsθQ}P¹Jê²JêQP

Pruébalo en línea!

Emigna
fuente
No es mucho, pero se puede guardar un byte eliminando todo Pdespués de los mapas y usarlo )˜Pal final. 41 bytes Buen enfoque con êsin embargo! Guarde 2 bytes en mi respuesta 05AB1E.
Kevin Cruijssen
4

Python 2 , 171 bytes

lambda l,w:(set(sum(l,[]))==set(''.join(w)))*all(a[-1]==b[0]for a,b in zip(w,w[1:]))*all((a in g)+(b in g)<2for x in w for a,b in zip(x,x[1:])for g in l)*min(map(len,w))>2

Pruébalo en línea!

TFeld
fuente
4

Gelatina , 34 bytes

Ṫ=¥/ƝḢ€Ạȧ⁸Fe€ⱮZḄ;IẠƊȧF}fƑF{
ẈṂ>2ȧç

Un enlace diádico que acepta las palabras a la izquierda y los grupos de letras a la derecha que produce 1 si es válido y 0si no.

Pruébalo en línea! O vea el conjunto de pruebas .

Jonathan Allan
fuente
4

Haskell , 231 bytes

import Data.List
l&w=all((>2).length)w&&c w&&all(l!)w&&(h l)%(h w)
h=concat
l%w=null[x|x<-l,x`notElem`w]
l!(a:b:c)=a#l?(b#l)&&l!(b:c)
l!_=1>0
Just a?Just b=a/=b
_?_=1<0
c#l=findIndex(elem c)l
c(a:b:t)=last a==head b&&c(b:t)
c _=1>0

Pruébalo en línea!

No es el mejor puntaje. Algunos gurús de Haskell probablemente podrán obtener esto por debajo de 100 bytes.

Uso

["ICO","MRE","GNS","APL"]&["CROPS", "SAIL", "LEAN", "NOPE", "ENIGMA"]

Explicación

import Data.List
l&w = all((>2).length)w &&      -- Every word has length > 2
      c w &&                    -- Every word ends with the same letter as the next one starts with
      all(l!)w &&               -- For every word: Consecutive letters are on different sides (and must exist on a side)
      (h l)%(h w)               -- All letters are used

h=concat                        -- Just a shorthand

l%w=null[x|x<-l,x`notElem`w]    -- The letters of l, with all letters of w removed, is empty

l!(a:b:c)=a#l?(b#l)&&l!(b:c)    -- Sides of the first two letters are different, recurse from second letter
l!_=1>0                         -- Until fewer than 2 letters remain

Just a?Just b=a/=b              -- Both sides must be different
_?_=1<0                         -- And must exist

c#l=findIndex(elem c)l          -- Find the side of letter c

c(a:b:t)=last a==head b&&c(b:t) -- Last letter of the first word must be same as first letter of second word, recurse starting from second word
c _=1>0                         -- Until there are fewer than 2 words
Paul Mutser
fuente
4

Haskell , 231 bytes

Una variación diferente de Haskell, exactamente del mismo tamaño que la de @Paul Mutser :)

import Data.List
f x=filter(\a->length a>1)$concatMap subsequences x
g=nub.concat.f
p l(x:y)=foldl(\(m,n)c->(c,n&&length c>2&&(not$any(`isInfixOf`c)(f l))&&last m==head c))(x,True)y
z l w=null(g l\\g w)&&null(g w\\g l)&&(snd$p l w)

Pruébalo en línea!

Sin golf

-- generate all invalid substrings
f :: [String] -> [String] 
f xs = filter (\x -> length x > 1) $ concatMap subsequences xs

-- utility function to flatten and remove duplicates
g :: [String] -> String
g  = nub $ concat $ f

-- verify that all conditions are satisfied along the list
p :: [String] -> [String] -> (String, Bool)
p l (x:xs) = foldl (\(m,n) c -> (c , n && length c > 2 && (not $ any (`isInfixOf` c)(f l)) && last m == head c)) (x, True) xs

-- put all the pieces together and consume input
z :: [String] -> [String] -> Bool
z l w = null (g l \\ g w) && null (g w \\ g l) && (snd $ p l w)
loco
fuente
3

Ruby , 126 bytes

->l,w{(/(_|^)..(_|$)/!~s=w*?_)&&!!s.chars.uniq[12]&&/__|^_|_$|(_.*)\1/!~s.gsub(/(.)_\1/,'\1').chars.map{|x|l.grep(/#{x}/)}*?_}

Pruébalo en línea!

GB
fuente
Agradable, cuando vi el desafío por primera vez, intenté hacer algo similar, pero me di por vencido con un puntaje en algún lugar de 140 años. Por cierto, guarde un byte soltando paréntesis después grep.
Kirill L.
Esto no funciona cuando la última palabra tiene 1 o 2 letras, por ejemplo, puts f[l,['PILGRIMAGE','ENCLOSE','EG']]devuelve en truelugar de false.
Robin Ryder
1
Tienes razón, arreglado.
GB
3

Java (JDK) , 188 bytes

g->w->{var v=0<1;int x=0,l,i=0,j,p,z,y=w[0][0];for(;i<w.length;i++)for(l=w[i].length,v&=y==w[i][0]&l>2,j=0,p=-9;j<l;v&=z>=0&z/3!=p/3,x|=2<<(p=z))z=g.indexOf(y=w[i][j++]);return v&x==8190;}

Pruébalo en línea!

Explicaciones

g->w->{     // Lambda accepting letter groups as a string and a list of words, in the form of an array of char arrays.
 var v=0<1;     // Validity variable
 int x=0,       // The letter coverage (rule 4)
     l,         // The length of w[i]
     i=0,       // The w iterator
     j,         // The w[i] iterator
     p,         // The previous group
     z,         // The current group
     y=w[0][0]; // The previous character
 for(;i<w.length;i++) // For each word...
  for(
     l=w[i].length,     // make a shortcut for the length
     v&=y==w[i][0]&l>2, // check if the last character of the previous word is the same as the first of the current.
                        // Also, check if the length is at least 3
     j=0,               // Reset the iteration
     p=-9               // Set p to an impossible value.
    ;
     j<l                // 
    ;
     v&=z>=0&z/3!=p/3,  // Check that each letter of the word is in the letter pool,
                        //  and that the current letter group isn't the same as the previous one.
     x|=2<<(p=z)      // After the checks, assign z to p,
                        //  and mark the letter of the pool as used.
   )
   z=g.indexOf(y=w[i][j++]); // Assign the current letter to y so that it contains the last at the end of the loop.
                             //  and fetch the position of the letter in the pool.
 return v&x==8190; // Return true if all matched
                   //  and if the rule 4 is enforced.
}

Créditos

  • -2 bytes gracias a ceilingcat
Olivier Grégoire
fuente
2

Carbón , 63 bytes

⌊⁺⁺⁺⭆η›Lι²⭆⪫ηω№⪫θωι⭆⪫θω№⪫ηωι⭆η⭆ι⎇μ¬⁼Φθ№νλΦθ№ν§ι⊖μ∨¬κ⁼§ι⁰§§η⊖κ±¹

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

⌊⁺⁺⁺

Concatene las siguientes expresiones y resultados 0si alguno de ellos incluye lo 0contrario 1.

⭆η›Lι²

Para cada palabra en la salida de salida si su longitud es al menos 3.

⭆⪫ηω№⪫θωι

Para cada letra en la salida de salida si aparece en el rompecabezas.

⭆⪫θω№⪫ηωι

Para cada letra en la salida del rompecabezas si aparece en la solución.

⭆η⭆ι⎇μ¬⁼Φθ№νλΦθ№ν§ι⊖μ∨¬κ⁼§ι⁰§§η⊖κ±¹

Para cada letra de la solución, verifique que la letra anterior no esté en el mismo grupo, a menos que sea la primera letra de una palabra, en cuyo caso verifique que sea igual a la última letra de la palabra anterior, a menos que sea la primera letra de la solución, en cuyo caso simplemente ignórela.

Neil
fuente
0

Python 2 , 168156 bytes

lambda l,w,J=''.join:(set(J(w))==set(J(l)))*all((v<1or u[-1]==v[0])*u[2:]*(2>(x in p)+(y in p))for u,v in zip(w,w[1:]+[0])for x,y in zip(u,u[1:])for p in l)

Pruébalo en línea!

Vuelve 1por la verdad, 0por falsey.

Chas Brown
fuente