Expresión que es igual a su longitud.


14

Dado un número, encuentre una expresión en palabras que sea igual a ese número, con una longitud de ese número.

Por lo tanto, para una entrada de 15, puede salir sixteen minus one, que tiene quince caracteres (sin contar espacios). Si existen varias soluciones, imprima lo que desee. Si no existe ninguno, imprimaimpossible

Utilice sólo los operadores plus, minus, times, y divided by. Los operadores son evaluados de izquierda a derecha.

Formato 1234 como one thousand two hundred thirty four. Tenga en cuenta la ausencia de "y", y que no hay guiones ni comas.

La entrada y todos los números utilizados en la salida deben ser enteros positivos menores de 10,000.

La entrada se dará como un argumento de línea de comando. Imprima en salida estándar.

Ejemplos

1: impossible
4: four
7: impossible
13: eight plus five (you could also output "five plus eight")
18: one plus two times six (note that operators are evaluated from left to right)
25: one thousand divided by forty

44
enteros no negativos? 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.
Level River St el

@steveverrill Buen punto; Lo he cambiado a "enteros positivos".
Ypnypn

44
taaaan ... one hundred three times one times one times one times one times one times one times one times one times one times one times onees válido?
Qwix

@ Qwix Sí; las respuestas aburridas son aceptables, aunque esa no funciona para 104, 105, 106, 107, 108, 109, 110 o 111.
Ypnypn

Respuestas:


1

Javascript, 434 caracteres

function f(s){return s.replace(/[A-Z]/g,function(t){return{O:'one',T:'two',H:'three',F:'four',I:'five',S:'six',E:'seven',G:'eight',N:'nine',Z:'ten',P:' plus ',M:' minus ',U:' times ',X:'teen',A:'thir',B:'twenty'}[t]})}A='TPAX|GeenMT|EXUO|B FMS|F|GPSUT|ZPHPG|BPFMT|AXPFPS|BPGMF|EUOPGeen|NPT|B GMSPI|GPI|EPE'.split('|');O=26640;function S(n){return n<15&&!(O>>n&1)?'Invalid':f(A[v=n%15])+(new Array(~~(n/15)+(O>>v&1))).join(f('PSPN'))}

Produce una función en el espacio de nombres global S, que acepta cualquier número entero no negativo y devuelve la cadena requerida, o "Invalid"si el número entero no se puede representar dentro de las especificaciones.

Parece que he usado el mismo enfoque que @optokopper, habiendo hecho la misma observación que "plus six plus nine"es la cadena de relleno más corta posible, y que todos los números mayores que 27 se pueden expresar concatenando una de las 15 cadenas de base con copias repetidas de la almohadilla.

Habiendo dicho eso, las tablas de cadenas base que usamos difieren, y mi solución se basa en el giro de bits y el operador restante ( %). También incluye "multiplied by"como posible operación. Y, naturalmente, la mecánica de cómo se construyen las cadenas son completamente diferentes debido a la diferencia entre C y Javascript.

Ese es mi mejor intento, en cualquier caso. ;)

Un agradecimiento especial a @chiru, cuya discusión sobre qué números se podían lograr ayudó a evitar búsquedas infructuosas.


22

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

I = [1;  10000]

excepto por

X = [1;  3] ∪ [5;  10] ∪ {12}

para lo cual no hay solución.

Conjunto de reglas reducido

Considere el siguiente subet de reglas:

  • Utilice solo los operadores plus, minusy times.
  • No necesita implementar múltiples ocurrencias de pluso minusen sus expresiones.
  • No necesita implementar ni divisiontampoco 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 + 87es, en efecto 104, por lo que podemos escribir 104como:

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.jsy asegúrese de que SpiderMonkey, un motor de JavaScript para líneas de comando, esté instalado en su sistema.

El algoritmo

  • Definamos la propiedad Kde los enteros positivos como el estado del número que tiene Nletras y tiene un valor de N.
  • Definamos más a fondo la propiedad Fde una expresión como el estado de la conversión de palabras que es 8k-más corta que su evaluación con k ∈ ℕ. Fsignifica "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 ( 4lamentablemente, 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 onese 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)

Grafico

Conclusiones:

  • Las expresiones tienden a volverse cada vez más aburridas de manera lineal.
  • Más del 99% de las soluciones son aburridas.

2
Existe una solución para 4—four
FUZxxl

@FUZxxl Nunca lo negué. En caso de que esté respondiendo If it does, return the words (4 is the only number with this property, unfortunately), es posible que haya entendido mal esta sección. Dice que 4es la única expresión sin operador que forma su propia solución.
Chiru

@FUZxxl Oh, está bien. Acabo de ver que en la sección inicial, dije que no hay soluciones en X = [0; 10] ∪ {12}, aunque más tarde, digo que 4tiene una solución. Corregí el intervalo, gracias. :)
Chiru

6

C, 450 caracteres

Editar: eliminado zero

Editar: usando solo plusyminus

Busqué la expresión más corta que agregue caracteres y mantenga la condición verdadera. Encontré plus ten plus five15 largos y agrega 15 a la cadena.

Solo necesito expresiones para los primeros 15 números que no son imposibles, para expresar cualquier número posible. 12 es el número imposible más grande, por lo tanto, es suficiente para codificar números menores de 28.

4 = cuatro
11 = seis más cinco
13 = ocho más cinco
14 = veinte menos seis
15 = veinte menos cinco
16 = dieciocho menos dos
17 = catorce más tres
18 = veintidos menos cuatro
20 = treinta y dos menos doce
21 = veinte más dos menos uno
22 = veinte más cuatro menos dos
23 = treinta menos ocho más uno
24 = veinte más ocho menos cuatro
25 = veinte más ocho menos tres
27 = veintiocho menos seis más cinco

Podemos escribir cada número> 27 como x * 15 + uno de los números anteriores.

Golfed

#define P" plus "
#define M" minus "
#define U"four"
#define F"five"
#define E"eight"
#define W"twenty"
#define A"ten"P F P
*e[]={0,0,0,0,U,0,0,0,0,0,0,F P"six",0,E P F,W M"six",W M F,E"een"M"two",U"teen"P"three",W" two"M U,A U,"thirty two"M"twelve",W P"two"M"one",W M"two"P U,"thirty"P"one"M E,W P E M U,W M"three"P E,A F P"six",W" "E M"six"P F};main(n){n=atoi(1[(int*)1[&n]]);for(printf("%d: ",n);n>27;n-=15)printf(A);puts(e[n]?e[n]:"impossible");}

Código legible

#include <stdio.h>
#include <stdlib.h>

// add fifteen to string, both as value and as character count (without spaces)
const char *add_fifteen = "plus ten plus five";

// table with hardcoded expressions
// NOTE: we could calculate 19, 26, 28 and 29 from 4, 11, 13 and 14
// but we would need more logic, so we hardcode those 4 numbers too.
const char *expressions[30]={"impossible", "impossible", "impossible", "impossible",
    "four", "impossible", "impossible", "impossible", "impossible",
    "impossible", "impossible", "five plus six", "impossible",
    "eight plus five", "twenty minus six",
    "fourteen plus one", "eighteen minus two", "fourteen plus three",
    "twenty two minus four", "four plus ten plus five",
    "thirty two minus twelve", "nine plus seven plus five",
    "twenty plus four minus two", "twelve plus seven plus four",
    "twenty plus eight minus four", "twenty plus eight minus three",
    "five plus six plus ten plus five", "twenty eight minus six plus five",
    "eight plus five plus ten plus five", "seven plus seven plus ten plus five"};

int main(int argc,char *argv[])
{
    int n = strtol(argv[1], NULL, 0);
    int fifteens = 0;

    printf("%d: ", n);

    // how many times do we need to add fifteen?
    if(n>29){
        fifteens=(n/15) - 1;
        n -= fifteens*15; // ensure 30 > n >= 15, so we don't get "impossible"
    }

    // look up the expression for n
    printf("%s", expressions[n]);

    // add fifteens till we are done
    while(fifteens-- > 0) {
        printf(" %s", add_fifteen);
    }

    printf("\n");
    return 0;
}

2
No estoy muy seguro de cómo funciona su código, pero dado que la pregunta establece que all numbers used in the output must be positive integers, ¿podría eliminarlo #define Z "zero"de su código junto con instancias de Z ya que nunca debería usarlo?
Qwix

"más doce" son 12 letras. ¿Eso ayudaría a acortar tu código?
isaacg

Lo haría más corto, por desgracia, los espacios no cuentan, plus twelveson solo 10 letras
Optokopper

OK, leí mal las reglas.
isaacg
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.