¿Es el escritor un hombre o una mujer?

8

Un problema en un sitio web como este es que a menudo no sabes si estás hablando con un hombre o una mujer. Sin embargo, se le ocurrió una técnica simple de PNL que puede utilizar para determinar el género del escritor de un texto.

Teoría

Alrededor del 38.1% de las letras usadas en inglés son vocales [a, e, i, o, u] (ver Referencias a continuación, yNO es una vocal en este caso). Por lo tanto, definiremos cualquier palabra que tenga al menos 40% de vocales como palabra femenina , y cualquier palabra que tenga menos de 40% de vocales como palabra masculina .

Más allá de esta definición, también podemos encontrar la masculinidad o feminidad de una palabra. Sea C el número de consonantes en la palabra y V sea ​​el número de vocales:

  • Si una palabra es femenina, es feminidad 1.5*V/(C+1).
  • Si una palabra es masculina, es masculinidad C/(1.5*V+1).

Por ejemplo, la palabra catches masculina. Su masculinidad es 4/(1.5*1+1) = 1.6. La palabra phonees femenina. Su feminidad es 1.5*2/(3+1) = .75.

Algoritmo

Para determinar el género del escritor de un texto, tomamos la suma de la masculinidad de todas las palabras masculinas (Σ M ) y la suma de la feminidad de todas las palabras femeninas (Σ F ). Si Σ M > Σ F , hemos determinado que el escritor es un hombre. De lo contrario, hemos determinado que el escritor es una mujer.

Nivel de confianza

Finalmente, necesitamos un nivel de confianza. Si ha determinado que el escritor es mujer, su nivel de confianza es . Si ha determinado que el escritor es hombre, el nivel de confianza es .2*ΣF/(ΣFM)-12*ΣM/(ΣFM)-1

Entrada

La entrada es un texto en inglés que incluye puntuación. Todas las palabras están separadas por espacios (no tiene que preocuparse por nuevas líneas o espacios adicionales). Algunas palabras tienen caracteres que no son letras, que debes ignorar (como "Eres"). Si encuentra una palabra que no contiene letras (como "5" o "!!!") simplemente ignórela. Cada entrada contendrá al menos una palabra utilizable.

Salida

Debe generar una M o una F según el género que crea que es el escritor, seguido de su nivel de confianza.

Ejemplos

  1. There's a snake in my boot.

    • Género + masculinidad / feminidad de cada palabra: [M1.0,F1.5,F.75,F.75,M2.0,F1.0]
    • Σ M = 3.0, Σ F = 4.0
    • CL: 2*4.0/(4.0+3.0)-1= .143
    • Salida: F .143
  2. Frankly, I don't give a ^$*.

    • [M2.4,F1.5,M1.2,F1.0,F1.5], Σ M = 3.6, Σ F = 4.0, CL: 2*4.0/(4.0+3.6)-1= .053, Salida:F .053
  3. I'm 50 dollars from my goal!

    • [F.75,M1.25,M1.2,M2.0,F1.0], Σ M = 4.45, Σ F = 1.75, CL: 2*4.45/(4.45+1.75)-1= .435, Salida:M .435

Referencias

  1. Porcentaje de vocales en palabras del diccionario de inglés (38.1%)
  2. Porcentaje de vocales en textos en inglés (38.15%)
geokavel
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Dennis

Respuestas:

5

Python 3 , 320 317 307 286 253 189 bytes

h=S=0
for v in input().split():V=sum(map(v.count,'aeiouAEIOU'));C=sum(x.isalpha()for x in v);H=V<.4*C;C-=V;K=[1.5*V/(C+1),C/(1.5*V+1)][H];h+=K*H;S+=K-K*H
print('FM'[h>S],2*max(S,h)/(S+h)-1)

Pruébalo en línea!

Sin golf :

def evaluateWord(s):
    V = len([*filter(lambda c: c in 'aeiou', s.lower())])
    C = len([*filter(lambda c: c in 'bcdfghjklmnpqrstvxzwy', s.lower())])
    isMasculine = V < 0.4*(V+C)
    return C/(1.5*V+1) if isMasculine else 1.5*V/(C+1), isMasculine


def evaluatePhrase(s):
    scores = []
    for word in s.split():
        scores.append(evaluateWord(word))
    masc = 0
    fem = 0
    for score in scores:
        if score[1]:
            masc += score[0]
        else:
            fem += score[0]
    return ('M', 2*masc/(fem+masc)-1) if masc > fem else ('F', 2*fem/(fem+masc)-1)


print(evaluatePhrase("There's a snake in my boot."))
wrymug
fuente
1
Puede guardar 4 bytes utilizando punto y coma y colocando todas las primeras funciones en una línea. Pruébalo en línea!
Camarada SparklePony
@ComradeSparklePony gracias!
wrymug
1
map(e,s.split())en lugar de[e(x)for x in s.split()]
Value Ink
1
Además, es mejor al return'FM'[h>S],2*max(S,h)/(S+h)-1final
Value Ink
1
Busqué una forma más eficiente de contar vocales / consonantes a través de sum(map(s.count,chars)), reduciendo su recuento a 253 bytes
Value Ink
4

Rubí , 154 + 1 = 155 bytes

Usa la -nbandera.

m=f=0
gsub(/\S+/){s=$&.gsub(/[^a-z]/i){}.upcase;k=s.size;v=s.count'AEIOU';v<k*0.4?m+=(k-v)/(1.5*v+1):f+=1.5*v/(k-v+1)}
puts m>f ??M:?F,2*[m,f].max/(m+f)-1

Pruébalo en línea!

Tinta de valor
fuente
4

Python 3 , 205 201 197 192 bytes

-Gracias a @Value Ink por 4 bytes: de lower()antemano
-Gracias a @Coty Johnathan Saxman por 9 bytes: Condición invertida .4*(v+c)>vy -~cpor (c+1)verificación de consonantes basada en cambio de bits en lugar de literal.

Python 3 , 192 bytes

M=F=0
for i in input().lower().split():
 v=sum(j in'aeiou'for j in i);c=sum(33021815<<98>>ord(k)&1for k in i)
 if.4*(v+c)>v:M+=c/(1.5*v+1)
 else:F-=1.5*v/~c
print('FM'[M>F],2*max(M,F)/(F+M)-1)

Pruébalo en línea!

officialaimm
fuente
1
for i in input().lower().split():para que solo necesite buscar 'aeiou'el recuento de vocales y cortar la lowerllamada en el recuento de consonantes.
Value Ink
1
En su 'else', el divisor (c + 1) se puede acortar a - ~ c, sin paréntesis, guardando un byte. Este negativo puede, a su vez, llevarse a su + =, convirtiéndolo en un - = y ahorrando un byte más. F- = 1.5 * v / ~ c
Coty Johnathan Saxman
1
Cambiar el orden de su desigualdad (en su declaración if) le ahorra un byte más porque puede eliminar el espacio. if.4 * (v + c)> v
Coty Johnathan Saxman
1
Esto es complicado, pero puede ahorrar 5 bytes cambiando su búsqueda de consonantes por una tabla de búsqueda binaria codificada. k in'bcdfghjklmnpqrstvxzwy'for k ... se convierte en 33021815 <<98>> ord (k) & 1for k ... [ tio.run/… ¡ Pruébelo en línea!]
Coty Johnathan Saxman
1

C (gcc) , 237 229 222 216 bytes

Chico, pensé que podría hacer esto en MUCHOS MENOS BYTES ...

v,c;float m,f;g(char*s){for(m=f=0;*s;v*1.0/(c+v)<.4?m+=c/(1.5*v+1):1?f+=1.5*v/(c+1):0,s+=*s!=0)for(v=c=0;*s&&*s^32;s++)isalpha(*s)?strchr("AaEeIiOoUu",*s)?++v:++c:0;printf("%c %.3f",m>f?77:70,(m>f?2*m:2*f)/(f+m)-1);}

Pruébalo en línea!

cleblanc
fuente
196 bytes
ceilingcat el
0

Lisp común, 404 bytes

(defun f(x &aux(a 0)c(f 0)m v u)(labels((w(x &aux(p(position #\  x)))(cons(#1=subseq x 0 p)(and p(w(#1#x(1+ p)))))))(dolist(e(w(coerce x'list)))(setf v(#2=count-if(lambda(x)(member x(coerce"aeiouAEIOU"'list)))e)u(#2#'alpha-char-p e)c(- u v)m(and(> c 0)(<(/ v c)4/6)))(and(> u 0)(if m(incf a(/ c(1+(* v 3/2))))(incf f(/ v 2/3(1+ c))))))(format t"~:[F~;M~] ~4f~%"(> a f)(-(/(* 2(if(> a f)a f))(+ a f))1))))

Buen viejo lisp verboso!

Pruébalo en línea!

Versión sin golf:

(defun f(x &aux (a 0) c (f 0) m v u)        ; parameter & auxiliary variables
  (labels ((w (x &aux (p (position #\  x))) ; recursive function to split input into words
              (cons (subseq x 0 p) (and p (w (subseq x (1+ p)))))))
    (dolist (e (w (coerce x 'list)))        ; for each word 
      (setf v (count-if (lambda (x) (member x(coerce"aeiouAEIOU"'list))) e) ; count vowels
            u (count-if 'alpha-char-p e)    ; count all alfabetic letters
            c (- u v)                       ; calculate consonants
            m (and (> c 0) (< (/ v c) 4/6))); is male or not?
      (and (> u 0)                          ; if non-empty word
           (if m
               (incf a (/ c (1+ (* v 3/2)))); increase masculinity
               (incf f (/ v 2/3 (1+ c)))))) ; increase femininity
    (format t "~:[F~;M~] ~4f"               ; print
              (> a f)                       ; “gender”
              (-(/ (* 2 (if (> a f)a f)) (+ a f)) 1))))  ; and confidence
Renzo
fuente