JS, 1719/1694
теория
К сожалению, набор правил, который вы предоставляете, не может быть мудрым решением с математической точки зрения. Фактически, используя меньшее подмножество правил, вы можете найти решение для каждого числа в данном интервале
![Я = [1; 10000]](https://i.stack.imgur.com/KBiqV.gif)
кроме
![Х = [1; 3] ∪ [5; 10] ∪ {12}](https://i.stack.imgur.com/rDCDo.gif)
для которого нет решения.
Сокращенный набор правил
Рассмотрим следующую часть правил:
- Используйте только оператор
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 : количество вхождений подстроки «times one» в выражении (мин. 0, макс. 1245)

Выводы:
- Выражения имеют тенденцию становиться все более и более скучным в линейной манере.
- Более 99% растворов скучны.
So for 1234 we can do (massive expression) times zero plus one thousand two hundred thirty four.Вы можете исключить ноль. Вам решать.