Ist der Schriftsteller ein Mann oder eine Frau?

8

Ein Problem auf einer solchen Website ist, dass Sie oft nicht wissen, ob Sie mit einem Mann oder einer Frau sprechen. Sie haben jedoch eine einfache NLP-Technik entwickelt, mit der Sie das Geschlecht des Verfassers eines Textes bestimmen können.

Theorie

Ungefähr 38,1% der im Englischen verwendeten Buchstaben sind Vokale [a, e, i, o, u] (siehe Referenzen unten, yist in diesem Fall KEIN Vokal). Daher definieren wir jedes Wort, das mindestens 40% Vokale enthält, als weibliches Wort und jedes Wort, das weniger als 40% Vokale enthält, als männliches Wort .

Über diese Definition hinaus können wir auch die Männlichkeit oder Weiblichkeit eines Wortes finden. Sei C die Anzahl der Konsonanten im Wort und V die Anzahl der Vokale:

  • Wenn ein Wort weiblich ist, ist es weiblich 1.5*V/(C+1).
  • Wenn ein Wort männlich ist, ist es Männlichkeit C/(1.5*V+1).

Zum Beispiel ist das Wort catchmännlich. Seine Männlichkeit ist 4/(1.5*1+1) = 1.6. Das Wort phoneist weiblich. Seine Weiblichkeit ist 1.5*2/(3+1) = .75.

Algorithmus

Um das Geschlecht des Verfassers eines Textes herauszufinden, nehmen wir die Summe der Männlichkeit aller männlichen Wörter (Σ M ) und die Summe der Weiblichkeit aller weiblichen Wörter (Σ F ). Wenn Σ M > Σ F ist , haben wir festgestellt, dass der Schreiber ein Mann ist. Ansonsten haben wir festgestellt, dass der Schriftsteller eine Frau ist.

Vertrauensniveau

Schließlich brauchen wir ein Vertrauensniveau. Wenn Sie festgestellt haben, dass der Autor weiblich ist, ist Ihr Selbstvertrauen . Wenn Sie festgestellt haben, dass der Autor männlich ist, ist das Konfidenzniveau .2*ΣF/(ΣFM)-12*ΣM/(ΣFM)-1

Eingang

Die Eingabe ist ein englischer Text einschließlich Interpunktion. Alle Wörter sind durch Leerzeichen getrennt (Sie müssen sich keine Gedanken über neue Zeilen oder zusätzliche Leerzeichen machen). Einige Wörter enthalten Nicht-Buchstaben-Zeichen, die Sie ignorieren müssen (z. B. "Du bist"). Wenn Sie auf ein Wort stoßen, das keine Buchstaben enthält (wie "5" oder "!!!"), ignorieren Sie es einfach. Jede Eingabe enthält mindestens ein verwendbares Wort.

Ausgabe

Sie müssen ein M oder F ausgeben, je nachdem, welches Geschlecht der Autor Ihrer Meinung nach ist, gefolgt von Ihrem Vertrauensniveau.

Beispiele

  1. There's a snake in my boot.

    • Geschlecht + Männlichkeit / Weiblichkeit jedes Wortes: [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
    • Ausgabe: 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= 0,053, Ausgabe: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= 0,435, Ausgabe:M .435

Verweise

  1. Prozentsatz der Vokale in englischen Wörterbuchwörtern (38,1%)
  2. Prozentsatz der Vokale in englischen Texten (38,15%)
Geokavel
quelle
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Dennis

Antworten:

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)

Probieren Sie es online aus!

Ungolfed :

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
quelle
1
Sie können 4 Bytes speichern, indem Sie Semikolons verwenden und alle ersten Funktionen in eine Zeile setzen. Probieren Sie es online aus!
Genosse SparklePony
@ ComradeSparklePony danke!
Wrymug
1
map(e,s.split())anstelle von[e(x)for x in s.split()]
Value Ink
1
Außerdem ist es besser, return'FM'[h>S],2*max(S,h)/(S+h)-1am Ende
Value Ink
1
Ich habe nach einer effizienteren Methode gesucht, um Vokale / Konsonanten zu zählen sum(map(s.count,chars)), indem ich Ihre Anzahl auf 253 Bytes gesenkt habe
Value Ink
4

Ruby , 154 + 1 = 155 Bytes

Verwendet die -nFlagge.

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

Probieren Sie es online aus!

Wert Tinte
quelle
4

Python 3 , 205 201 197 192 Bytes

- Danke @Wert Tinte für 4 Bytes: lower()vorher -
Danke @Coty Johnathan Saxman für 9 Bytes: Invertierter Zustand .4*(v+c)>vund -~cfür eine auf (c+1)Bitverschiebungen basierende Konsonantenprüfung anstelle von 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)

Probieren Sie es online aus!

Officialaimm
quelle
1
for i in input().lower().split():so dass Sie nur nach 'aeiou'der Vokalzahl suchen und den lowerAnruf in der Konsonantenzahl abschneiden müssen .
Wert Tinte
1
In Ihrem 'else' kann der Divisor (c + 1) ohne Klammern auf - ~ c gekürzt werden, wodurch ein Byte gespeichert wird. Dieses Negativ kann dann wiederum auf Ihr + = übertragen werden, wodurch es zu einem - = wird und ein weiteres Byte gespeichert wird. F- = 1,5 * v / ~ c
Coty Johnathan Saxman
1
Durch Ändern der Reihenfolge Ihrer Ungleichung (in Ihrer if-Anweisung) sparen Sie ein weiteres Byte, da Sie das Leerzeichen löschen können. if.4 * (v + c)> v
Coty Johnathan Saxman
1
Dies ist schwierig, aber Sie können 5 Bytes sparen, indem Sie Ihre Konsonantensuche gegen eine fest codierte binäre Nachschlagetabelle austauschen. k in'bcdfghjklmnpqrstvxzwy'for k ... wird 33021815 << 98 >> ord (k) & 1for k ... [ tio.run/… Versuchen Sie es online!]
Coty Johnathan Saxman
1

C (gcc) , 237 229 222 216 Bytes

Junge, ich dachte, ich könnte das in VIELEN WENIGEREN BYTES tun ...

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);}

Probieren Sie es online aus!

Cleblanc
quelle
196 Bytes
Deckenkatze
0

Common Lisp, 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))))

Gutes altes wortreiches Lispeln!

Probieren Sie es online aus!

Ungolfed Version:

(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
quelle