Pegue a raiz quadrada de uma corda

14

Motivação

Em deste desafio a sua tarefa era multiplicar duas cordas, isso naturalmente introduz uma maneira de tirar a raiz quadrada de um string.

Como funciona?

Dada uma sequência (por exemplo pub), a primeira coisa que você precisa fazer é determinar o código ASCII para cada caractere:

"pub" -> [112, 117, 98]

Em seguida, você mapeia esses códigos para o intervalo [0..94]subtraindo 32cada valor:

[112, 117, 98] -> [80, 85, 66]

Agora você precisa encontrar para cada valor seu módulo raiz 95(por exemplo 40*40 % 95 = 80, você também pode escolher 55):

[80, 85, 66] -> [40, 35, 16]

E finalmente, você o mapeará de volta para o intervalo [32..126]e o converterá em uma sequência de caracteres:

[40, 35, 16] -> [72, 67, 48] -> "HC0"

De fato, "HC0" ⊗ "HC0" = "pub"como você pode verificar com uma solução do outro desafio aqui .


Os familiarizados com a aritmética modular provavelmente notaram que o módulo da raiz quadrada 95nem sempre existe, por exemplo, não existe raiz para isso 2. Nesse caso, a raiz quadrada de uma string não é definida e seu programa / função pode falhar, executar um loop indefinidamente etc.

Para sua conveniência, aqui está a lista de caracteres que têm uma raiz quadrada (a primeira é um espaço):

 !$%&)+03489:>CDGLMQVW]`bjlpqu

Regras

  • Você escreverá um programa / função que usa uma string (ou lista de caracteres) como argumento e retorna qualquer raiz quadrada, se existir
  • Você pode supor que a entrada sempre tenha uma raiz quadrada
  • A entrada pode consistir em uma sequência vazia
  • A entrada estará no intervalo imprimível ( [32..126])
  • A saída é impressa no console ou você retorna uma sequência se a raiz quadrada existir
  • Caso a raiz quadrada não exista, o comportamento do seu programa / função é deixado indefinido
  • Se você optar por imprimir a raiz no console, as novas linhas ou espaços em branco serão excelentes

Casos de teste

Observe que essas não são necessariamente as únicas soluções:

''              -> ''
'pub'           -> 'HC0'
'pull!'         -> 'HC33!'
'M>>M'          -> '>MM>'
'49'            -> '4%'
'64'            -> undefined
'Hello, World!' -> undefined
ბიმო
fonte
Forçar um estado de erro nesses caracteres sem uma raiz quadrada parece desnecessário, recomendo apenas um comportamento indefinido.
ATaco 26/07
@ATaco Atualizei o desafio.
ბიმო
O que fazer se a sequência especificada for o quadrado de várias seqüências?
tsh
@tsh Retorne qualquer, atualizarei o desafio.
ბიმო
1
@curiousdannii Na verdade, deve ser o intervalo 0-94(esse é o intervalo imprimível), isso é um erro de digitação - desculpe por isso.
ბიმო

Respostas:

10

sh + coreutils, 58 bytes

tr '$%&)+0389:>CDGLMQVW]`bjpqu' 1u.#:BFO%+M/L2Aa,795d0@H=C

Experimente online!

A raiz quadrada modular normalmente não é única; temos 2 ou 4 opções para cada personagem, exceto . Nós não precisamos de traduzir , !, 4, luma vez que cada já é uma raiz quadrada de si. Para os caracteres restantes, escolhemos imagens que não precisam ser escapadas para o shell ou tr.

Anders Kaseorg
fonte
6

Python 3, 57 56 bytes

lambda s:s.translate({k*k%95+32:k+32for k in range(95)})

translateusa um mapeamento de "Ordinais Unicode para Ordinais Unicode". Assim, não precisamos de chr/ ordconversões. Nota: não falha quando o caractere não tem raiz.

Guardado 1 byte graças a @ jonathan-allan

O valor do mapeamento é a maior raiz no intervalo de 0 a 94 da chave. Para ter o mínimo de raiz (como nos exemplos), use:

lambda s:s.translate({k*k%95+32:k+32for k in range(95,0,-1)})

(61 bytes)

>>> [s.translate({k*k%95+32:k+32for k in range(95,0,-1)}) for s in ['','pub','pull!','M>>M','49','64','Hello, World!']]
['', 'HC0', 'HC33!', '>MM>', '4%', '64', 'He33o,\x7f9or3d!']
jferard
fonte
Bem-vinda! Bom primeiro post. Você pode remover o espaço entre 32e for.
22617 Jonathan Allan
... também, aqui está um link para um conjunto de testes de intérpretes online.
Jonathan Allan
3

Python 2 , 80 bytes

lambda s:''.join([chr(i+32)for i in range(95)if i*i%95==ord(c)-32][0]for c in s)

Experimente online!

Lança IndexError se não houver raiz.

Chas Brown
fonte
3

Japonês , 16 15 bytes

c@H+LDz%95+HÃbX

Experimente online!

Salve um byte olhando a resposta 05AB1E (usando L= 100 em vez de 95). Agora Japt é o mais curto, uma ocorrência bastante rara :-D

Explicação

 c@ H+LÇ   ²  %95+HÃ bX
UcX{H+LoZ{Zp2 %95+H} bX}   Ungolfed
                           Implicit: U = input string, H = 32, L = 100
UcX{                   }   Map each charcode X in the input to the following:
      Lo                     Create the array [0, 1, ..., 98, 99]
        Z{         }         and map each item Z to
          Zp2                  Z ** 2
              %95              mod 95
                 +H            plus 32.
                     bX      Find the first index of X in this array. This gives the
                             smallest square root (mod 95) of (X - 32).
    H+                       Add 32 to map this back into the printable range.
                           Implicit: output result of last expression
ETHproductions
fonte
2

Mathematica, 94 bytes

(R[x_]:=Min@Select[Range@45,Mod[#^2,95]==x&];FromCharacterCode[R/@(ToCharacterCode@#-32)+32])&


Experimente online!

J42161217
fonte
2

Geléia , 18 17 16 bytes

95Ḷ²%95+32żØṖFyO

Experimente online! (vem com rodapé da suíte de teste)

Economizou 2 bytes fazendo uma reescrita completa. Também a primeira vez que encontrei utilidade para }.

Explicação

O código primeiro calcula todos os caracteres quadrados e depois os mapeia para suas respectivas raízes quadradas.

95Ḷ²%95+32żØṖFyO    Main link. Argument: S (string)
95                    Take 95.
  Ḷ                   Get the array [0, 1, ..., 94].
   ²                  Square each to get [0, 1, ..., 8836].
    %95               Get each square modulo 95 to get [0, 1, ..., 1].
       +32            Add 32 to get [32, 33, ..., 33].
           ØṖ         Get the list of printables [" ", "!", ..., "~"].
          ż           Interleave with printables to get [[32, " "], ..., [33, "~"]].
             F        Flatten the mapping to [32, " ", ..., 33, "~"].
               O      Get the code point of each character in input.
              y       Map the code points to the correct output characters using the map.
PurkkaKoodari
fonte
95Ḷ²%95+32iЀO+31Ọé basicamente o que a minha resposta Japt faz, embora a sua solução é de dois bytes mais curto ...
ETHproductions
2

JavaScript, 82 bytes

Colaborou com @ETHproductions

s=>s.map(x=>(g=z=>z*z%95==x.charCodeAt(0)-32?String.fromCharCode(z+32):g(z+1))(0))

Entrada e saída estão na forma de uma matriz de caracteres.

Snippet de teste

Oliver
fonte
2

05AB1E , 17 bytes

vтLn95%žQykk33+ç?

O algoritmo é muito parecido com a resposta Jelly e Japt (tinha outra coisa antes, mas isso só me levou a 19 bytes)

Explicação

vтLn95%žQykk33+ç?
v                 # For each character of the input...
 тL                # Push [1..100]
   n               # Square every element of the list
    95%            # And take it modulo 95
       žQyk        # Push the index of the current character in the printable ascii range
           k       # Push the index of that in the list created earlier
            33+    # Add 33 to the result
               ç   # And convert it back to a character
                ?  # Print the character

Experimente online!

Datboi
fonte
1

Mathematica, 60 bytes

FromCharacterCode[PowerMod[ToCharacterCode@#-32,1/2,95]+32]&

Função anônima. Pega uma string como entrada e retorna uma string como saída. Erros na entrada inválida.

LegionMammal978
fonte
1

Perl 6 , 53 bytes

{[~] .comb.map({32+first *²%95==.ord-32,^95})».chr}

Experimente online!

Sean
fonte
1

Mathematica 82 Bytes

FromCharacterCode[Solve[x^2==#,Modulus->95][[1,1,2]]+32&/@(ToCharacterCode@#-32)]&

Usando a capacidade do Solve para fazer aritmética modular.

Kelly Lowder
fonte