Caracteres alfabéticos cruzados

17

Antecedentes

Vi este diagrama de Venn muy interesante en Wikipedia: https://simple.wikipedia.org/wiki/Alphabet#/media/File:Venn_diagram_gr_la_ru.svg

Muestra las letras (formas físicas) en diferentes alfabetos que son comunes entre los alfabetos ruso, griego y latino.

El reto

Dada una cadena de entrada de caracteres de cualquiera de los tres scripts mostrados (es decir, letras mayúsculas griegas, cirílicas o latinas), genera un porcentaje de la cadena que coincide con cada idioma. Las letras repetidas cuentan cada vez.

Por ejemplo, FFLURSson todos los caracteres latinos, por lo que la salida es FFLURS is 100% Latin, 0% Cyrillic and 0% Greek.

Por el contrario, TOX BEAM PHPestá formado completamente por caracteres que aparecen en los tres idiomas, por lo que el resultado es TOX BEAM PHP is 100% Cyrillic, 100% Greek and 100% Latin.

Tablas de búsqueda

El diagrama de Venn es la fuente de las siguientes letras:

Solo latín:

J,G,S,D,Q,U,V,W,F,L,R

Latín y cirílico:

C, С

Latín y griego:

I,Ι, N,Ν, Z,Ζ

Griego y cirílico

Φ,Ф, Π,П, Γ,Г, Λ,Л

Los tres:

A,B,E,O,M,K,T,X,Y,H,P (and equivalents in greek and cyrillic), (space)

El resto ... son solo griegos o cirílicos.

NOTA IMPORTANTE

Unicode define (por ejemplo) "A" en (al menos) tres formas distintas, una para cada idioma. Cualquiera que se use en la entrada (& # 0391, & # 0410 o & # 0041), el programa debe entender que coincide con los tres idiomas. Entonces, A(latín), Α(griego alfa) y А(cirílico) deberían dar 100% Cyrillic, 100% Greek and 100% Latincomo respuesta.

Formato de entrada

Cualquier cadena que contiene exclusivamente А-Я, Α-Ω, A-Zy (espacio). Estos caracteres se pueden repetir varias veces dentro de la cadena.

Formato de salida

La salida puede estar en cualquier formato, siempre que la función produzca resultados consistentes. Me gustaría ver la salida en el formato que muestro en mis ejemplos ( FFLURS is 100% Latin, 0% Cyrillic and 0% Greek), pero para que el desafío sea más abierto para todos, estoy feliz de aceptar matrices / cadenas de porcentajes / proporciones:

[100,0,0],

100 0 0

[1.0 0.0 0.0]

siempre que esté claro qué número es qué idioma, por lo que el resultado debe ser coherente.

Algunos casos de prueba más

CINEMATICS -> CINEMATICS is 100% Latin, 70% Greek and 60% Cyrillic

ЩJЩFЩLΞRΞVΞW -> ЩJЩFЩLΞRΞVΞW is 50% Latin, 25% Cyrillic and 25% Greek

-> is 100% Cyrillic, 100% Greek and 100% Latin

ΨΩTESTINGЯЮ -> ΨΩTESTINGЯЮ is 63.6% Greek, 63.6% Latin and 45.5% Cyrillic

Criterios ganadores

Se aplican las reglas y exclusiones habituales; la respuesta más corta (bytes) gana.

(enlace de sandbox: https://codegolf.meta.stackexchange.com/a/14984/62289 )

Para evitar dudas, los únicos caracteres Unicode válidos en la entrada son:

  • 0020, 0041-005A (alfabeto latino)
  • 0020, 0391-03A9 (alfabeto griego)
  • 0020, 0401, 0410-042F (alfabeto cirílico)

Pero como se muestra en las tablas de búsqueda, los caracteres pueden ser alfabéticos cruzados.

Agregando la tabla de Jonathan Allan de los comentarios:

                                                 Latin  Greek  Cyrillic
U+0020     Space                                 1      1      1
U+0041  A  Latin capital letter A                1      1      1
U+0042  B  Latin capital letter B                1      1      1
U+0043  C  Latin capital letter C                1      0      1
U+0044  D  Latin capital letter D                1      0      0
U+0045  E  Latin capital letter E                1      1      1
U+0046  F  Latin capital letter F                1      0      0
U+0047  G  Latin capital letter G                1      0      0
U+0048  H  Latin capital letter H                1      1      1
U+0049  I  Latin capital letter I                1      1      0
U+004A  J  Latin capital letter J                1      0      0
U+004B  K  Latin capital letter K                1      1      1
U+004C  L  Latin capital letter L                1      0      0
U+004D  M  Latin capital letter M                1      1      1
U+004E  N  Latin capital letter N                1      1      0
U+004F  O  Latin capital letter O                1      1      1
U+0050  P  Latin capital letter P                1      1      1
U+0051  Q  Latin capital letter Q                1      0      0
U+0052  R  Latin capital letter R                1      0      0
U+0053  S  Latin capital letter S                1      0      0
U+0054  T  Latin capital letter T                1      1      1
U+0055  U  Latin capital letter U                1      0      0
U+0056  V  Latin capital letter V                1      0      0
U+0057  W  Latin capital letter W                1      0      0
U+0058  X  Latin capital letter X                1      1      1
U+0059  Y  Latin capital letter Y                1      1      1
U+005A  Z  Latin capital letter Z                1      1      0

U+0391  Α  Greek capital letter Alpha            1      1      1
U+0392  Β  Greek capital letter Beta             1      1      1
U+0393  Γ  Greek capital letter Gamma            0      1      1
U+0394  Δ  Greek capital letter Delta            0      1      0
U+0395  Ε  Greek capital letter Epsilon          1      1      1
U+0396  Ζ  Greek capital letter Zeta             1      1      0
U+0397  Η  Greek capital letter Eta              1      1      1
U+0398  Θ  Greek capital letter Theta            0      1      0
U+0399  Ι  Greek capital letter Iota             1      1      0
U+039A  Κ  Greek capital letter Kappa            1      1      1
U+039B  Λ  Greek capital letter Lambda           0      1      1
U+039C  Μ  Greek capital letter Mu               1      1      1
U+039D  Ν  Greek capital letter Nu               1      1      0
U+039E  Ξ  Greek capital letter Xi               0      1      0
U+039F  Ο  Greek capital letter Omicron          1      1      1
U+03A0  Π  Greek capital letter Pi               0      1      1
U+03A1  Ρ  Greek capital letter Rho              1      1      1

U+03A3  Σ  Greek capital letter Sigma            0      1      0
U+03A4  Τ  Greek capital letter Tau              1      1      1
U+03A5  Υ  Greek capital letter Upsilon          1      1      1
U+03A6  Φ  Greek capital letter Phi              0      1      1
U+03A7  Χ  Greek capital letter Chi              1      1      1
U+03A8  Ψ  Greek capital letter Psi              0      1      0
U+03A9  Ω  Greek capital letter Omega            0      1      0

U+0401  Ё  Cyrillic capital letter Io            0      0      1

U+0410  А  Cyrillic capital letter A             1      1      1
U+0411  Б  Cyrillic capital letter Be            0      0      1
U+0412  В  Cyrillic capital letter Ve            1      1      1
U+0413  Г  Cyrillic capital letter Ghe           0      1      1
U+0414  Д  Cyrillic capital letter De            0      0      1
U+0415  Е  Cyrillic capital letter Ie            1      1      1
U+0416  Ж  Cyrillic capital letter Zhe           0      0      1
U+0417  З  Cyrillic capital letter Ze            0      0      1
U+0418  И  Cyrillic capital letter I             0      0      1
U+0419  Й  Cyrillic capital letter Short I       0      0      1
U+041A  К  Cyrillic capital letter Ka            1      1      1
U+041B  Л  Cyrillic capital letter El            0      1      1
U+041C  М  Cyrillic capital letter Em            1      1      1
U+041D  Н  Cyrillic capital letter En            1      1      1
U+041E  О  Cyrillic capital letter O             1      1      1
U+041F  П  Cyrillic capital letter Pe            0      1      1
U+0420  Р  Cyrillic capital letter Er            1      1      1
U+0421  С  Cyrillic capital letter Es            1      0      1
U+0422  Т  Cyrillic capital letter Te            1      1      1
U+0423  У  Cyrillic capital letter U             1      1      1
U+0424  Ф  Cyrillic capital letter Ef            0      1      1
U+0425  Х  Cyrillic capital letter Ha            1      1      1
U+0426  Ц  Cyrillic capital letter Tse           0      0      1
U+0427  Ч  Cyrillic capital letter Che           0      0      1
U+0428  Ш  Cyrillic capital letter Sha           0      0      1
U+0429  Щ  Cyrillic capital letter Shcha         0      0      1
U+042A  Ъ  Cyrillic capital letter hard sign     0      0      1
U+042B  Ы  Cyrillic capital letter Yeru          0      0      1
U+042C  Ь  Cyrillic capital letter soft sign     0      0      1
U+042D  Э  Cyrillic capital letter E             0      0      1
U+042E  Ю  Cyrillic capital letter Yu            0      0      1
U+042F  Я  Cyrillic capital letter Ya            0      0      1
simonalexander2005
fuente
1
Bienvenido a PPCG! Este es un buen primer desafío. :) Una nota en su nota UTF-8: no es UTF-8 que define múltiples versiones de estos caracteres, sino Unicode (y UTF-8 es solo una forma específica de codificar puntos de código Unicode). Además, dado que esta parte es bastante importante para que las respuestas sean correctas, es posible que desee incluir la lista explícita de todos los caracteres Unicode que deben manejarse correctamente.
Martin Ender
@ngn sí, gracias.
simonalexander2005
@JonathanAllan, ngn: Estoy de acuerdo, solo pretendía las letras que están en el diagrama de Venn, pero todas las representaciones de esas letras son válidas, como trato de decir en la pregunta, hay múltiples representaciones unicode de "A", por ejemplo
simonalexander2005
El cirílico "El" es en realidad griego "Lambda". Cirílico "Pe" es griego "Pi".
simonalexander2005
@JonathanAllan Dependiendo de la fuente, cirílico Л puede verse exactamente como griego Λ. La forma similar a Π es solo otra variación estilística de la misma letra.
ngn

Respuestas:

4

Jalea , 56 bytes

Un hash bien puede ser más corto.

O:⁹:2;ON©œị“ŒḂI4ƥƒⱮıtɱN¦“¤COṙṚ¹`“ÑṂḄẈɼ]ġÐ’b4¤+4Bṙ®Ḣµ€S÷L

Un enlace monádico que devuelve una lista de importes de proporción en el orden inglés, griego, ruso.

Pruébalo en línea!
... o vea una salida con formato completo (incluido el redondeo implícito a un decimal)

¿Cómo?

Deseamos tener un código que traduzca cada carácter posible a un triple de unos y ceros que represente si pertenecen a cada uno de los alfabetos (al igual que la tabla en la pregunta dónde Cestá 1 0 1). Una vez hecho esto, podemos sumarlos y dividirlos por la longitud para obtener las proporciones (entre cero y uno inclusive); esto es solo S÷L(visto a la derecha del código).

Para cualquier carácter dado Sabemos que si el ordinal es menor que 256 se cuenta como inglés, si es mayor que 1024 se cuenta como ruso, y si se encuentra entre 256 y 1024 se cuenta como griego. Como tal, tomar el ordinal y el entero dividiendo por 256 y luego el entero dividiendo el resultado entre dos rendimientos 0para el espacio y los caracteres latinos (cuentan como inglés), 1para helénico (cuentan como griego) y 2para cirílico (cuentan como ruso). Esto es solo O:⁹:2en Jelly (visto a la izquierda del código).

Si rotamos los triples de bits de modo que el bit * natural del alfabeto sea el más significativo, entonces podemos codificar los dos bits inferiores (como valores entre cero y tres inclusive) en una tabla de búsqueda con tres filas y luego rotar a la derecha números encontrados arriba.

Cuando hacemos esto, hay dos cosas dignas de mención: 1. Jelly tiene un átomo de rotación a la izquierda, no uno de rotación a la derecha; 2. la fila helénica de la tabla de búsqueda comenzaría con un cero (ya Ξque solo es griego), frustrando una codificación simple de base 4 (ya que los ceros iniciales no son codificables). Para aliviar (1) podemos rotar a la izquierda por el valor negado y para aliviar (2) podemos codificar nuestras filas en reversa e indexarlas con la cantidad negativa. De esta forma, podemos negar tanto el índice de fila como el de columna con un solo byte ( N) como tal, nuestros índices de fila y columna pueden calcularse con O:⁹:2;ON.

Tenga en cuenta que la jalea ahora tiene un átomo de indexación multidimensional, œị.

La tabla está formada por tres números grandes que, una vez convertidos a base cuatro, dan los bits más bajos requeridos para cirílico, griego y latino (+ Espacio) respectivamente. Tienen una longitud mínima, de modo que es posible la indexación modular por los valores ordinales negados: 47, 25 y 30 respectivamente (los .s están en índices no utilizados):

1: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 1 3 3 2 3 1 3 3 3 1 3 0 0 0 0 3 0 1 3 0 3 0 0 0 0 0 0
   . . . . . . . . . Я Ю Э Ь Ы Ъ Щ Ш Ч Ц Х Ф У Т С Р П О Н М Л К Й И З Ж Е Д Г В Б А Ё . . . . .

2: 3 2 3 1 0 3 1 3 0 2 3 3 0 0 3 2 3 3 0 0 3 2 3 0 1
   Μ Λ Κ Ι Θ Η Ζ Ε Δ Γ Β Α Ω Ψ Χ Φ Υ Τ Σ . Ρ Π Ο Ξ Ν

3: 3 3 0 0 0 3 0 0 0 3 3 2 3 0 3 0 2 3 0 0 3 0 1 3 3 0 0 3 0 2
   Y X W V U T S R Q P O N M L K J I H G F E D C B A . .   . Z

Como ejemplo, considere el carácter Φ en el punto Unicode U + 03A6 (que debería producir [0,1,1]) tiene un valor ordinal de (3 × 16² + 10 × 16 + 6 =) 934. ( O:⁹:2significa 934 // 256 // 2 =) 1 identificándolo como parte del bloque helénico. El ;Oconcatena el ordinal que nos da [1,934]y Nluego niega ambos valores que nos dan [-1,-934]. Dado que la indexación Jelly está basada en 1 y es modular y hay tres filas, las -1referencias son la segunda de las tres filas (fila 2 en el bloque de código anterior), ya que la fila del medio tiene una longitud de 25 las -934referencias ((-934% 25 =) 16ª entrada en esa fila, que es 2. El código luego agrega cuatro (el bit más significativo) dándonos 6qué convertido a binario es[1,1,0]. El código luego gira esto a la izquierda por cada uno [-1,-934]y toma la cabeza (es decir, la rotación hacia la izquierda por -1, una rotación hacia la derecha en 1) cediendo [0,1,1]según sea necesario.

* Inglés para el espacio ya que está agrupado con los caracteres latinos.


Código comentado

O:⁹:2;ON©œị“...“...“...’b4¤+4Bṙ®Ḣµ€S÷L - Link: list of characters        e.g.: "СЯ"
                                 µ€    - for €ach character:                С       Я
O                                      -   cast to ordinal               1057    1071
  ⁹                                    -   literal 256
 :                                     -   integer division                 4       4
   :2                                  -   integer divide by 2              2       2
      O                                -   cast to ordinal               1057    1071
     ;                                 -   concatenate                  [2,1057] [2,1071]
       N                               -   negate                     [-2,-1057] [-2,-1071]
        ©                              -   copy to register for later
                          ¤            -   nilad followed by link(s) as a nilad:
           “...“...“...’               -     list of integers encoded in base 250 = [4951760157204492290900832256, 1043285073970097, 1081712651052809266]
                        b4             -     convert to base 4                    = [[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,1,3,3,2,3,1,3,3,3,1,3,0,0,0,0,3,0,1,3,0,3,0,0,0,0,0,0],[3,2,3,1,0,3,1,3,0,2,3,3,0,0,3,2,3,3,0,0,3,2,3,0,1],[3,3,0,0,0,3,0,0,0,3,3,2,3,0,3,0,2,3,0,0,3,0,1,3,3,0,0,3,0,2]]
         œị                            -   index into                       2       0                   ^--[-2,-1071]   [-2,-1057]--^
                           +4          -   add four                         6       4
                             B         -   convert to binary             [1,1,0] [1,0,0]
                               ®       -   recall from register       [-2,-1057] [-2,-1071]
                              ṙ        -   rotate left         [[1,0,1],[0,1,1]] [[0,0,1],[1,0,0]]
                                Ḣ      -   head                          [1,0,1] [0,0,1]
                                   S   - sum                                 [1,0,2]
                                     L - length                                 2
                                    ÷  - divide                            [0.5,0,1]
                                       -   i.e.: 50.0% Latin, 0% Greek, 100% Russian
Jonathan Allan
fuente
Parece que tienes algo de terminología allí ... ¿"hash" significa una construcción como (keys)iị(values)Ʋ?
Erik the Outgolfer
Me refiero a formar un conjunto distinto de claves a partir de alguna manipulación matemática para que uno pueda indexar en una lista de valores, sí. Así como ...ị“...o posiblemente ...ṃ“...(estrictamente hablando, la cadena monádica que formé es una función hash )
Jonathan Allan
@ngn M kebard es anning
Jonathan Allan
¡Oh, sé cómo arreglar eso! Vuelva a configurar su teclado y escriba cirílico "у" y "о" en lugar de "y" y "o": D
ngn
Nunca he visto una respuesta tan larga de Jelly ... ¡gran trabajo!
simonalexander2005
5

JavaScript (ES6), 197 179 bytes

Devuelve una matriz de 3 razones en [0..1].

s=>[...s].map(_=>(x='b;C6cC6%c>b^[<$]_3--_c_acC-----$+aKHbKK[`H`H]'[(p=s[a='charCodeAt'](l++)%202%116%89)>>1][a]()-36,x/=p&1||8,L+=x/4&1,G+=x/2&1,C+=x&1),l=L=G=C=0)&&[L/l,G/l,C/l]

Pruébalo en línea!

¿Cómo?

Utilizamos la función hash (bastante ineficiente) % 202 % 116 % 89para transformar cada código de caracteres en un índice en [0..88]. La tabla de búsqueda correspondiente consta de entradas de 3 bits donde bit # 2 = latín, bit # 1 = griego y bit # 0 = cirílico. Usando dígitos decimales, esto da:

76273722773722017732767267300071731711117377737577371111111111000775474476474767744474447

Agregamos un extra 1para obtener un número par de entradas y codificar este flujo de bits con caracteres ASCII imprimibles en el rango [37..99] ( %a c), con 6 bits de datos de carga útil por carácter.

Esto lleva a la siguiente cadena:

b;C6cC6%c>b^[<$]_3--_c_acC-----$+aKHbKK[`H`H]

El desplazamiento se eligió para evitar que caracteres como \ese hubieran requerido escapar.

Arnauld
fuente
3

Ruby , 165 bytes

->s{(0..2).map{|x|s.chars.map{|c|o=c.ord;(o<33?7:"ĝ]ē¯]÷W59WUė½ñĝĕ×ßoĝėÏė55#{?!*15}"[o-[913,1040,65][y=o>>7<=>7]].ord+226>>3*-~y)[x]*1.0}.sum/s.size}}

Pruébalo en línea!

Editar: jugó significativamente el código y, lo más importante, apretó 3 secuencias de traducción en una cadena UTF-8. El código original más largo se mantiene a continuación para una mejor legibilidad y explicación de la lógica.

Rubí, 211 bytes

->s{(0..2).map{|x|s.chars.map{|x|o=x.ord;o<33?7:o<91?"77517117317173771117111773"[o-65]:o<938?"7762737237673276702776722"[o-913]:"74764744444767776757767#{?4*15}"[o-1040]}.inject(0.0){|y,z|y+=z.to_i[x]}/s.size}}

Pruébalo en línea!

Puede que no sea el enfoque más eficiente, pero hace el trabajo. Utiliza una tabla de traducción para cada alfabeto con la aparición de caracteres en diferentes scripts codificados por los bits del número (en el orden: latín, griego, ruso). La salida es una matriz de porcentajes en el mismo orden.

Para arreglar el Ёcaso atípico , extendí el bloque de 4 s solo en ruso desde 10 posiciones al final del alfabeto hasta 15. De esta manera, Ёse selecciona correctamente con índice negativo (y no estamos obligados a manejar letras minúsculas que correspondan a estos índices extra).

Kirill L.
fuente
1

Retina 0.8.2 , 230 bytes

.+
$&¶$&¶$&¶$&
T`ΓΔΘΛΞΠΣΦΨΩЁБГДЖ-ЙЛПФЦ-Я`_`.+(?=¶.+¶.+$)
T`CDFGJ\LQRSUVWЁБДЖ-ЙС-Я`_`.+(?=¶.+$)
T`DFGIJ\LNQRSUVWZΔΖΘΙΝΞΣΨΩ`_`.+$
¶(.*)
¶$.1$*
1
100$*
.
1
(1+)¶(\1)*1*¶(\1)*1*¶(\1)*1*
$#2 $#3 $#4

Pruébalo en línea! El enlace incluye casos de prueba. Nota: La salida está en% truncada a un número entero, porque al aumentar la precisión, el script se hizo demasiado lento y se agotó el tiempo en TIO.

Neil
fuente