Aproximar quando você vai morrer
Uma tábua de mortalidade ou tábua de vida é uma ferramenta atuarial que dá a probabilidade de que uma pessoa envelhece \$A\$anos morrerão no próximo ano e é usado para ajudar a calcular os prêmios de seguro de vida, entre outras coisas. Uma das primeiras pessoas a compilar uma tábua de vida foi Edmond Halley , de fama cometária. Essas probabilidades também permitem estimar a expectativa de vida para uma determinada idade, que é o objetivo deste desafio.
Entrada
- Um número inteiro de 0 a 119, inclusive.
- Um indicador para Sexo M / F.
Resultado
- Uma aproximação para a esperança de vida para essa Idade / Sexo de acordo com a Tabela de Mortalidade de 2016 da Administração da Segurança Social , também conhecida como tabela de Vida Atuarial, cuja parte relevante pode ser encontrada abaixo.
Age M F
0 75.97 80.96
1 75.45 80.39
2 74.48 79.42
3 73.50 78.43
4 72.52 77.45
5 71.53 76.46
6 70.54 75.47
7 69.55 74.47
8 68.56 73.48
9 67.57 72.49
10 66.57 71.50
11 65.58 70.50
12 64.59 69.51
13 63.60 68.52
14 62.61 67.53
15 61.63 66.54
16 60.66 65.55
17 59.70 64.57
18 58.74 63.59
19 57.79 62.61
20 56.85 61.63
21 55.91 60.66
22 54.98 59.69
23 54.06 58.72
24 53.14 57.75
25 52.22 56.78
26 51.31 55.82
27 50.39 54.85
28 49.48 53.89
29 48.56 52.93
30 47.65 51.97
31 46.74 51.01
32 45.83 50.06
33 44.92 49.10
34 44.01 48.15
35 43.10 47.20
36 42.19 46.25
37 41.28 45.30
38 40.37 44.36
39 39.47 43.41
40 38.56 42.47
41 37.65 41.53
42 36.75 40.59
43 35.85 39.66
44 34.95 38.73
45 34.06 37.80
46 33.17 36.88
47 32.28 35.96
48 31.41 35.04
49 30.54 34.13
50 29.67 33.23
51 28.82 32.33
52 27.98 31.44
53 27.14 30.55
54 26.32 29.68
55 25.50 28.81
56 24.70 27.94
57 23.90 27.09
58 23.12 26.24
59 22.34 25.39
60 21.58 24.56
61 20.83 23.72
62 20.08 22.90
63 19.35 22.07
64 18.62 21.26
65 17.89 20.45
66 17.18 19.65
67 16.47 18.86
68 15.77 18.07
69 15.07 17.30
70 14.39 16.54
71 13.71 15.79
72 13.05 15.05
73 12.40 14.32
74 11.76 13.61
75 11.14 12.92
76 10.53 12.23
77 9.94 11.57
78 9.37 10.92
79 8.82 10.29
80 8.28 9.68
81 7.76 9.09
82 7.26 8.52
83 6.79 7.98
84 6.33 7.45
85 5.89 6.95
86 5.48 6.47
87 5.08 6.01
88 4.71 5.57
89 4.37 5.16
90 4.05 4.78
91 3.75 4.43
92 3.48 4.11
93 3.23 3.81
94 3.01 3.55
95 2.81 3.31
96 2.64 3.09
97 2.49 2.90
98 2.36 2.73
99 2.24 2.58
100 2.12 2.42
101 2.01 2.28
102 1.90 2.14
103 1.80 2.01
104 1.70 1.88
105 1.60 1.76
106 1.51 1.65
107 1.42 1.54
108 1.34 1.44
109 1.26 1.34
110 1.18 1.24
111 1.10 1.15
112 1.03 1.06
113 0.96 0.98
114 0.90 0.91
115 0.84 0.84
116 0.78 0.78
117 0.72 0.72
118 0.66 0.66
119 0.61 0.61
Por conveniência, aqui estão eles em formato amplo (idades de 0-119 na ordem):
M: [75.97, 75.45, 74.48, 73.5, 72.52, 71.53, 70.54, 69.55, 68.56, 67.57, 66.57, 65.58, 64.59, 63.6, 62.61, 61.63, 60.66, 59.7, 58.74, 57.79, 56.85, 55.91, 54.98, 54.06, 53.14, 52.22, 51.31, 50.39, 49.48, 48.56, 47.65, 46.74, 45.83, 44.92, 44.01, 43.1, 42.19, 41.28, 40.37, 39.47, 38.56, 37.65, 36.75, 35.85, 34.95, 34.06, 33.17, 32.28, 31.41, 30.54, 29.67, 28.82, 27.98, 27.14, 26.32, 25.5, 24.7, 23.9, 23.12, 22.34, 21.58, 20.83, 20.08, 19.35, 18.62, 17.89, 17.18, 16.47, 15.77, 15.07, 14.39, 13.71, 13.05, 12.4, 11.76, 11.14, 10.53, 9.94, 9.37, 8.82, 8.28, 7.76, 7.26, 6.79, 6.33, 5.89, 5.48, 5.08, 4.71, 4.37, 4.05, 3.75, 3.48, 3.23, 3.01, 2.81, 2.64, 2.49, 2.36, 2.24, 2.12, 2.01, 1.9, 1.8, 1.7, 1.6, 1.51, 1.42, 1.34, 1.26, 1.18, 1.1, 1.03, 0.96, 0.9, 0.84, 0.78, 0.72, 0.66, 0.61]
F: [80.96, 80.39, 79.42, 78.43, 77.45, 76.46, 75.47, 74.47, 73.48, 72.49, 71.5, 70.5, 69.51, 68.52, 67.53, 66.54, 65.55, 64.57, 63.59, 62.61, 61.63, 60.66, 59.69, 58.72, 57.75, 56.78, 55.82, 54.85, 53.89, 52.93, 51.97, 51.01, 50.06, 49.1, 48.15, 47.2, 46.25, 45.3, 44.36, 43.41, 42.47, 41.53, 40.59, 39.66, 38.73, 37.8, 36.88, 35.96, 35.04, 34.13, 33.23, 32.33, 31.44, 30.55, 29.68, 28.81, 27.94, 27.09, 26.24, 25.39, 24.56, 23.72, 22.9, 22.07, 21.26, 20.45, 19.65, 18.86, 18.07, 17.3, 16.54, 15.79, 15.05, 14.32, 13.61, 12.92, 12.23, 11.57, 10.92, 10.29, 9.68, 9.09, 8.52, 7.98, 7.45, 6.95, 6.47, 6.01, 5.57, 5.16, 4.78, 4.43, 4.11, 3.81, 3.55, 3.31, 3.09, 2.9, 2.73, 2.58, 2.42, 2.28, 2.14, 2.01, 1.88, 1.76, 1.65, 1.54, 1.44, 1.34, 1.24, 1.15, 1.06, 0.98, 0.91, 0.84, 0.78, 0.72, 0.66, 0.61]
Regras de pontuação
Para este desafio, a finalização com a menor pontuação vence . Sua pontuação será igual a \$(1+L)\times(1 + M)\$, onde \$L\$é o comprimento do seu código em bytes e \$M\$é o erro quadrático médio de suas estimativas, arredondado para duas casas decimais. Este é um programa de pontuação para \$M\$.
Outras regras
- As lacunas padrão são proibidas.
- A entrada é bastante flexível. Você pode especificar quaisquer dois valores distintos para M / F:
'M'/'F',0/1. Se você realmente quiser, pode até pegar um único inteiro, com o sinal representando M / F, mas observe que0é uma entrada para ambos. Ou as partes reais e imaginárias de um número complexo.- Você não precisa dar nenhuma entrada se não quiser, o que deve permitir que você publique respostas que sempre retornam 4 ou qualquer outra coisa.
- Caso haja alguma confusão, a saída não pode ser aleatória.
- Inclua um meio de verificar sua pontuação.
- Construções que têm essa tábua de mortalidade exata não são proibidas, mas implemente sua própria solução também.
- Explicações são encorajadas.
Bônus Adicionais:
Uma vez que R é o idioma do mês em setembro de 2020 , estarei concedendo uma recompensa de 500 representantes para a resposta R com a melhor pontuação no final do mês.
Respostas
JavaScript (ES6), pontuação: 59,51 59,10
L = 52 bytes, M ≈ 0,1150638
Espera (n)(m), onde m é 1 para Masculino ou 0 para Feminino.
n=>m=>81-5*m-(.9+m/51+(70-27*m-(.92-m/7)*n)/2e4*n)*n
Experimente online!
ou Obtenha os dados brutos no formato esperado pelo programa de pontuação .
Método
Isso se baseia em duas regressões cúbicas, com uma compensação entre o tamanho do código e a precisão.
Para mulheres, isso calcula:
$$f_0(x)=81-\frac{9}{10}x-\frac{7}{2000}x^2+\frac{23}{500000}x^3$$
E para os homens:
$$f_1(x)=76-\frac{469}{510}x-\frac{43}{20000}x^2+\frac{17}{437500}x^3$$
Quão preciso é isso?
Abaixo segue um gráfico dos erros produzidos pela função de acordo com a idade e o sexo.
R , pontuação = 67,47 47,92
30 bytes, MSE = 0,54587
-1 byte (e -1,47 na pontuação) graças a Dominic van Essen.
pnorm(scan(),31,41,F)*scan()-2
Experimente online!
O formato de entrada é: idade como um inteiro, depois uma nova linha, depois sexo e depois uma nova linha. Sexo é codificado como 98 para homens e 106 para mulheres.
Aproxima as tabelas atuariais pela função de sobrevivência de uma distribuição normal (a função de sobrevivência é 1 - a função de distribuições cumulativas). Tentei algumas famílias de distribuição, e o normal minimizou o MSE.
Vamos \$\phi(x;\mu,\sigma)\$seja a densidade de um \$\mathcal N(\mu,\sigma^2)\$distribuição. A aproximação usada é
\$f(x)=a+m\int_x^\infty\phi(t;\mu,\sigma)\,dt\$
Tentei usar valores de parâmetros diferentes para homens e mulheres, mas a melhor pontuação é obtida usando os mesmos valores de \$a\$, \$\mu\$e \$\sigma\$, e escolhendo apenas valores diferentes para \$m\$. Desde \$m=98\$para homens e \$m=106\$ para as mulheres são os valores ideais, eu os uso para codificar o sexo diretamente.
(Na verdade, os valores ideais seriam \$m=98.25528\$para homens e \$m=106.34315\$para as mulheres, mas usar esses valores para definir os sexos realmente parece trapaça. Isso levaria a uma pontuação de 47,49, uma ligeira melhora.)
Trama da aproximação para homens:
Gráfico de aproximação para mulheres:
Wolfram Language (Mathematica) , Pontuação 151.8,
32 bytes, 3,6 MSE
#-Cos[x(Pi-.02)/238]~Sum~{x,#2}&
Experimente online!
Percebi que as diferenças dos valores eram semelhantes a Cos(x) [0,pi/2]
Então, Cos (x) acumulado funciona muito bem em homens ...
MACHO
MSE 0,90
MSE FEMININO 6,29
( acho que Cos (x) entende melhor os homens ... )
Agradecimentos especiais a @att por reduzir meu código para 33 bytes
Ruby , pontuação 56,12 ... 43,94 43,92
\$L=35\$, \$M\approx0.220060\$
->x,f{f.*1.87e6-(21676+(66-x)*x)*x}
Experimente online!
A entrada é uma idade \$x\$e um flutuador \$f\$, que é 4.027e-5para homens e 4.362e-5mulheres. (Veja abaixo uma versão alternativa que leva \$f\$como um número inteiro.) A abordagem é ajustar um polinômio cúbico à média de expectativa de vida de ambos os sexos e, em seguida, dimensionar esse polinômio por um fator de sexo para recuperar aproximações específicas do sexo. O polinômio selecionado para a esperança média de vida é$$ \frac{x^3-66x^2-21676x+1870000}{23840} $$ e o fator sexo é $$ \begin{cases}0.96,\;\text{male}\\1.04,\;\text{female}.\end{cases} $$Em outras palavras, a expectativa de vida de um homem é de aproximadamente \$0.96\$vezes a de um ser humano médio (homem ou mulher). Da mesma forma, a expectativa de vida de uma mulher é de aproximadamente \$1.04\$ vezes o de um ser humano médio.
O gráfico abaixo mostra o erro quadrático em função da idade para cada sexo. A linha cinza tracejada representa o erro quadrático médio para ambos os sexos.
Um ponto de interesse no código é a chamada explícita ao *método do float f. Tudo à direita de f.*é interpretado como o argumento do método, portanto, o polinômio não precisa ser colocado entre parênteses .
Ruby , pontuação 50,06
\$L=40\$, \$M\approx0.220981\$
->x,f{f/9e3*(56541-(656+(2-x/33r)*x)*x)}
Experimente online!
Apesar de estar dentro das regras, levando \$f\$como um flutuador (como acima) parece mais do que um pouco 'barato'. Esta versão usa a mesma abordagem geral, mas aqui \$f\$é um inteiro: \$12\$para homens e \$13\$para mulheres. O polinômio usado para a expectativa de vida média é$$ \frac{x^3/33-2x^2-656x+56541}{720}. $$
J , pontuação 53,76 52,78
L = 46, M = 0.122983
Assume M / F como 1/0 no lado direito e envelhece no lado esquerdo. Uma aproximação polinomial de terceiro grau simples. Os polinômios J são lidos da esquerda para a direita, portanto, 81 - 0.9x - 347e-5x² + 455e-7x³para o caso 1. O caso 0 apenas modifica os números um pouco para 76 - 0.92x - 207e-5x² + 385e-7x³. p.avalia o polinômio em x, neste caso a idade.
p.~81 _0.9 _347e_5 455e_7-5 0.02 _14e_4 7e_6&*
Experimente online!
Python 3 , pontuação 94,40, 58 bytes, 0,60 MSE
Apenas aproximações lineares simples. Truepara mulheres e Falsepara macho .
lambda a,g:[75+5*g-(.89+g/30)*a,12-a/11][a>81]+(70<a<90)*2
Experimente online!
Representação visual da aproximação:
R , pontuação 46.00036
Empurrando os limites de 'quaisquer dois valores distintos' como entrada mais do que um pouco ...
45 bytes, erro quadrático médio 7,9e-6
function(a,s)s%/%gmp::as.bigz(1e4)^a%%1e4/100
Experimente online!
A entrada é um número inteiro acomo idade e um dos dois valores de 'número inteiro grande' spara especificar o sexo M / F.
A produção é um número 'grande e racional'.
Como (presumivelmente) encorajado pelas regras de entrada generosamente flexíveis, os valores que especificam o sexo são integrais para o cálculo (embora neste caso provavelmente mais do que o pretendido ...).
Cada um dos grandes inteiros M, F são construídos como o 1 ... 120º poder de 1e4 multiplicado por 100x a expectativa de vida em cada idade: essencialmente, uma codificação de base 10000. A life_expectancyfunção simplesmente decodifica o aº dígito de base 10000 e divide por 100.
Embora a função use a gmpbiblioteca de precisão arbitrária para cálculos, um pequeno número dos valores decodificados ainda contém imprecisões na 2ª casa decimal, por motivos que não entendo.
No entanto, o erro médio quadrático é (como esperado) suficientemente próximo de zero que isso não importa, já que precisamos adicionar 1 a ele de qualquer maneira para obter a pontuação.
R , pontuação 75,74445
61 bytes, erro quadrático médio 0,222
function(a,s)s*predict(loess(c(82,58,35,14,3,1)~c(0:5*24)),a)
Experimente online!
Usa suavização de loess para interpolar entre pontos de dados embutidos em código.
As curvas M e F são notavelmente semelhantes entre si após o dimensionamento (por 0,92x) - veja os pontos pretos e cinza no gráfico - então os pontos codificados são retirados da média das duas curvas (em escala) e, em seguida, arredondado para valores agradáveis e curtos. A linha vermelha no gráfico mostra os valores interpolados.
Infelizmente (para mim), o sistema de pontuação de adicionar 1 ao erro quadrático médio recompensa fortemente ajustes razoavelmente próximos, mas não oferece muito mais recompensa por um ajuste muito próximo, então o comprimento de código extra aqui significa que a pontuação geral ainda é pior do que o ajuste mais flexível de Robin Ryder para uma distribuição normal.
Wolfram Language (Mathematica) , pontuação 34,16
27 bytes, erro quadrático médio 0,21676 (arredondado para 0,22)
#3(#2-#+Sqrt[(#2-#)^2+#4])&
Experimente online!
Uma função sem nome (que chamaremos fpara fins de discussão) que leva dois argumentos (nesta ordem), a idade (um número inteiro de 0 a 119) e os indicadores para feminino ou masculino nesta forma:
- indicador para "feminino":
Sequence[83.506,0.4794,222.8] - indicador para "masculino":
Sequence[80.596,0.4636,248.5]
No Mathematica, f[a,Sequence[b,c,d]]é o mesmo que f[a,b,c,d]; portanto, Sequence[b,c,d]é quase exatamente um triplo ordenado, exceto que é melhor para se conectar a funções.
O código acima implementa a função matemática
\$ f(a,b,c,d) = c\big( b-a + \sqrt{(b-a)^2+d} \big), \$
onde \$a\$é a idade e \$b,c,d\$ são parâmetros numéricos usados para otimizar o ajuste com os dados.
Esta forma específica foi motivada pela minha percepção de que os gráficos dos dados para cada sexo pareciam uma hipérbole com uma assíntota inclinada à esquerda e uma assíntota horizontal à direita, que pode ser trazida para a forma paramétrica acima (aqui \$(b,0)\$são as coordenadas do centro da hipérbole, \$2c\$é a inclinação da assíntota inclinada, e \$d\$controla a que distância do centro a hipérbole se curva). Um algoritmo evolutivo foi então usado para ajustar os parâmetros para cada sexo separadamente; experimentos sugerem que há um único mínimo local para cada conjunto de dados, pois todas as tentativas convergiram para valores muito semelhantes para \$b,c,d\$.
(Tecnicamente, toda a função poderia ter sido usada como indicador de sexo, levando à solução de 4 bytes #2@#com pontuação 6.1 . Mas muitos dos envios poderiam ter feito coisas semelhantes.)