Criptic Kicker //

12

Kicker Críptico

Um método comum, porém inseguro, de criptografar texto é permutar as letras do alfabeto. Em outras palavras, cada letra do alfabeto é consistentemente substituída no texto por alguma outra letra. Para garantir que a criptografia seja reversível, duas letras não serão substituídas pela mesma letra. Sua tarefa é descriptografar várias linhas de texto codificadas, assumindo que cada linha use um conjunto diferente de substituições e que todas as palavras no texto descriptografado sejam de um dicionário de palavras conhecidas.

Entrada

A entrada consiste em palavras em minúsculas, em ordem alfabética. Essas palavras compõem o dicionário de palavras que podem aparecer no texto descriptografado. A seguir ao dicionário, várias linhas de entrada. Cada linha é criptografada como descrito acima.

Não há mais de 1.000 palavras no dicionário. Nenhuma palavra excede 16 letras. As linhas criptografadas contêm apenas letras minúsculas e espaços e não excedem 80 caracteres.

Resultado

Descriptografe cada linha e imprima-a na saída padrão. Se houver várias soluções, qualquer um fará. Se não houver solução, substitua todas as letras do alfabeto por um asterisco.

Entrada de amostra

and dick jane puff spot yertle

bjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn
xxxx yyy zzzz www yyyy aaa bbbb ccc dddddd

Saída de amostra

dick and jane and puff and spot and yertle
**** *** **** *** **** *** **** *** ******

Aqui está a solução. Observe que eu não sou um cavalo correndo na corrida pelos bytes mais curtos / programador competitivo. Eu apenas gosto de quebra-cabeças!

( Fonte )

Dhruv Ramani
fonte
1
Relaxe suas restrições de entrada <> para algo aplicável a cada idioma. Por exemplo, muitos idiomas odeiam, e não apreciam que o formato comece com um 6. Eu sugiro deixar o formato totalmente não especificado, e apenas dizer que a entrada é uma lista de palavras e uma lista de linhas a serem criptografadas.
orlp 8/08/2015
Ok, lá vai você!
Dhruv Ramani
1
Existem restrições de tempo de execução para isso? Posso simplesmente percorrer todas as combinações possíveis de substituição, até que funcione (o que provavelmente levaria anos para terminar)?
Nathan Merrill
@NathanMerrill Faça isso e, se levar anos, imprima-o na forma de estrela. Vihan, não é uma cópia duplicada, por favor leia a pergunta corretamente.
Dhruv Ramani
Podemos apenas produzir as palavras ou precisamos nos juntar a elas?
Downgoat 9/08/2015

Respostas:

3

Python 3, 423 bytes

import sys,re
S=re.sub
D,*L=sys.stdin.read().split('\n')
def f(W,M=[],V="",r=0):
 if len({d for(s,d)in M})==len(M):
  if[]==W:return V.lower()
  for d in D.split():p='([a-z])(?%s.*\\1)';m=re.match(S(p%'=',')\\1=P?(',S(p%'!',').>\\1<P?(',W[0].translate(dict(M))[::-1]))[::-1]+'$',d.upper());r=r or m and f(W[1:],M+[(ord(s),m.group(s))for s in m.groupdict()],V+d+" ")
  return r
for l in L:print(f(l.split())or S('\w','*',l))

Lê a entrada de STDIN e grava a saída em STDOUT, usando o mesmo formato da entrada / saída de amostra.

Explicação

Para cada linha de texto cifrado, realizamos o seguinte procedimento:

Mantemos um mapa, M , de todas as transformações de letras que já estabelecemos (que estão inicialmente vazias). Fazemos isso de maneira que as letras de origem estejam todas em minúsculas e as de destino em maiúsculas.

Processamos as palavras no texto cifrado em ordem. Para cada palavra, encontramos todas as palavras no dicionário que podem corresponder, da seguinte forma:

Suponha que nossa palavra, w , seja glpplppljjle que M contenha a regra j -> P. Primeiro, transformamos w usando as regras existentes em M , obtendo glpplpplPPl. Em seguida, transformamos w no seguinte regex com sabor de python:

(?P<g>.)(?P<l>.)(?P<p>.)(?P=p)(?P=l)(?P=p)(?P=p)(?P=l)PP(?P=l)

As regras da transformação são as seguintes:

  • A primeira ocorrência de cada letra minúscula x, é substituída por . Isso define um grupo de captura nomeado, chamado , que corresponde a um único cahracter.(?P<x>.)x
  • A cada ocorrência subsequente, cada letra minúscula x, é substituída por . Esta é uma referência anterior ao personagem capturado anteriormente pelo grupo nomeado .(?P=x)x

Realizamos essa transformação revertendo w e aplicando as duas substituições de regex a seguir:

s/([a-z])(?!.*\1)/)>\1<P?(/
s/([a-z])(?=.*\1)/)\1=P?(/

e depois revertendo o resultado. Observe que os caracteres anteriormente transformados por M aparecem em maiúsculas e, portanto, permanecem inalterados.

Combinamos a regex resultante com cada uma das palavras do dicionário, onde as palavras do dicionário aparecem em maiúsculas. Por exemplo, o regex acima corresponderia à palavra MISSISSIPPI. Se encontrar uma correspondência, extraímos as novas regras de transformação a partir dele, e adicioná-los ao M . As novas regras de transformação são simplesmente os caracteres capturados por cada um dos grupos de captura. No regex acima, o grupo gcorresponde M, o grupo de ljogo I, eo grupo de ppartidas S, dando-nos as regras g -> M, l -> I, p -> S. Temos que garantir que as regras resultantes sejam consistentes, ou seja, que nenhuma letra de origem seja mapeada para a mesma letra de destino; caso contrário, rejeitamos a partida.

Em seguida, prosseguimos para a próxima palavra, usando as regras de transformação aumentada. Se conseguirmos combinar todas as palavras do texto cifrado usando esse processo, descriptografamos o texto. Se não conseguirmos combinar uma palavra com nenhuma das palavras do dicionário, retornamos e tentamos corresponder as palavras anteriores com diferentes palavras do dicionário. Se esse processo falhar, não há solução e imprimimos uma linha de asteriscos.

Ell
fonte
2

CJam, 62 56 bytes

qN%Sf/(f{\:C,m*{C..+`Sa`m2/Q|z_''f-Qf|=},C:,'*f*a+0=S*N}

Bastante lento e com muita memória, mas funciona para o caso de teste com o interpretador Java.

Exemplo de execução

$ cat input; echo
and dick jane puff spot yertle

bjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn
xxxx yyy zzzz www yyyy aaa bbbb ccc dddddd
$ time cjam kicker.cjam < input
dick and jane and puff and spot and yertle
**** *** **** *** **** *** **** *** ******

real    5m19.817s
user    6m41.740s
sys     0m1.611s
Dennis
fonte