Ausdruck, der seiner Länge entspricht


14

Suchen Sie bei einer gegebenen Zahl einen Ausdruck in Wörtern, die dieser Zahl entsprechen, mit einer Länge dieser Zahl.

Bei einer Eingabe von 15könnten Sie also eine Ausgabe sixteen minus onemit fünfzehn Zeichen (ohne Leerzeichen) durchführen. Wenn mehrere Lösungen vorhanden sind, drucken Sie, was Sie möchten. Ist dies nicht der Fall, drucken Sieimpossible

Verwenden Sie nur die Betreiber plus, minus, times, und divided by. Operatoren werden von links nach rechts ausgewertet.

Format 1234 als one thousand two hundred thirty four. Beachten Sie das Fehlen von "und" und dass es keine Bindestriche oder Kommas gibt.

Die Eingabe und alle in der Ausgabe verwendeten Zahlen müssen positive ganze Zahlen unter 10.000 sein.

Die Eingabe wird als Befehlszeilenargument angegeben. Auf Standardausgabe drucken.

Beispiele

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
nichtnegative ganze Zahlen? So for 1234 we can do (massive expression) times zero plus one thousand two hundred thirty four.Möglicherweise möchten Sie Null ausschließen. Wie du willst.
Level River St

@ Steveverrill Guter Punkt; Ich habe es in "positive ganze Zahlen" geändert.
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 oneist das gültig?
Qwix

@ Qwix Ja; langweilige Antworten sind akzeptabel, obwohl dies für 104, 105, 106, 107, 108, 109, 110 oder 111 nicht
funktioniert.

Antworten:


1

Javascript, 434 Zeichen

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

Gibt eine Funktion im globalen Namespace zurück, Sdie eine nicht negative Ganzzahl akzeptiert und die erforderliche Zeichenfolge zurückgibt oder "Invalid"wenn die Ganzzahl nicht in den Spezifikationen dargestellt werden kann.

Ich habe anscheinend den gleichen Ansatz wie @optokopper verwendet, wobei ich die gleiche Beobachtung gemacht habe, dass dies "plus six plus nine"die kürzestmögliche Füllzeichenfolge ist und dass alle Zahlen größer als 27 durch Verketten einer von 15 Basiszeichenfolgen zu wiederholten Kopien des Pads ausgedrückt werden können.

Allerdings unterscheiden sich die Tabellen der von uns verwendeten Basiszeichenfolgen, und meine Lösung basiert auf Bit-Twiddling und dem Restoperator ( %). Dies beinhaltet "multiplied by"auch eine mögliche Operation. Und natürlich ist die Mechanik des Aufbaus der Zeichenfolgen aufgrund der Unähnlichkeit zwischen C und Javascript völlig unterschiedlich.

Das ist jedenfalls mein bester Versuch. ;)

Besonderer Dank geht an @chiru, dessen Diskussion, welche Zahlen erreichbar waren, dazu beitrug, erfolgloses Suchen zu verhindern.


22

JS, 1719/1694

Theorie

Leider ist der von Ihnen angegebene Regelsatz aus mathematischer Sicht möglicherweise keine kluge Entscheidung. Tatsächlich können Sie mithilfe einer kleineren Teilmenge von Regeln für jede Zahl im angegebenen Intervall eine Lösung finden

I = [1;  10000]

ausser für

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

für die es keine lösung gibt.

Reduzierter Regelsatz

Beachten Sie die folgenden Regeln:

  • Verwenden Sie nur die Betreiber plus, minusund times.
  • Sie müssen nicht mehrere Vorkommen von plusoder minusin Ihren Ausdrücken implementieren .
  • Sie brauchen sich nicht zu implementieren weder divisionnoch operator associativity(wie ihre Lösungsmenge bereits durch die erste Regel abgedeckt ist).

Der Grund dafür ist, dass Sie, wie Sie bereits mit @Qwix besprochen haben, langweilige Antworten zulassen, dh Ausdrücke, die mit dem regulären Ausdruck enden ( times one)+$. Wenn Sie dies zulassen, hat jede Zahl im angegebenen Intervall eine Lösung.

Als Sie in einem Ihrer Kommentare geantwortet haben,

@ Qwix Ja; langweilige Antworten sind akzeptabel, obwohl dies für 104, 105, 106, 107, 108, 109, 110 oder 111 nicht funktioniert. -

Sie hatten vollkommen recht: Dies funktioniert nicht, wenn Sie versuchen, Ihren Ausdruck aus den Zahlen selbst one hundred four times one times one …oder einer anderen dieser Zahlen zu erstellen .

Wenn Ihr Ausdruck jedoch mit einem Ausdruck beginnt, dessen Bewertung einer der angegebenen Zahlen entspricht, haben Sie kein Glück. Beachten Sie beispielsweise, dass dies 17 + 87tatsächlich 104so ist , dass wir schreiben könnten 104:

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

Um zu sehen, ob diese Teilmenge funktioniert, speichern Sie diese Datei unter num.jsund stellen Sie sicher, dass SpiderMonkey, eine JavaScript-Engine für Befehlszeilen, auf Ihrem System installiert ist.

Der Algorithmus

  • Definieren wir die Eigenschaft Kfür positive Ganzzahlen als den Zustand der Zahl mit NBuchstaben und einem Wert von N.
  • Definieren wir die Eigenschaft Feines Ausdrucks weiter als den Zustand seiner 8kWortumwandlung , der -mal kürzer ist als seine Auswertung mit k ∈ ∈. Fsteht für "fillable" und beschreibt, ob wir die Wortkonvertierung des Ausdrucks mit Ausdrücken der Länge 8 (dh " times one") füllen können oder nicht , damit der resultierende Ausdruck die Eigenschaft erhält N.

Wir gehen dann wie folgt vor:

  • Wandle die eingegebene Zahl in Wörter um.
  • Überprüfen Sie, ob die eingegebene Nummer eine Eigenschaft hat K.
    • Wenn dies der Fall ist, geben Sie die Wörter zurück ( 4dies ist leider die einzige Zahl mit dieser Eigenschaft).
    • Wenn nicht, fahren Sie fort.
  • Überprüfen Sie für alle Zwei-Operanden-Ausdrücke (Additionen, Subtraktionen und Multiplikationen in dieser Reihenfolge), die zur Eingabenummer führen, ob ihre Auswertung Eigenschaften hat K.
    • Wenn dies der Fall ist, geben Sie die Wörter zurück.
    • Ist dies nicht der Fall, prüfen Sie, ob der Ausdruck mit zwei Operanden eine Eigenschaft hat N.
      • Wenn dies der Fall ist, füllen Sie den Ausdruck mit " times one"und prüfen Sie, ob die Auswertung des resultierenden Ausdrucks eine Eigenschaft hat K.
        • Wenn dies der Fall ist, geben Sie die Wörter zurück
        • Wenn nicht, fahren Sie fort
      • Wenn nicht, fahren Sie fort
  • Geh einen Kaffee trinken

Trainieren

num.js (für SpiderMonkey / Kommandozeilen)

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 (für Browser)

Der angegebene Code von oben kann aufgrund seines letzten Befehls, der die Befehlszeilenargumente aufgreift, nicht für Browser verwendet werden, um aus dem angegebenen Skript einen netten Befehl zu machen.

Um den JavaScript-Code direkt in Ihrem Browser auszuführen, wählen Sie diesen Teil des obigen Codes aus:

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}

Fügen Sie es nun in die JavaScript-Konsole Ihres Browsers ein, damit Sie die gleichen Ergebnisse in Ihrem Browser erzielen, zum Beispiel mit:

Y(1234);

Beispiele (Kommandozeile)

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

Und um zu sehen, mit welchem ​​Trick Sie jede Zahl zum Laufen bringen können, werfen Sie einen Blick auf die langweilige Antwort für 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

Mit den angegebenen Codes werden gültige Lösungen für das angegebene Intervall generiert (und wahrscheinlich müssen Sie auch darüber nur den Wert der Variablen erhöhen L).

Statistiken

Ich war daran interessiert, wie " langweilig " die Ausdrücke waren (oder wie viel der Teilstring times onepro Ausdruck in diesem Algorithmus verwendet wurde), da dieser Teil dafür verantwortlich war, für jede Zahl innerhalb des angegebenen Intervalls eine Lösung zu finden. Überzeugen Sie sich selbst:

x : n-ter Ausdruck (min. 0, max. 10.000)

y : Anzahl der Vorkommen der Teilzeichenfolge "mal eins" innerhalb des Ausdrucks (min. 0, max. 1245)

Graph

Schlussfolgerungen:

  • Die Ausdrücke werden linear immer langweiliger.
  • Über 99% der Lösungen sind langweilig.

2
Eine Lösung für 4 existiertfour
FUZxxl

@FUZxxl Das habe ich nie bestritten. Falls Sie antworten If it does, return the words (4 is the only number with this property, unfortunately), haben Sie diesen Abschnitt möglicherweise falsch verstanden. Es heißt, dies 4sei der einzige Ausdruck ohne Operator, der eine eigene Lösung bilde.
Chiru

@FUZxxl Oh, okay. Ich habe gerade bemerkt, dass es zu Beginn des Abschnitts keine Lösungen in X = [0; 10] ∪ {12}, obwohl ich später sage, das 4hat eine Lösung. Ich habe das Intervall korrigiert, danke. :)
Chiru

6

C 450 Zeichen

Bearbeiten: entfernt zero

Bearbeiten: nur mit plusundminus

Ich habe nach dem kürzesten Ausdruck gesucht, der Zeichen hinzufügt und die Bedingung wahr hält. Ich fand plus ten plus fiveist 15 lang und fügt 15 der Zeichenfolge hinzu.

Ich brauche nur Ausdrücke für die ersten 15 Zahlen, die nicht unmöglich sind, um eine mögliche Zahl auszudrücken. 12 ist die größte unmögliche Zahl, daher reicht es aus, Zahlen kleiner 28 fest zu codieren.

4 = vier
11 = sechs plus fünf
13 = acht plus fünf
14 = sechsundzwanzig minus
15 = fünfundzwanzig minus
16 = achtzehn minus zwei
17 = vierzehn plus drei
18 = zweiundzwanzig minus vier
20 = zweiunddreißig minus zwölf
21 = zwanzig plus zwei minus eins
22 = vierundzwanzig minus zwei
23 = dreißig minus acht plus eins
24 = zwanzig plus acht minus vier
25 = zwanzig plus acht minus drei
27 = achtundzwanzig minus sechs plus fünf

Wir können jede Zahl> 27 als x * 15 + eine der obigen Zahlen schreiben.

Golf gespielt

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

Lesbarer Code

#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
Sie sind sich nicht sicher, wie Ihr Code funktioniert, aber da die Frage lautet all numbers used in the output must be positive integers, können Sie den #define Z "zero"Code zusammen mit Instanzen von Z aus Ihrem Code entfernen, da Sie ihn niemals verwenden sollten?
Qwix

"plus zwölf" sind 12 Buchstaben. Würde das helfen, Ihren Code zu verkürzen?
isaacg

Ich würde es kürzer machen, leider zählen Leerzeichen nicht, plus twelveist nur 10 Buchstaben
Optokopper

OK, ich habe die Regeln falsch verstanden.
isaacg
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.