Expressão igual ao seu comprimento


14

Dado um número, encontre uma expressão em palavras iguais a esse número, com um comprimento desse número.

Assim, para uma entrada de 15, você pode produzir sixteen minus one, que possui quinze caracteres (sem contar espaços). Se existirem várias soluções, imprima o que quiser. Se não houver, imprimaimpossible

Utilize apenas os operadores plus, minus, times, e divided by. Os operadores são avaliados da esquerda para a direita.

Formate 1234 como one thousand two hundred thirty four. Observe a ausência de "e" e que não há traços ou vírgulas.

A entrada e todos os números usados ​​na saída devem ser números inteiros positivos menores que 10.000.

A entrada será fornecida como um argumento de linha de comando. Imprimir na saída padrão.

Exemplos

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

4
números inteiros não negativos? So for 1234 we can do (massive expression) times zero plus one thousand two hundred thirty four.Você pode excluir zero. Você decide.
Level River St

@steveverrill Bom ponto; Eu mudei para "números inteiros positivos".
Ypnypn

4
tããão ... one hundred three times one times one times one times one times one times one times one times one times one times one times oneé válido?
Qwix 14/08/19

@Qwix Sim; respostas chatas são aceitáveis, apesar de que um não funciona para 104, 105, 106, 107, 108, 109, 110, ou 111.
Ypnypn

Respostas:


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

Rende uma função no espaço de nomes global,, Sque aceita qualquer número inteiro não negativo e retorna a sequência necessária, ou "Invalid"se o número inteiro não puder ser representado dentro das especificações.

Parece que eu usei a mesma abordagem que o @optokopper, tendo feito a mesma observação que "plus six plus nine"é a menor string de preenchimento possível e que todos os números maiores que 27 podem ser expressos concatenando uma das 15 cadeias de base para cópias repetidas da almofada.

Dito isto, as tabelas de strings base que usamos diferem, e minha solução depende de ajustes de bits e do operador restante ( %). Também inclui "multiplied by"como uma operação possível. E, naturalmente, a mecânica de como as strings são construídas é completamente diferente devido à diferença entre C e Javascript.

Essa é a minha melhor tentativa, pelo menos. ;)

Agradecimentos especiais a @chiru, cuja discussão de quais números eram alcançáveis ​​ajudou a impedir a busca infrutífera.


22

JS, 1719/1694

Teoria

Infelizmente, o conjunto de regras que você fornece pode não ser uma decisão sábia do ponto de vista matemático. De fato, usando um subconjunto menor de regras, você pode encontrar uma solução para cada número no intervalo especificado

I = [1;  10000]

exceto por

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

para o qual não há solução.

Conjunto de regras reduzido

Considere o seguinte subconjunto de regras:

  • Use apenas os operadores plus, minuse times.
  • Você não precisa implementar várias ocorrências de plusou minusem suas expressões.
  • Você não precisa implementar nem divisionnem operator associativity(como o conjunto de soluções já está coberto pela primeira regra).

A razão pela qual isso funciona é que, conforme discutido anteriormente com o @Qwix, você permite respostas chatas , ou seja, expressões que terminam na expressão regular ( times one)+$. Permitindo isso, cada número no intervalo especificado terá uma solução.

Quando você respondeu em um de seus comentários,

@Qwix Sim; respostas chatas são aceitáveis, embora essa não funcione para 104, 105, 106, 107, 108, 109, 110 ou 111. -

você estava absolutamente certo: isso não funciona quando você está tentando criar sua expressão começando pelos próprios números, one hundred four times one times one …ou seja, ou qualquer outro desses números.

Se, no entanto, sua expressão começar com uma expressão cuja avaliação seja igual a um dos números fornecidos, você estará sem sorte. Por exemplo, observe que 17 + 87sim 104, para que possamos escrever 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 verificar se esse subconjunto funciona, salve esse arquivo num.jse verifique se o SpiderMonkey, um mecanismo JavaScript para linhas de comando, está instalado no seu sistema.

O algoritmo

  • Vamos definir a propriedade Kpara números inteiros positivos como o estado do número com Nletras e com um valor de N.
  • Vamos definir ainda mais a propriedade Fde uma expressão como o estado de sua conversão de palavras sendo - 8kvezes mais curto que sua avaliação com k ∈ ℕ. Fsignifica "preenchível" e descreve se podemos ou não preencher a conversão de palavras da expressão com expressões de comprimento 8 (ou seja " times one"), de modo que a expressão resultante possa obter a propriedade N.

Em seguida, procedemos da seguinte forma:

  • Converta o número de entrada em palavras.
  • Verifique se o número de entrada tem propriedade K.
    • Se isso acontecer, retorne as palavras ( 4é o único número com essa propriedade, infelizmente).
    • Caso contrário, prossiga.
  • Para todas as expressões de dois operandos (adições, subtrações e multiplicações nesta ordem) que resultam no número de entrada, verifique se a avaliação tem propriedade K.
    • Se isso acontecer, retorne as palavras.
    • Caso contrário, verifique se a expressão de dois operandos possui propriedade N.
      • Se houver, preencha a expressão " times one"e verifique se a avaliação da expressão resultante tem propriedade K.
        • Se isso acontecer, retorne as palavras
        • Caso contrário, continue
      • Caso contrário, continue
  • Vá tomar um café

Prática

num.js (para SpiderMonkey / linhas 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)

O código fornecido acima não funciona nos navegadores devido ao seu último comando, que captura os argumentos da linha de comando para criar um bom comando a partir do script fornecido.

Para executar o código JavaScript diretamente de dentro do seu navegador, selecione esta parte do código acima:

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}

Agora, cole-o no console JavaScript do seu navegador, para que você possa produzir os mesmos resultados no seu navegador com, por exemplo:

Y(1234);

Exemplos (linha 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

E para ver o truque com o qual você pode fazer cada número funcionar, basta dar uma olhada na resposta chata 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

Os códigos fornecidos geram soluções válidas para o intervalo especificado (e provavelmente até acima, você só precisa aumentar o valor da variável L).

Estatisticas

Eu estava interessado em "quão chatas " eram as expressões (ou: quanto a substring times onefoi usada por expressão nesse algoritmo), pois essa parte era responsável por encontrar uma solução para cada número dentro do intervalo especificado. Veja por si mesmos:

x : n-ésima expressão (mín. 0, máx. 10.000)

y : número de ocorrências de substring "vezes um" dentro da expressão (mín. 0, máx. 1245)

Gráfico

Conclusões:

  • As expressões tendem a ficar cada vez mais chatas de maneira linear.
  • Mais de 99% das soluções são chatas.

2
Existe uma solução para 4four
FUZxxl 15/08/14

@FUZxxl Eu nunca neguei isso. Caso esteja respondendo If it does, return the words (4 is the only number with this property, unfortunately), você pode ter entendido mal esta seção. Diz que 4é a única expressão sem operador que forma sua própria solução.
Chiru

@FUZxxl Oh, ok. Acabei de descobrir que, na seção inicial, eu disse que não há soluções em X = [0; 10] ∪ {12}, embora mais tarde eu diga que 4tem uma solução. Corrigi o intervalo, obrigado. :)
Chiru 16/08

6

C, 450 caracteres

Editar: removido zero

Editar: usando apenas pluseminus

Procurei a expressão mais curta que adiciona caracteres e mantém a condição verdadeira. Eu descobri que plus ten plus fivetem 15 anos e acrescenta 15 à string.

Eu preciso apenas de expressões para os 15 primeiros números que não são impossíveis, para expressar qualquer número possível. 12 é o maior número impossível; portanto, basta codificar números menores 28.

4 = quatro
11 = seis mais cinco
13 = oito mais cinco
14 = vinte menos seis
15 = vinte menos cinco
16 = dezoito menos dois
17 = catorze mais três
18 = vinte e dois menos quatro
20 = trinta e dois menos doze
21 = vinte mais dois menos um
22 = vinte mais quatro menos dois
23 = trinta menos oito mais um
24 = vinte mais oito menos quatro
25 = vinte mais oito menos três
27 = vinte e oito menos seis mais cinco

Podemos escrever todos os números> 27 como x * 15 + um dos números acima.

Golfe

#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 legível

#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
Não tenho muita certeza de como seu código funciona, mas como a pergunta afirma isso all numbers used in the output must be positive integers, você pode remover o #define Z "zero"código juntamente com instâncias de Z, pois nunca deve usá-lo?
Qwix 15/08

"mais doze" são 12 letras. Isso ajudaria a diminuir o seu código?
Isaacg

Eu torná-lo mais curto, espaços infelizmente não contagem, plus twelveé de apenas 10 letras
Optokopper

OK, eu li errado as regras.
Isaacg
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.