Validador Letter Box

28

O New York Times tem um jogo online diário chamado Letter Boxed (o link está atrás de um paywall; o jogo também é descrito aqui ), apresentado em um quadrado da seguinte forma:

Exemplo de carta em caixa do New York Times

Você recebe 4 grupos de 3 letras (cada grupo corresponde a um lado da foto); nenhuma letra aparece duas vezes. O objetivo do jogo é encontrar palavras compostas por essas 12 letras (e apenas essas letras) de modo que:

  • Cada palavra tem pelo menos três letras;
  • Cartas consecutivas não podem ser do mesmo lado;
  • A última letra de uma palavra se torna a primeira letra da palavra seguinte;
  • Todas as letras são usadas pelo menos uma vez (as letras podem ser reutilizadas).

Neste desafio, você recebe as letras e uma lista de palavras. O objetivo é verificar se a lista de palavras é uma solução válida para caixas de correio.

Entrada

A entrada consiste em (1) 4 grupos de 3 letras e (2) uma lista de palavras. Pode estar em qualquer formato adequado.

Saída

Um valor verdadeiro, se a lista de palavras for uma solução válida para o desafio Letter Boxed para essas letras 4 × 3, e um valor falsey caso contrário.

Casos de teste

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

Valores reais

  • PEREGRINAÇÃO, INCLUIR
  • CULTURAS, VELA, LEAN, NOPE, ENIGMA

Valores de Falsey

  • PEREGRINAÇÃO, ECONOMIAS (não pode ter CO, pois estão do mesmo lado)
  • CROPS, SAIL, LEAN, NOPE (G e M não foram utilizados)
  • PEREGRINAÇÃO ENCLOSURE (U não é uma das 12 letras)
  • ANEXAR, PEREGRINAÇÃO (a última letra da 1ª palavra não é a primeira letra da 2ª palavra)
  • SCAMS, SO, ORGANIZAR, FUGIR (todas as palavras devem ter pelo menos três letras).

Observe que, neste desafio, não nos importamos se as palavras são válidas (parte de um dicionário).

Pontuação:

Esse , a menor pontuação em bytes, ganha!

Robin Ryder
fonte
4
@TFeldno letter appears twice
feersum 15/04
Um valor verdadeiro, se a lista de palavras for uma solução válida para o desafio Letter Boxed para essas letras 4 × 3, e um valor falsey caso contrário. Para Python (e para a maioria das outras linguagens, espero), ambas []e 0são falsey. Podemos produzir ou nossa produção deve ser consistente?
Artemis apoia Monica em
@ArtemisFowl Está tudo bem.
Robin Ryder
Eu pensava assim, mas minha pergunta era: podemos misturá- los?
Artemis apoia Monica
@ArtemisFowl Sim, você pode misturá-los.
Robin Ryder

Respostas:

6

JavaScript (ES6),  130  126 bytes

Toma entrada como (letters)(words). Retorna 0 0 ou 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)))

Experimente online!

Passo 1

eus

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()

Passo 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
fonte
6

Geléia , 30 29 bytes

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

Experimente online!

Um link diádico que leva a lista de palavras como argumento à esquerda e a lista achatada de letras na caixa como o argumento à direita. Retorna1 para verdadeiro e0 para falso.

Explicação

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
fonte
6

05AB1E , 37 35 33 32 31 29 28 bytes

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

-2 bytes, inspirando-se na êabordagem @Emigna usada em sua resposta 05AB1E .
-3 bytes graças a @Grimy .

Leva uma lista da lista de caracteres para as palavras como primeira entrada e a lista nivelada de doze letras como segunda entrada.

Experimente online ou verifique todos os casos de teste .

Explicação:

ε         # 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
fonte
1
@ Grimy Ah, esse primeiro comentário é realmente óbvio. Acabei de alterá-lo para uma matriz de caracteres, e agora isso realmente funciona onde antes não era quando as palavras ainda eram strings. Essa segunda abordagem de mesclagem, verificar igualdade de pares, soma é bastante brilhante! : D Obrigado (como sempre).
Kevin Cruijssen 18/09
1
Outro -1: ¹€g3@-> DO2@após a primeira verificação ( TIO )
Grimmy 18/09
1
@ Grimy Outro bom, obrigado. Agora estamos abaixo da resposta Jelly de 29. :)
Kevin Cruijssen 18/09
5

05AB1E , 42 bytes

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

Experimente online!

Emigna
fonte
Não é muito, mas um byte pode ser salvo removendo tudo Pdepois dos mapas e usando )˜Pno final. 41 bytes Abordagem agradável com êno entanto! Salvei 2 bytes na minha resposta 05AB1E.
Kevin Cruijssen 15/04
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

Experimente online!

TFeld
fonte
4

Geléia , 34 bytes

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

Um link diádico que aceita as palavras à esquerda e os grupos de letras à direita, que produz 1se válido e 0se não.

Experimente online! Ou veja a suíte de testes .

Jonathan Allan
fonte
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

Experimente online!

Não é a melhor pontuação. Algum guru Haskell provavelmente conseguirá isso abaixo de 100 bytes.

Uso

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

Explicação

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
fonte
4

Haskell , 231 bytes

Uma variação diferente de Haskell, exatamente do mesmo tamanho que 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)

Experimente online!

Ungolfed

-- 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)
insetos
fonte
3

Ruby , 126 bytes

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

Experimente online!

GB
fonte
Bom, quando vi o desafio pela primeira vez, tentei fazer algo semelhante, mas desisti de pontuar em algum momento dos 140 anos. BTW, salve um byte, soltando parênteses depois grep.
Kirill L.
Isso não funciona quando a última palavra tem 1 ou 2 letras, por exemplo, puts f[l,['PILGRIMAGE','ENCLOSE','EG']]retorna em truevez de false.
Robin Ryder
1
Você está certo, fixo.
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;}

Experimente online!

Explicações

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 graças ao ceilingcat
Olivier Grégoire
fonte
2

Carvão , 63 bytes

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

Experimente online! Link é a versão detalhada do código. Explicação:

⌊⁺⁺⁺

Concatene as expressões e a saída abaixo, 0se alguma delas incluir um 0contrário 1.

⭆η›Lι²

Para cada palavra na solução, indique se seu comprimento é pelo menos 3.

⭆⪫ηω№⪫θωι

Para cada letra na solução, indique se ela aparece no quebra-cabeça.

⭆⪫θω№⪫ηωι

Para cada letra no quebra-cabeça, indique se ela aparece na solução.

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

Para cada letra da solução, verifique se a letra anterior não está no mesmo grupo, a menos que seja a primeira letra de uma palavra; nesse caso, verifique se é igual à última letra da palavra anterior, a menos que seja a primeira letra da solução; nesse caso, apenas a ignore.

Neil
fonte
0

Python 2 , 168 156 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)

Experimente online!

Retorna 1para verdade, 0para falsey.

Chas Brown
fonte