Encontre as palavras do infinito!

36

(Nota: Este é um desdobramento do meu desafio anterior Encontre as palavras em redemoinho! )

Definição de Infinito Palavra :

  1. Se você conectar com curvas todos os caracteres de uma Palavra Infinita no alfabeto (AZ), obterá o símbolo do infinito ∞ como nos diagramas abaixo.
  2. Todas as conexões pares devem estar inoperantes , todas as conexões ímpares devem estar ativadas .
  3. Você pode ignorar maiúsculas / minúsculas ou considerar / converter tudo em maiúsculas ou tudo em minúsculas.
  4. As palavras de entrada são apenas caracteres no intervalo alfabético de AZ, sem espaços, sem pontuação ou símbolos.
  5. Cada palavra deve ter exatamente 5 caracteres. Palavras> 5 ou <5 não são válidas.
  6. Se uma palavra tem caracteres consecutivos duplos, a palavra não é válida, como "FLOOD" ou "QUEEN".
  7. Todas as Palavras Infinitas começam e terminam com o mesmo caractere.

Aqui estão alguns exemplos:

Palavras do infinito

Tarefa:

Escreva um programa ou função completa que retire uma palavra da entrada padrão e faça a saída se for uma Infinity Word ou não. A saída pode ser verdadeira / falsa, 1/0, 1 / Nula, etc.

Casos de teste:

Infinity Words:
ALPHA, EAGLE, HARSH, NINON, PINUP, RULER, THEFT, WIDOW

NOT Infinity Words:
CUBIC, ERASE, FLUFF, LABEL, MODEM, RADAR, RIVER, SWISS, TRUST, 
KNEES, QUEEN, GROOVE, ONLY, CHARACTER, OFF, IT, ORTHO

Regras:

  1. O menor código vence.

Tarefa opcional:

Encontre, como uma lista, quantas palavras infinitas puder em um dicionário de inglês. Você pode tomar, por exemplo, como referência a lista completa de palavras em inglês aqui .

Mario
fonte
Podemos assumir que a entrada é sempre do comprimento 5? Você definiu a regra 5: " Cada palavra deve ter exatamente 5 caracteres. Palavras> 5 ou <5 não são válidas. ", Mas não NOT Infinity Words contendo menos ou mais de 5 caracteres.
21816 Kevin Cruijssen 13:17
4
Muito engraçado que ALPHA faz esse padrão
Fatalize
@KevinCruijssen Você deve verificar se a palavra respeita a definição, atualizei os casos falsos.
Mario
1
@Arnauld cinco "A" se conectam a si mesmos (ou não se movem) criando um único ponto, ele não desenha o símbolo do infinito, então não acho que seja um caso positivo.
Mario
3
Decidi realizar a Tarefa Opcional: "Encontre, como uma lista, o maior número possível de Palavras Infinitas em um dicionário de inglês ..." Usei essa fonte e a resposta de Kevin Cruijssen para produzir esta lista de 278 Palavras Infinitas .
22416 Thomas Quinn Kelly

Respostas:

19

Gelatina , 43 41 40 25 24 23 22 21 14 13 bytes

-7 bytes graças ao fireflame241 ( 0ị=1ị$-> =ṚḢe uso de IIA⁼2,2para testar as 4 rotações)

-1 Agradecimentos a Kevin Cruijssen (uso de nilad anteriormente indisponível Ø2que produz [2,2])

=ṚḢȧOIṠIIA⁼Ø2

TryItOnline
Ou todos os casos de teste (mais "REGRAS")

Quão?

Uma palavra infinita possui:

  1. a mesma primeira e última letra;
  2. comprimento 5;
  3. não há letras iguais próximas uma da outra;
  4. soma dos quatro deltas do alfabeto iguais a zero;
  5. soma dos quatro sinais de deltas do alfabeto iguais a zero;
  6. dois deltas positivos do alfabeto ou dois deltas negativos do alfabeto seguidos.

Todos, exceto (1) e (equivalentemente) (4), podem ser resumidos a uma condição na qual os sinais delta do alfabeto são uma rotação de [1,1,-1,-1](onde o sinal de 0é 0)

fireflame241 observou que isso é equivalente aos deltas dos deltas do alfabeto, sendo [[2,2],[2,-2],[-2,2],[-2,-2]]que os sinais delta podem ser testados pelos valores absolutos iguais a [2,2]!

Quão?

=ṚḢȧOIṠIIA⁼Ø2 - Main link: word
 Ṛ            - reverse word
=             - equals? (vectorises)
  Ḣ           - head (is the first character equal to the last?)
   ȧ          - and
    O         - cast word to ordinals
     I        - increments - the alphabet deltas (or just [] if 1st != last)
      Ṡ       - sign (vectorises)
       I      - increments - deltas of those signs
        I     - increments - deltas of those
         A    - absolute value (vectorises)
           Ø2 - literal [2,2]
          ⁼   - equals? (non-vectorising version)
Jonathan Allan
fonte
Como é que isso funciona?
Oliver Ni
explicação recebida.
Jonathan Allan
2
@PascalvKooten É principalmente para diversão e para ser competitivo no código de golfe - eu sou bastante novo no código de golfe e no Jelly, então montar um programa de Jelly é como um pequeno quebra-cabeça quase sempre; Eu acho isso satisfatório. Se alguém deseja obter algo tangível neste jogo, deve usá-lo para aprimorar suas habilidades em um idioma que é mais comum no mundo real, embora, ou, é claro, crie um idioma para o golfe!
Jonathan Allan
1
@ lois6b :). Você começa com o tutorial e, em seguida, usa as páginas com definições Atom , definições Quicks e procura o código-fonte .
Jonathan Allan
1
14 bytes O golfe principal aqui usa IIpara verificar a igualdade em uma rotação de 1,1, -1, -1.
fireflame241
11

Java 8, 231 193 185 122 103 78 bytes

s->s.length==5&&(s[1]-s[0])*(s[3]-s[2])<0&(s[2]-s[1])*(s[4]-s[3])<0&s[4]==s[0]

Experimente aqui.

-38 bytes graças a @ dpa97 por me lembrar de usar em char[]vez de String.
-63 bytes graças à fórmula derivada de @KarlNapf .
-25 bytes, convertendo-o do Java 7 para o Java 8 (e agora retornando um booleano em vez de inteiro).

Resposta de 193 bytes:

int c(char[]s){if(s.length!=5)return 0;int a=s[0],b=s[1],c=s[2],d=s[3],e=s[4],z=b-a,y=c-b,x=d-c,w=e-d;return e!=a?0:(z>0&y>0&x<0&w<0)|(z<0&y>0&x>0&w<0)|(z>0&y<0&x<0&w>0)|(z<0&y<0&x>0&w>0)?1:0;}

Explicação:

  • Se o comprimento da string não for 5, retornamos false
  • Se o primeiro caractere não for igual ao último, retornamos false
  • Em seguida, verificamos os quatro casos válidos um por um (vamos indicar os cinco caracteres como 1 a 5) e retornamos truese estiver em conformidade com algum deles (e falsecaso contrário):
    1. Se os cinco caracteres são distribuídos como: 1<2<3>4>5(ou seja ALPHA)
    2. Se os cinco caracteres são distribuídos como: 1>2<3<4>5 (isto é EAGLE, HARSH, NINON, PINUP)
    3. Se os cinco caracteres são distribuídos como: 1<2>3>4<5(ou seja RULER)
    4. Se os cinco caracteres forem distribuídos como: 1>2>3<4<5(por exemplo,THEFT , WIDOW)

Essas quatro regras podem ser simplificadas 1*3<0 and 2*4<0(graças à resposta em Python 2 do @KarlNapf ).

Kevin Cruijssen
fonte
2
+1 para compensar o voto negativo inexplicável ... Até onde eu sei, essa é uma solução perfeitamente funcional.
Arnauld
1
Eu reduzi para 215 convertendo s em um char [] char [] c = s.toCharArray (); int z = c [1] -c [0], y = c [2] -c [1] ,. .. #
dpa97 17/10
@ dpa97 Obrigado pelo lembrete para usar char[]como entrada em vez de String. -38 bytes graças a você.
Kevin Cruijssen 17/10
1
Seus booleanos podem ser otimizados: z,xe w,ydevem ter um sinal alternado, portanto basta verificar z*x<0ew*y<0
Karl Napf
@KarlNapf Ah, eu interpretei mal seu comentário algumas horas atrás. Implementei sua fórmula derivada para -63 bytes impressionantes. :) Obrigado.
Kevin Cruijssen 18/10
4

JavaScript (ES6), 91 89 87 bytes

Guardado 2 bytes graças a Ismael Miguel

s=>(k=0,[...s].reduce((p,c,i)=>(k+=p>c?1<<i:0/(p<c),c)),k?!(k%3)&&!s[5]&&s[0]==s[4]:!1)

Como funciona

Construímos uma máscara de bits de 4 bits krepresentando as 4 transições entre os 5 caracteres da string:

k += p > c ? 1<<i : 0 / (p < c)
  • se o caractere anterior for maior que o próximo, o bit será definido
  • se o caractere anterior for menor que o próximo, o bit não está definido
  • se o caractere anterior for idêntico ao próximo, a máscara de bit inteira será forçada a fazer NaNcom que a palavra seja rejeitada (para obedecer à regra 6)

As máscaras de 1bits válidas são as que possuem exatamente duas transições consecutivas (o primeiro e o último bits também são considerados consecutivos ):

Binary | Decimal
-------+--------
0011   | 3
0110   | 6
1100   | 12
1001   | 9

Em outras palavras, estas são as combinações que são:

  • k? : maior que 0
  • !(k%3): congruente a 0 módulo 3
  • inferior a 15

As outras condições são:

  • !s[5] : não há mais de 5 caracteres
  • s[0]==s[4] : o primeiro e o quinto caracteres são idênticos

NB : Não verificamos explicitamente k != 15porque qualquer palavra que segue esse padrão será rejeitada por esta última condição.

Casos de teste

Versão inicial

Para o registro, minha versão inicial era de 63 bytes. Ele está sendo aprovado em todos os casos de teste com êxito, mas falha em detectar caracteres idênticos consecutivos.

([a,b,c,d,e,f])=>!f&&a==e&&!(((a>b)+2*(b>c)+4*(c>d)+8*(d>e))%3)

Abaixo está uma versão de 53 bytes sugerida por Neil nos comentários, que funciona (e falha) igualmente bem:

([a,b,c,d,e,f])=>!f&&a==e&&!((a>b)-(b>c)+(c>d)-(d>e))

Editar: Veja a resposta de Neil para a versão fixa / completa do código acima.

Arnauld
fonte
0000também é congruente com 0 módulo 3, mas, novamente, você não pode ter a primeira e a última letras iguais; portanto, como 15, não é necessário testá-lo explicitamente.
Neil
Para essa versão inicial, você pode usar !((a>b)-(b>c)+(c>d)-(d>e))?
Neil
p<c?0:NaNpode ser escrito como 0/(p<c), o que economiza 2 bytes.
Ismael Miguel
@ Neil Em relação ao teste contra 0: você está perfeitamente certo. (No entanto, eu preciso do k?teste por causa do possível NaN.) Com relação à sua versão alternativa: isso deve funcionar de fato.
Arnauld
@IsmaelMiguel - Good call! Obrigado.
Arnauld 17/10
4

JavaScript (ES6), 78 bytes

([a,b,c,d,e,f])=>a==e&&!(f||/(.)\1/.test(a+b+c+d+e)||(a>b)-(b>c)+(c>d)-(d>e))

Com base no código incorreto de @ Arnauld, mas foi corrigido e corrigido. Funciona verificando primeiro se o primeiro caractere é o mesmo que o quinto (garantindo assim 5 caracteres) e se o comprimento da string não é maior que 5. Após verificar se há caracteres duplicados consecutivos, resta verificar a ondulação da string, que deve ter um pico e um calha com duas letras de diferença.

  • Se o pico e o vale são as letras do meio e da primeira / última, as duas primeiras comparações e as duas últimas são canceladas.
  • Se o pico e o vale são a segunda e a quarta letras, as duas comparações do meio e as duas externas são canceladas
  • Caso contrário, algo não será cancelado e a expressão geral retornará false

Edit: Solução alternativa de 78 bytes com base na resposta de @ KarlNapf:

([a,b,c,d,e,f],g=(a,b)=>(a<b)-(a>b))=>a==e&&!f&&g(a,b)*g(c,d)+g(b,c)*g(d,e)<-1
Neil
fonte
3

Código de saída Python 2, 56 bytes

s=input()
v,w,x,y,z=map(cmp,s,s[1:]+s[0])
v*x+w*y|z>-2>_

Saídas via código de saída: Erro para False e execução bem-sucedida para True.

Pega a sequência scom caracteres abcde, gira-a para bcdea, faz uma comparação elementar dos caracteres correspondentes e os atribui a cinco variáveis v,w,x,y,z. O comprimento errado dá um erro.

Todas as palavras infinitas têm

v*x == -1
w*y == -1
z == 0

que pode ser verificado em conjunto como v*x+w*y|z == -2. A comparação encadeada v*x+w*y|z>-2>_curto-circuito, se esse for o caso, e continua avaliando -2>_qual erro de nome ocorre .

xnor
fonte
Ah, que bom que você jogou o condicionador mais!
1913 Karl Karlf
3

Python 2, 110 87 60 bytes

Economizando 1 byte graças a Neil

Requer entrada entre aspas, por exemplo 'KNEES'

Truese for uma palavra infinita, Falsese não, e tiver um comprimento de 5 e imprimirá uma mensagem de erro se o comprimento estiver errado

s=input()
a,b,c,d,e=map(cmp,s,s[1:]+s[0])
print a*c+b*d|e<-1

Inspirado pela resposta do xnor usandomap(cmp...

s=input()
e=map(cmp,s,s[1:]+s[0])
print e[4]==0and e[0]*e[2]+e[1]*e[3]==-2and 5==len(s)

solução anterior:

s=input()
d=[ord(x)-ord(y)for x,y in zip(s,s[1:])]
print s[0]==s[4]and d[0]*d[2]<0and d[1]*d[3]<0and 4==len(d)

Usando a lógica otimizada de Kevin Cruijssen

Karl Napf
fonte
Por que não a*c+b*d+2==0==e?
Neil
@ Neil sim, por que não, mas o xnor a*c+b*d|eé ainda mais curto.
Karl Napf
Eu acho que <-1pode funcionar, já que ambos -2|1e -2|-1iguais -1.
Neil
2

PHP, 102 bytes

for(;$i<strlen($w=$argv[1]);)$s.=($w[$i++]<=>$w[$i])+1;echo preg_match("#^(2200|0022|2002|0220)#",$s);
Jörg Hülsermann
fonte
2

Python 2, 71 bytes

lambda s:map(cmp,s,s[1:]+s[0])in[[m,n,-m,-n,0]for m in-1,1for n in-1,1]

Pega a sequência scom caracteres abcde, gira-a para bcdeae faz uma comparação elementar dos caracteres correspondentes.

a  b   cmp(a,b)
b  c   cmp(b,c)
c  d   cmp(c,d)
d  e   cmp(d,e)
e  a   cmp(e,a)

O resultado é uma lista de -1, 0, 1. Em seguida, verifica se o resultado é uma das seqüências válidas de altos e baixos:

[-1, -1, 1, 1, 0]
[-1, 1, 1, -1, 0]
[1, -1, -1, 1, 0]
[1, 1, -1, -1, 0]

conforme gerado a partir do modelo [m,n,-m,-n,0]com m,n=±1. A última 0verifica se a primeira e a última letra foram iguais e o comprimento garante que a cadeia de entrada tenha comprimento 5.


Uma alternativa 71. Verifica as condições nas comparações, garantindo o comprimento certo.

def f(s):a,b,c,d,e=map(cmp,s,s[1:]+s*9)[:5];print a*c<0==e>b*d>len(s)-7
xnor
fonte
1

R, 144 bytes

A resposta é baseada na lógica de @ Jonathan Allan. Provavelmente poderia ser jogado golfe.

s=strsplit(scan(,""),"")[[1]];d=diff(match(s,LETTERS));s[1]==tail(s,1)&length(s)==5&all(!rle(s)$l-1)&!sum(d)&!sum(sign(d))&any(rle(sign(d))$l>1)

Casos de teste R-fiddle (exemplo vetorizado, mas a mesma lógica)

Billywob
fonte
Como você já tem uma verificação length(s)==5, é possível substituir s[1]==tail(s,1)por s[1]==s[5]. Um método mais curto de um byte para verificar o comprimento é is.na(s[6]). Juntas, essas duas mudanças retornam TRUEno scomprimento 5 exatamente e de FALSEoutra forma, como TRUE&NAsão NAmas FALSE&NAsão FALSE. Você também pode salvar alguns bytes substituindo !sum(sign(d))&any(rle(sign(d))$l>1)por !sum(a<-sign(d))&any(rle(a)$l>1).
rturnbull
1

GNU Prolog, 47 bytes

i([A,B,C,D,A]):-A>B,B>C,C<D,D<A;i([B,C,D,A,B]).

Define um predicado ique obtém êxito (infinitamente muitas vezes, na verdade) para uma palavra infinita, emitindo "yes" quando executado a partir do intérprete (como é habitual no Prolog); falha em uma palavra candidata cujas primeiras e últimas letras não coincidem ou não têm 5 letras, emitindo "não" quando executadas no intérprete; e trava com um estouro de pilha se for dada uma palavra candidata que não seja uma palavra infinita, mas que seja cinco letras com a primeira e a última duas correspondências. (Não sei por quetrava; a chamada recursiva deve ser tratada como uma chamada de cauda. Aparentemente, o otimizador do GNU Prolog não é muito bom.) Sucesso é o equivalente do Prolog à verdade e, na sua falta, o equivalente ao falsey; uma falha é definitivamente mais falsa do que verdade, e corrigi-la tornaria a solução substancialmente mais longa, então espero que isso conte como uma solução válida.

O algoritmo é bastante simples (e, de fato, o programa é legível); verifique se as letras formam um dos quatro padrões que formam uma palavra infinita; se não, permitem cíclicamente e tente novamente. Não precisamos verificar explicitamente se há letras duplas, pois os operadores <e >permitem verificar implicitamente que, ao mesmo tempo, verificamos se os deltas correspondem.


fonte
1

Na verdade , 38 27 bytes

Essa resposta foi amplamente inspirada na excelente resposta de Jonathan Allan à geléia . Provavelmente existem vários lugares onde isso pode ser jogado, então sugestões de golfe são bem-vindas! Experimente online!

O;\♀-dY@♂s4R`0~;11({k`Míub*

Ungolfing

     Implicit input s.
O    Push the ordinals of s. Call this ords.
;    Duplicate ords.
\    Rotate one duplicate of ords left by 1.
♀-   Vectorized subtraction. This effectively gets the first differences of ords.
d    Pop ord_diff[-1] onto the stack. This is ords[0] - ords[-1].
Y    Logical negate ord_diff[-1], which returns 1 if s[0] == s[-1], else 0.
@    Swap (s[0] == s[-1]) with the rest of ord_diff.

♂s       Vectorized sgn() of ord_diff. This gets the signs of the first differences.
4R       Push the range [1..4] onto the stack.
`...`M   Map the following function over the range [1..4]. Variable x.
  0~;      Push -1 onto the stack twice.
  11       Push 1 onto the stack twice.
  (        Rotate x to TOS.
  {        Rotate the stack x times, effectively rotating the list [1, 1, -1, -1].
  k        Wrap it all up in a list.

     Stack: list of rotations of [1, 1, -1, -1], sgn(*ord_diff)
í    Get the 0-based index of sgn(*ord_diff) from the list of rotations. -1 if not found.
ub   This returns 1 only if sgn(*ord_diff) was found, else 0.
     This checks if the word loops like an infinity word.

*    Multiply the result of checking if the word s loops and the result of s[0] == s[-1].
     Implicit return.
Sherlock9
fonte
1

TI-BASIC, 81 bytes

A string a ser transmitida para o programa está em Ans. Retorna (e é exibido implicitamente) 1 se a palavra inserida é uma palavra infinita e 0 (ou sai com uma mensagem de erro) se não for.

seq(inString("ABCDEFGHIJKLMNOPQRSTUVWXYZ",sub(Ans,A,1)),A,1,length(Ans
min(Ans(1)=Ans(5) and {2,2}=abs(deltaList(deltaList(deltaList(Ans)/abs(deltaList(Ans

Erros em caracteres repetidos ou palavras que não sejam de 5 letras.

Josiah Winslow
fonte
1

05AB1E , 16 bytes

Ç¥DO_s.±¥¥Ä2DиQ*

Porto da resposta de @JonathanAllan Jelly .

Experimente online ou verifique todos os casos de teste .

Explicação:

Ç             # Convert the (implicit) input string to a list of unicode values
              #  i.e. "RULES" → [82,85,76,69,82]
 ¥            # Take the deltas
              #  i.e. [82,85,76,69,82] → [3,-9,-7,13]
  DO          # Duplicate and take the sum
              #  i.e. [3,-9,-7,13] → 0
    _         # Check if that sum is exactly 0
              # (which means the first and last characters are equal)
              #  i.e. 0 and 0 → 1 (truthy)
 s            # Swap so the deltas are at the top of the stack again
            # Get the sign of each
              #  i.e. [3,-9,-7,13] → [1,-1,-1,1]
    ¥         # Get the deltas of those signs
              #  i.e. [1,-1,-1,1] → [-2,0,2]
     ¥        # And then get the deltas of those
              #  i.e. [-2,0,2] → [2,2]
      Ä       # Convert them to their absolute values
       2Dи    # Repeat the 2 two times as list: [2,2]
          Q   # Check if they are equal
              #  i.e. [2,2] and [2,2] → 1 (truthy)
 *            # Check if both are truthy (and output implicitly)
              #  i.e. 1 and 1 → 1 (truthy)
Kevin Cruijssen
fonte