O escritor é homem ou mulher?

8

Um problema em um site como esse é que muitas vezes você não sabe se está falando com um homem ou uma mulher. No entanto, você criou uma técnica simples de PNL que pode ser usada para determinar o sexo do escritor de um pedaço de texto.

Teoria

Aproximadamente 38,1% das letras usadas em inglês são vogais [a, e, i, o, u] (consulte as referências abaixo, yNÃO é uma vogal neste caso). Portanto, definiremos qualquer palavra que tenha pelo menos 40% de vogais como uma palavra feminina e qualquer palavra que tenha menos de 40% de vogais como uma palavra masculina .

Além dessa definição, também podemos encontrar a masculinidade ou feminilidade de uma palavra. Seja C o número de consoantes na palavra e V o número de vogais:

  • Se uma palavra é feminina, é feminilidade 1.5*V/(C+1).
  • Se uma palavra é masculina, é masculinidade C/(1.5*V+1).

Por exemplo, a palavra catché masculina. Sua masculinidade é 4/(1.5*1+1) = 1.6. A palavra phoneé feminina. Sua feminilidade é 1.5*2/(3+1) = .75.

Algoritmo

Para descobrir o gênero do escritor de um pedaço de texto, tomamos a soma da masculinidade de todas as palavras masculinas (Σ M ) e a soma da feminilidade de todas as palavras femininas (Σ F ). Se Σ M > Σ F , determinamos que o escritor é um homem. Caso contrário, determinamos que o escritor é uma mulher.

Nível de confiança

Finalmente, precisamos de um nível de confiança. Se você determinou que o escritor é do sexo feminino, seu nível de confiança é . Se você determinou que o escritor é homem, o nível de confiança é .2*ΣF/(ΣFM)-12*ΣM/(ΣFM)-1

Entrada

Entrada é um pedaço de texto em inglês, incluindo pontuação. As palavras são todas separadas por espaços (você não precisa se preocupar com novas linhas ou espaços extras). Algumas palavras têm caracteres que não são da letra, que você precisa ignorar (como "Você é"). Se você encontrar uma palavra que não seja letras (como "5" ou "!!!"), ignore-a. Cada entrada conterá pelo menos uma palavra utilizável.

Resultado

Você precisa gerar um M ou F, dependendo do sexo que você acha que o escritor é, seguido pelo seu nível de confiança.

Exemplos

  1. There's a snake in my boot.

    • Gênero + masculinidade / feminilidade de cada palavra: [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= 0,143
    • Resultado: 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, Saída: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, Saída:M .435

Referências

  1. Porcentagem de vogais nas palavras do dicionário em inglês (38,1%)
  2. Percentual de vogais em textos em inglês (38,15%)
geokavel
fonte
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Dennis

Respostas:

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)

Experimente online!

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
fonte
1
Você pode salvar 4 bytes usando ponto e vírgula e colocando toda a primeira função em uma linha. Experimente online!
Camarada SparklePony
@ComradeSparklePony thanks!
wrymug
1
map(e,s.split())em vez de[e(x)for x in s.split()]
Value Ink
1
Além disso, é melhor return'FM'[h>S],2*max(S,h)/(S+h)-1no final
Value Ink
1
Olhei para cima uma forma mais eficiente para contar vogais / consoantes via sum(map(s.count,chars)), deixando cair sua contagem para 253 bytes
valor da tinta
4

Ruby , 154 + 1 = 155 bytes

Usa a -nbandeira.

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

Experimente online!

Value Ink
fonte
4

Python 3 , 205 201 197 192 bytes

-Obrigado, @Value Ink por 4 bytes: lower()antes
-Obrigado @Coty Johnathan Saxman por 9 bytes: condição invertida .4*(v+c)>ve verificação de consoante baseada -~cem (c+1)shift de bits em vez 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)

Experimente online!

officialaimm
fonte
1
for i in input().lower().split():para que você só precise procurar 'aeiou'a contagem de vogais e cortar a lowerchamada na contagem de consoantes.
Value Ink
1
No seu 'else', o divisor (c + 1) pode ser reduzido para - ~ c, sem parênteses, salvando um byte. Esse negativo pode, por sua vez, ser carregado para o seu + =, tornando-o - = e economizando mais um byte. F- = 1,5 * v / ~ c #
Coty Johnathan Saxman
1
Mudar a ordem da sua desigualdade (na instrução if) economiza mais um byte, pois você pode excluir o espaço. if.4 * (v + c)> v
Coty Johnathan Saxman
1
Essa é uma tarefa complicada, mas você pode salvar 5 bytes alternando sua pesquisa consoante para uma tabela de pesquisa binária codificada. k in'bcdfghjklmnpqrstvxzwy'for k ... torna-se 33021815 <<98>> ord (k) & 1for k ... [ tio.run/… Experimente on-line!]
Coty Johnathan Saxman
1

C (GCC) , 237 229 222 216 bytes

Garoto, embora eu pudesse fazer isso em MUITOS 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);}

Experimente online!

cleblanc
fonte
196 bytes
tetocat,
0

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

Bom e velho verboso verboso!

Experimente online!

Versão não destruída:

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