Toma la raíz cuadrada de una cuerda

14

Motivación

En este desafío, su tarea consistía en multiplicar dos cadenas, esto naturalmente introduce una forma de sacar la raíz cuadrada de una cadena.

¿Como funciona?

Dada una cadena (por ejemplo pub), lo primero que debe hacer es determinar el código ASCII para cada carácter:

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

A continuación, asigna estos códigos al rango [0..94]restando 32cada valor:

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

Ahora necesita encontrar para cada valor su módulo raíz 95(por ejemplo 40*40 % 95 = 80, también podría elegir 55):

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

Y finalmente lo volverá a asignar al rango [32..126]y lo convertirá de nuevo en una cadena:

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

En efecto "HC0" ⊗ "HC0" = "pub" como puede verificar con una solución del otro desafío aquí .


Los que están familiarizados con la aritmética modular. probablemente notaron que el módulo de raíz cuadrada 95no siempre existe, por ejemplo, no hay raíz 2. En tal caso, la raíz cuadrada de una cadena no está definida y su programa / función puede fallar, repetirse indefinidamente, etc.

Para su comodidad, aquí está la lista de caracteres que tienen una raíz cuadrada (el primero es un espacio):

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

Reglas

  • Escribirás un programa / función que tome una cadena (o lista de caracteres) como argumento y devuelva cualquier raíz cuadrada si existe
  • Puede suponer que la entrada siempre tiene una raíz cuadrada
  • La entrada puede consistir en una cadena vacía
  • La entrada estará en el rango imprimible ([32..126] )
  • El resultado se imprime en la consola o devuelve una cadena si existe la raíz cuadrada
  • En caso de que la raíz cuadrada no exista, el comportamiento de su programa / función se deja sin definir
  • Si elige imprimir la raíz en la consola, las líneas nuevas o espacios en blanco finales están bien

Casos de prueba

Tenga en cuenta que estas no son necesariamente las únicas soluciones:

''              -> ''
'pub'           -> 'HC0'
'pull!'         -> 'HC33!'
'M>>M'          -> '>MM>'
'49'            -> '4%'
'64'            -> undefined
'Hello, World!' -> undefined
ბიმო
fuente
Forzar un estado de error en estos caracteres sin una raíz cuadrada parece innecesario, recomendaría un comportamiento indefinido.
ATaco
@ATaco Actualicé el desafío.
ბიმო
¿Qué hacer si la cadena dada es el cuadrado de varias cadenas?
tsh
@tsh Devuelve cualquiera, actualizaré el desafío.
ბიმო
1
@curiousdannii En realidad debería ser el rango 0-94(ese es el rango imprimible), es un error tipográfico, lo siento.
ბიმო

Respuestas:

10

sh + coreutils, 58 bytes

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

Pruébalo en línea!

La raíz cuadrada modular generalmente no es única; Tenemos 2 o 4 opciones para cada personaje excepto . No necesitamos traducir , !, 4, lya que cada uno es ya una raíz cuadrada de sí mismo. Para los caracteres restantes, elegimos imágenes que no necesitan escapar para el shell o tr.

Anders Kaseorg
fuente
6

Python 3, 57 56 bytes

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

translateutiliza una asignación de "ordinales Unicode a ordinales Unicode". Por lo tanto, no necesitamos chr/ ordconversiones. Nota: no se bloquea cuando el carácter no tiene raíz.

Guardado 1 byte gracias a @ jonathan-allan

El valor de la asignación es la raíz más grande en el rango 0..94 de la clave. Para tener la menor raíz (como en los ejemplos), 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
fuente
¡Bienvenido! Bonito primer post. Puede eliminar el espacio entre 32y for.
Jonathan Allan
... también, aquí hay un enlace a un conjunto de pruebas de interpretación en línea.
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)

Pruébalo en línea!

Lanza IndexError si no existe una raíz.

Chas Brown
fuente
3

Japt , 16 15 bytes

c@H+LDz%95+HÃbX

Pruébalo en línea!

Guarda un byte mirando la respuesta 05AB1E (usando L= 100 en lugar de 95). Ahora Japt es el más corto, una ocurrencia bastante rara :-D

Explicación

 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
fuente
2

Mathematica, 94 bytes

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


Pruébalo en línea!

J42161217
fuente
2

Jalea , 18 17 16 bytes

95Ḷ²%95+32żØṖFyO

Pruébalo en línea!(viene con el pie de página de la suite de pruebas)

Ahorró 2 bytes haciendo una reescritura completa. También la primera vez que he encontrado uso para }.

Explicación

El código primero calcula todos los caracteres cuadrados y luego los asigna a sus respectivas raíces cuadradas.

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
fuente
95Ḷ²%95+32iЀO+31Ọes básicamente lo que hace mi respuesta de Japt, aunque su solución es dos bytes más corta ...
ETHproductions
2

JavaScript, 82 bytes

Colabora con @ETHproductions

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

La entrada y la salida tienen la forma de una matriz de caracteres.

Fragmento de prueba

Oliver
fuente
2

05AB1E , 17 bytes

vтLn95%žQykk33+ç?

El algoritmo es muy similar a la respuesta de Jelly y Japt (tenía algo más antes, pero eso solo me llevó a 19 bytes)

Explicación

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

Pruébalo en línea!

Datboi
fuente
1

Mathematica, 60 bytes

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

Función anónima. Toma una cadena como entrada y devuelve una cadena como salida. Errores en entrada inválida.

LegionMammal978
fuente
1

Mathematica 82 Bytes

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

Usando la capacidad de Solve para hacer aritmética modular.

Kelly Lowder
fuente