Вираз, що дорівнює його довжині


14

Давши число, знайдіть вираз у словах, що дорівнюють цьому числу, з довжиною цього числа.

Таким чином, на вхід 15ви можете вивести sixteen minus one, який містить п'ятнадцять символів (не рахуючи пробілів). Якщо існує декілька рішень, друкуйте те, що вам потрібно. Якщо такої немає, надрукуйтеimpossible

Використовуйте тільки оператори plus, minus, times, і divided by. Оператори оцінюються зліва направо.

Формат 1234 як one thousand two hundred thirty four. Зверніть увагу на відсутність "і", а також відсутні тире й коми.

Вхідні дані та всі числа, що використовуються у висновку, повинні бути цілими додатними числами менше 10 000.

Вхід буде подано як аргумент командного рядка. Друк на стандартний вихід.

Приклади

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
невід’ємні цілі числа? So for 1234 we can do (massive expression) times zero plus one thousand two hundred thirty four.Ви можете виключити нуль. До вас.
Рівень річки Св.

@steveverrill Хороший момент; Я змінив це на "натуральні числа".
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дійсно?
Qwix

@Qwix Так; нудні відповіді прийнятні, хоча це не працює для 104, 105, 106, 107, 108, 109, 110 або 111.
Ypnypn

Відповіді:


1

Javascript, 434 символів

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

Виходить функція в глобальній області імен, Sяка приймає будь-яке невід'ємне ціле число і повертає необхідний рядок, або"Invalid" якщо ціле число не може бути представлене в специфікаціях.

Здавалося б, я використовував той самий підхід, що і @optokopper, зробив те саме спостереження, що "plus six plus nine" є найкоротшою можливою рядок і всі числа, що перевищують 27, можна виразити шляхом об'єднання одного з 15 базових рядків у повторні копії колодки.

Сказавши це, таблиці базових рядків, які ми використовуємо, відрізняються, і моє рішення покладається на подвійне скручування біт та оператор залишку ( %). Він також включає "multiplied by"як можливу операцію. І, природно, механіка побудови струн зовсім інша через несхожість C та Javascript.

Це моя найкраща спроба, у будь-якому випадку. ;)

Особлива подяка @chiru, обговорення якої кількості було досягти, допомогло запобігти безрезультатному пошуку.


22

JS, 1719/1694

Теорія

На жаль, набір правил, який ви надаєте, не може бути розумним рішенням з математичної точки зору. Насправді, використовуючи менший підмножина правил, ви можете знайти рішення для кожного числа в заданому інтервалі

I = [1;  10000]

окрім

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

для якого немає рішення.

Скорочений набір правил

Розглянемо наступну підгрупу правил:

  • Використовуйте лише операторів plus, minusі times.
  • Вам не потрібно реалізовувати численні зустрічі plusабо minusу своїх виразах.
  • Вам не потрібно ні реалізувати, ні divisionні operator associativity(оскільки їх набір рішень вже охоплений першим правилом).

Причина, чому це працює, полягає в тому, що, як ви обговорювали раніше з @Qwix, ви дозволяєте нудні відповіді , тобто вирази, які закінчуються в регулярному виразі ( times one)+$ . Дозволяючи це, кожне число у заданому інтервалі матиме рішення.

Коли ви відповіли в одному зі своїх коментарів,

@Qwix Так; нудні відповіді прийнятні, хоча це не працює для 104, 105, 106, 107, 108, 109, 110 або 111. -

ви були абсолютно праві: це не спрацьовує, коли ви намагаєтеся побудувати своє вираження, починаючи з самих чисел, тобто one hundred four times one times one … будь-яких інших цих чисел.

Якщо ж ваш вираз починається з виразу, оцінка якого дорівнює одному із заданих чисел, вам не пощастило. Наприклад, зауважте, що 17 + 87це дійсно 104, тому ми могли б написати 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

Щоб побачити, що ця підмножина працює, збережіть цей файл як num.js і переконайтесь, що у вашій системі встановлено SpiderMonkey, двигун JavaScript для командних рядків.

Алгоритм

  • Давайте визначимо властивість Kдля натуральних чисел як стан числа, що має Nлітери та має значення N.
  • Далі визначимо властивість Fдля виразу як стан його перетворення слів, який 8k-тричі коротший, ніж його оцінка з k ∈ ℕ. Fозначає "fillable" і описує, чи можемо ми заповнити перетворення слова виразом виразами довжини 8 (тобто " times one") таким чином, щоб отриманий вираз міг отримати властивість N.

Потім ми поступаємо так:

  • Перетворити вхідне число в слова.
  • Перевірте, чи є вхідний номер K.
    • Якщо це так, поверніть слова ( 4на жаль, єдине число з цією властивістю).
    • Якщо цього не відбувається, продовжуйте.
  • Для всіх виразів з двома операндами (додавання, віднімання та множення в цьому порядку), які призводять до вхідного числа, перевірте, чи має їх оцінка властивість K.
    • Якщо так, поверніть слова.
    • Якщо це не так, перевірте, чи має вираз двох операндів властивість N .
      • Якщо це так, заповніть вираз " times one"і перевірте, чи має значення отриманий вираз властивістьK .
        • Якщо так, поверніть слова
        • Якщо цього не відбувається, продовжуйте
      • Якщо цього не відбувається, продовжуйте
  • Іди випий каву

Практика

num.js (для SpiderMonkey / командних рядків)

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 (для браузерів)

Даний код зверху не може працювати для браузерів через останню команду, яка захоплює аргументи командного рядка, щоб зробити гарну команду з даного сценарію.

Для того, щоб запустити код JavaScript безпосередньо з вашого браузера, виберіть цей фрагмент вищевказаного коду:

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}

Тепер вставте його в консоль JavaScript свого веб-переглядача, щоб ви могли створити ті самі результати у своєму браузері, наприклад:

Y(1234);

Приклади (командний рядок)

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

А для того , щоб побачити трюк , з яким ви можете зробити кожен номер роботи, просто подивитися на нудному відповідь на 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

Надані коди генерують дійсні рішення для заданого інтервалу (і, мабуть, навіть вище, вам доведеться лише підняти значення змінної L).

Статистика

Мене цікавило, наскільки нудними були вирази (або: скільки підрядкаtimes one було використано для кожного виразу в рамках цього алгоритму), оскільки ця частина відповідала за пошук рішення для кожного числа протягом заданого інтервалу. Побачте самі:

x : n-й вираз (хв. 0, макс. 10000)

y : кількість випадків підрядки "раз один" в виразі (хв. 0, макс. 1245)

Графік

Висновки:

  • Вирази, як правило, стають все більш нудними в лінійному порядку.
  • Понад 99% рішень нудні.

2
Рішення для 4 існуєfour
FUZxxl

@FUZxxl Я ніколи цього не заперечував. У випадку, якщо ви відповідаєте на це If it does, return the words (4 is the only number with this property, unfortunately), ви, можливо, неправильно зрозуміли цей розділ. Це говорить про те, що 4це єдиний вираз без оператора, який формує власне рішення.
Чіру

@FUZxxl О, добре. Я щойно помітив, що на початку розділу я сказав, що в X = немає рішень. 10] ∪ {12}, хоча пізніше я кажу, що це 4має рішення. Я виправив інтервал, дякую. :)
Чіру

6

C, 450 символів

Редагувати: видалено zero

Редагувати: лише за допомогою plusтаminus

Я шукав найкоротший вираз, який додає символів і підтримує умову. Я знайшов plus ten plus five15 довгих і додає 15 до рядка.

Мені потрібні лише вирази для перших 15 чисел, які не є неможливими, щоб виразити будь-яке можливе число. 12 є найбільшим неможливим числом, тому достатньо ввести код жорсткого коду, менший 28.

4 = чотири
11 = шість плюс п’ять
13 = вісім плюс п’ять
14 = двадцять мінус шість
15 = двадцять мінус п’ять
16 = вісімнадцять мінус два
17 = чотирнадцять плюс три
18 = двадцять два мінус чотири
20 = тридцять два мінус дванадцять
21 = двадцять плюс два мінус один
22 = двадцять плюс чотири мінус два
23 = тридцять мінус вісім плюс один
24 = двадцять плюс вісім мінус чотири
25 = двадцять плюс вісім мінус три
27 = двадцять вісім мінус шість плюс п’ять

Ми можемо записати кожне число> 27 у вигляді х * 15 + одне з чисел вище.

Гольф

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

Читаний код

#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
Не зовсім впевнений, як працює ваш код, але оскільки у запитанні зазначено, що all numbers used in the output must be positive integersви можете вийняти його #define Z "zero"зі свого коду разом із екземплярами Z, оскільки ви ніколи не повинні його використовувати?
Qwix

"плюс дванадцять" - це 12 літер. Чи допоможе це скоротити ваш код?
isaacg

Я зробив би коротше, на жаль, пробіли не рахуються, plus twelveце лише 10 букв
Optokopper

Гаразд, я неправильно прочитав правила.
isaacg
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.