JS, 1719/1694
Teoría
Desafortunadamente, el conjunto de reglas que proporcione puede no ser una decisión acertada desde un punto de vista matemático. De hecho, usando un subconjunto más pequeño de reglas, puede encontrar una solución para cada número en el intervalo dado
excepto por
para lo cual no hay solución.
Conjunto de reglas reducido
Considere el siguiente subet de reglas:
- Utilice solo los operadores
plus
, minus
y times
.
- No necesita implementar múltiples ocurrencias de
plus
o minus
en sus expresiones.
- No necesita implementar ni
division
tampoco operator associativity
(ya que su conjunto de soluciones ya está cubierto por la primera regla).
La razón por la que esto funciona es que, como discutió anteriormente con @Qwix, permite respuestas aburridas , es decir, expresiones que terminan en la expresión regular
( times one)+$
. Si se permite esto, cada número en el intervalo dado tendrá una solución.
Cuando respondiste en uno de tus comentarios,
@ Qwix Sí; las respuestas aburridas son aceptables, aunque esa no funciona para 104, 105, 106, 107, 108, 109, 110 o 111. -
tenías toda la razón: esto no funciona cuando intentas construir tu expresión comenzando con los números mismos, es decir, one hundred four times one times one …
o con cualquier otro de esos números.
Sin embargo, si su expresión comienza con una expresión cuya evaluación es igual a uno de los números dados, no tiene suerte. Por ejemplo, nota que 17 + 87
es, en efecto 104
, por lo que podemos escribir 104
como:
104: seventeen plus eighty seven times one times one times one times one times one times one times one times one times one times one
Para ver que este subconjunto funciona, guarde este archivo como num.js
y asegúrese de que SpiderMonkey, un motor de JavaScript para líneas de comando, esté instalado en su sistema.
El algoritmo
- Definamos la propiedad
K
de los enteros positivos como el estado del número que tiene N
letras y tiene un valor de N
.
- Definamos más a fondo la propiedad
F
de una expresión como el estado de la conversión de palabras que es 8k
-más corta que su evaluación con k ∈ ℕ. F
significa "rellenable" y describe si podemos llenar o no la conversión de palabras de la expresión con expresiones de longitud 8 (es decir " times one"
) de modo que la expresión resultante pueda obtener la propiedad N
.
Luego procedemos de la siguiente manera:
- Convierta el número de entrada a palabras.
- Compruebe si el número de entrada tiene propiedad
K
.
- Si lo hace, devuelve las palabras (
4
lamentablemente, es el único número con esta propiedad).
- Si no es así, proceda.
- Para todas las expresiones de dos operandos (sumas, restas y multiplicaciones en este orden) que dan como resultado el número de entrada, verifique si su evaluación tiene propiedad
K
.
- Si es así, devuelve las palabras.
- Si no es así, verifique si la expresión de dos operandos tiene propiedad
N
.
- Si es así, complete la expresión con
" times one"
y verifique si la evaluación de la expresión resultante tiene propiedad K
.
- Si es así, devuelve las palabras.
- Si no es así, proceda
- Si no es así, proceda
- Ve a tomar un café
Práctica
num.js (para SpiderMonkey / líneas de comando)
function X(e,t){return e+": "+t}function P(e){var n,t;for(n=1;.5*e+(e%2===0?1:0)>n;++n){if(t=C.s(n)+" plus "+C.s(e-n),t.replace(/\s/g,"").length===e)return t;if(F(e,t)&&e>t.length)return G(e,t)}return!1}function M(e){var t,n;for(t=L;t>1;--t){if(0>t-e)return!1;if(n=C.s(t)+" minus "+C.s(t-e),n.replace(/\s/g,"").length===e)return n;if(F(e,n)&&e>n.length)return G(e,n)}return!1}function F(e,t){return(e-t.replace(/\s/g,"").length)%8===0}function G(r,t){var e,i=(r-t.replace(/\s/g,"").length)/8,n="";for(e=0;i>e;++e)n+=" times one";return t+n}function T(e){var t,n,r;if(F(e,C.s(e)))return G(e,C.s(e));for(t=1,n=1;t<Math.floor(Math.sqrt(e));++t){for(;e>tn;)++n;if(tn===e&&(r=C.s(t)+" times "+C.s(n),r.replace(/\s/g,"").length===e))return r}return!1}function Y(e){var n,r,t;return e===C.s(e).length?X(e,C.s(e)):(n=P(e))?X(e,n):(r=M(e))?X(e,r):(t=T(e),t?X(e,t):X(e,"impossible"))}var L=1e4,C=new function(){return this.o=["","one","two","three","four","five","six","seven","eight","nine"],this.t=["","","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"],this.T=["ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"],this.s=function(e){return e?this.m(e):"zero"},this.m=function(e){return e>=1e6?this.m(Math.floor(e/1e6))+" million"+(e%1e6!==0?" "+this.Z(e%1e6):""):this.Z(e)},this.Z=function(e){return e>=1e3?this.h(Math.floor(e/1e3))+" thousand"+(e%1e3!==0?" "+this.h(e%1e3):""):this.h(e)},this.h=function(e){return e>99?this.o[Math.floor(e/100)]+" hundred"+(e%100!==0?" "+this.U(e%100):""):this.U(e)},this.U=function(e){return 10>e?this.o[e]:e>=10&&20>e?this.T[e-10]:this.t[Math.floor(e/10)]+(e%10!==0?" "+this.o[e%10]:"")},this};print(Y(0|arguments[0]))
num.js (para navegadores)
El código dado desde arriba no puede funcionar para los navegadores debido a su último comando, que toma los argumentos de la línea de comando para hacer un buen comando del script dado.
Para ejecutar el código JavaScript directamente desde su navegador, seleccione esta parte del código anterior:
function X(e,t){return e+": "+t}function P(e){var n,t;for(n=1;.5*e+(e%2===0?1:0)>n;++n){if(t=C.s(n)+" plus "+C.s(e-n),t.replace(/\s/g,"").length===e)return t;if(F(e,t)&&e>t.length)return G(e,t)}return!1}function M(e){var t,n;for(t=L;t>1;--t){if(0>t-e)return!1;if(n=C.s(t)+" minus "+C.s(t-e),n.replace(/\s/g,"").length===e)return n;if(F(e,n)&&e>n.length)return G(e,n)}return!1}function F(e,t){return(e-t.replace(/\s/g,"").length)%8===0}function G(r,t){var e,i=(r-t.replace(/\s/g,"").length)/8,n="";for(e=0;i>e;++e)n+=" times one";return t+n}function T(e){var t,n,r;if(F(e,C.s(e)))return G(e,C.s(e));for(t=1,n=1;t<Math.floor(Math.sqrt(e));++t){for(;e>tn;)++n;if(tn===e&&(r=C.s(t)+" times "+C.s(n),r.replace(/\s/g,"").length===e))return r}return!1}function Y(e){var n,r,t;return e===C.s(e).length?X(e,C.s(e)):(n=P(e))?X(e,n):(r=M(e))?X(e,r):(t=T(e),t?X(e,t):X(e,"impossible"))}var L=1e4,C=new function(){return this.o=["","one","two","three","four","five","six","seven","eight","nine"],this.t=["","","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"],this.T=["ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen"],this.s=function(e){return e?this.m(e):"zero"},this.m=function(e){return e>=1e6?this.m(Math.floor(e/1e6))+" million"+(e%1e6!==0?" "+this.Z(e%1e6):""):this.Z(e)},this.Z=function(e){return e>=1e3?this.h(Math.floor(e/1e3))+" thousand"+(e%1e3!==0?" "+this.h(e%1e3):""):this.h(e)},this.h=function(e){return e>99?this.o[Math.floor(e/100)]+" hundred"+(e%100!==0?" "+this.U(e%100):""):this.U(e)},this.U=function(e){return 10>e?this.o[e]:e>=10&&20>e?this.T[e-10]:this.t[Math.floor(e/10)]+(e%10!==0?" "+this.o[e%10]:"")},this}
Ahora, péguelo en la consola JavaScript de su navegador, para que pueda producir los mismos resultados desde su navegador con, por ejemplo:
Y(1234);
Ejemplos (línea de comando)
chiru@chiru ~ $ js num.js 28
28: fourteen plus fourteen times one
chiru@chiru ~ $ js num.js 7
7: impossible
chiru@chiru ~ $ js num.js 42
42: nine thousand sixty minus nine thousand eighteen
Y para ver el truco con el que puede hacer que cada número funcione, solo eche un vistazo a la aburrida respuesta para js num.js 1337
:
1337: ten plus one thousand three hundred twenty seven times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one times one
Los códigos provistos generan soluciones válidas para el intervalo dado (y probablemente incluso arriba, solo tendría que aumentar el valor de la variable L
).
Estadísticas
Estaba interesado en "cuán aburridas " eran las expresiones (o: cuánto times one
se usaba la subcadena por expresión dentro de este algoritmo), ya que esta parte era responsable de encontrar una solución para cada número dentro del intervalo dado. Compruébalo por ti mismo:
x : enésima expresión (mín. 0, máx. 10.000)
y : número de ocurrencias de la subcadena "veces uno" dentro de la expresión (mín. 0, máx. 1245)
Conclusiones:
- Las expresiones tienden a volverse cada vez más aburridas de manera lineal.
- Más del 99% de las soluciones son aburridas.
So for 1234 we can do (massive expression) times zero plus one thousand two hundred thirty four.
Es posible que desee excluir cero. Depende de usted.