Espressione uguale alla sua lunghezza


14

Dato un numero, trova un'espressione in parole uguale a quel numero, con una lunghezza di quel numero.

Quindi, a un input di 15, potresti output sixteen minus one, che ha quindici caratteri (senza contare gli spazi). Se esistono più soluzioni, stampa quello che vuoi. Se non esiste, stampaimpossible

Utilizzare solo gli operatori plus, minus, times, e divided by. Gli operatori vengono valutati da sinistra a destra.

Formato 1234 come one thousand two hundred thirty four. Notare l'assenza di "e" e che non ci sono trattini o virgole.

L'input e tutti i numeri utilizzati nell'output devono essere numeri interi positivi inferiori a 10.000.

L'input verrà fornito come argomento della riga di comando. Stampa su output standard.

Esempi

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
numeri interi non negativi? So for 1234 we can do (massive expression) times zero plus one thousand two hundred thirty four.Potresti voler escludere zero. Sta a te.
Level River St

@steveverrill Un buon punto; L'ho cambiato in "numeri interi positivi".
Ypnypn,

4
sooo ... 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è valido?
Qwix,

@Qwix Sì; risposte noiose sono accettabili, anche se non si lavora per 104, 105, 106, 107, 108, 109, 110 o 111.
Ypnypn,

Risposte:


1

Javascript, 434 caratteri

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

Fornisce una funzione nello spazio dei nomi globale S, che accetta qualsiasi numero intero non negativo e restituisce la stringa richiesta o "Invalid"se non è possibile rappresentare l'intero nelle specifiche.

Sembrerebbe che abbia usato lo stesso approccio di @optokopper, avendo fatto la stessa osservazione che "plus six plus nine"è la stringa di riempimento più corta possibile e che tutti i numeri maggiori di 27 possono essere espressi concatenando una delle 15 stringhe di base a copie ripetute del pad.

Detto questo, le tabelle delle stringhe di base che utilizziamo differiscono e la mia soluzione si basa su bit twiddling e sul resto dell'operatore ( %). Include anche "multiplied by"come possibile operazione. E naturalmente la meccanica di come sono costruite le stringhe è completamente diversa a causa della dissomiglianza tra C e Javascript.

Questo è il mio miglior tentativo, in ogni caso. ;)

Un ringraziamento speciale a @chiru, la cui discussione sui numeri ottenibili ha contribuito a prevenire ricerche infruttuose.


22

JS, 1719/1694

Teoria

Sfortunatamente, il set di regole che fornisci potrebbe non essere una decisione saggia da un punto di vista matematico. In effetti, usando un sottoinsieme di regole più piccolo, puoi trovare una soluzione per ogni numero nell'intervallo dato

I = [1;  10000]

eccetto per

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

per il quale non esiste soluzione.

Set di regole ridotto

Considera il seguente sottoinsieme di regole:

  • Utilizzare solo gli operatori plus, minuse times.
  • Non è necessario implementare più occorrenze di pluso minusnelle tue espressioni.
  • Non è necessario implementaredivisionoperator associativity(poiché il loro set di soluzioni è già coperto dalla prima regola).

Il motivo per cui funziona è che, come discusso in precedenza con @Qwix, si consentono risposte noiose , ovvero espressioni che terminano nell'espressione regolare ( times one)+$. Consentendo ciò, ogni numero nell'intervallo indicato avrà una soluzione.

Quando hai risposto in uno dei tuoi commenti,

@Qwix Sì; risposte noiose sono accettabili, anche se non si lavora per 104, 105, 106, 107, 108, 109, 110 o 111. -

avevi assolutamente ragione: questo non funziona quando stai cercando di costruire la tua espressione iniziando con i numeri stessi, cioè one hundred four times one times one …o con qualsiasi altro di quei numeri.

Se tuttavia, la tua espressione inizia con un'espressione la cui valutazione è uguale a uno dei numeri indicati, sei sfortunato. Ad esempio, nota che 17 + 87è davvero 104, quindi potremmo scrivere 104come:

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

Per vedere che questo sottoinsieme funziona, salva questo file num.jse assicurati che SpiderMonkey, un motore JavaScript per le linee di comando, sia installato sul tuo sistema.

L'algoritmo

  • Definiamo la proprietà Kper numeri interi positivi come lo stato del numero che ha Nlettere e ha un valore di N.
  • Definiamo ulteriormente la proprietà Fdi un'espressione come lo stato della sua conversione di parole essendo 8kvolte più breve della sua valutazione con k ∈ ℕ. Fsta per "compilabile" e descrive se possiamo riempire o meno la parola conversione dell'espressione con espressioni di lunghezza 8 (cioè " times one") tali che l'espressione risultante possa ottenere la proprietà N.

Quindi procediamo come segue:

  • Converti il ​​numero di input in parole.
  • Controlla se il numero di input ha proprietà K.
    • In tal caso, restituisci le parole ( 4purtroppo è l'unico numero con questa proprietà).
    • In caso contrario, procedere.
  • Per tutte le espressioni a due operandi (aggiunte, sottrazioni e moltiplicazioni in questo ordine) che risultano nel numero di input, verificare se la loro valutazione ha proprietà K.
    • In tal caso, restituisci le parole.
    • In caso contrario, controlla se l'espressione a due operandi ha proprietà N.
      • In tal caso, riempire l'espressione con " times one"e verificare se la valutazione dell'espressione risultante ha proprietà K.
        • In tal caso, restituisci le parole
        • In caso contrario, procedere
      • In caso contrario, procedere
  • Vai a bere un caffè

Pratica

num.js (per SpiderMonkey / righe di 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 (per browser)

Il codice dato dall'alto non può funzionare per i browser a causa del suo ultimo comando, che afferra gli argomenti della riga di comando per fare un bel comando dallo script dato.

Per eseguire il codice JavaScript direttamente dal tuo browser, seleziona questa parte del codice sopra:

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}

Ora incollalo nella console JavaScript del tuo browser, in modo da poter produrre gli stessi risultati dal tuo browser con, ad esempio:

Y(1234);

Esempi (riga di 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 per vedere il trucco con cui puoi far funzionare ogni numero, dai un'occhiata alla noiosa risposta per 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

I codici forniti generano soluzioni valide per l'intervallo dato (e probabilmente anche sopra, dovresti solo aumentare il valore della variabile L).

statistica

Ero interessato a "quanto noiose " fossero le espressioni (o: quanto la sottostringa times onefosse usata per espressione all'interno di questo algoritmo), poiché questa parte era responsabile di trovare una soluzione per ogni numero all'interno dell'intervallo dato. Guardate voi stessi:

x : espressione n-esima (min. 0, max. 10.000)

y : numero di occorrenze della sottostringa "volte una" all'interno dell'espressione (min. 0, max. 1245)

Grafico

conclusioni:

  • Le espressioni tendono a diventare sempre più noiose in modo lineare.
  • Oltre il 99% delle soluzioni è noioso.

2
Esiste una soluzione per 4four
FUZxxl,

@FUZxxl Non l'ho mai negato. Nel caso tu stia rispondendo If it does, return the words (4 is the only number with this property, unfortunately), potresti aver frainteso questa sezione. Dice che 4è l'unica espressione priva di operatore che forma la propria soluzione.
Chiru,

@FUZxxl Oh, ok. Ho appena notato che nella sezione iniziale ho detto che non ci sono soluzioni in X = [0; 10] ∪ {12}, anche se in seguito, dico che 4ha una soluzione. Ho corretto l'intervallo, grazie. :)
Chiru,

6

C, 450 caratteri

Modifica: rimosso zero

Modifica: usando solo pluseminus

Ho cercato l'espressione più breve che aggiunge caratteri e mantiene la condizione vera. Ho trovato che plus ten plus fiveè lungo 15 e aggiunge 15 alla stringa.

Ho solo bisogno di espressioni per i primi 15 numeri che non sono impossibili, per esprimere qualsiasi numero possibile. 12 è il numero più grande impossibile, quindi è sufficiente per hardcode numeri più piccoli 28.

4 = quattro
11 = sei più cinque
13 = otto più cinque
14 = venti meno sei
15 = venti meno cinque
16 = diciotto meno due
17 = quattordici più tre
18 = ventidue meno quattro
20 = trentadue meno dodici
21 = venti più due meno uno
22 = venti più quattro meno due
23 = trenta meno otto più uno
24 = venti più otto meno quattro
25 = venti più otto meno tre
27 = ventotto meno sei più cinque

Possiamo scrivere ogni numero> 27 come x * 15 + uno dei numeri sopra.

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");}

Codice leggibile

#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
Non sei sicuro di come funzioni il tuo codice, ma dato che la domanda lo dice all numbers used in the output must be positive integers, potresti rimuoverlo #define Z "zero"dal tuo codice insieme alle istanze di Z poiché non dovresti mai usarlo?
Qwix,

"più dodici" è di 12 lettere. Ciò contribuirebbe ad abbreviare il codice?
isaacg,

Lo plus twelve
renderei

OK, ho letto male le regole.
isaacg,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.