等于长度的表达式


14

给定一个数字,找到一个等于该数字且长度等于该数字的表达式。

因此,对于的输入15,您可能会输出sixteen minus one,其中包含15个字符(不计算空格)。如果存在多个解决方案,请打印所需的任何内容。如果不存在,请打印impossible

只使用运营商plusminustimes,和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 2014年

4
那么... 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

Answers:


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

理论

不幸的是,从数学的角度来看,您提供的规则集可能不是明智的决定。实际上,使用较小的规则子集,您可以找到给定间隔中每个数字的解决方案

我= [1;  10000]

除了

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

为此没有解决方案。

简化规则集

请考虑以下规则子集:

  • 只能使用运营商plusminustimes
  • 无需在表达式中实现多次出现plusminus
  • 并不需要实现既不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∈evaluation的求值状态短-倍。F代表“ fillable”并描述我们是否可以使用长度为8(即" times one")的表达式来填充表达式的单词转换,以使结果表达式可以获取该属性N

然后,我们进行如下操作:

  • 将输入数字转换为单词。
  • 检查输入的数字是否具有属性K
    • 如果是这样,则返回单词(4很遗憾,此属性是唯一的数字)。
    • 如果不是,请继续。
  • 对于所有导致输入数字的二操作数表达式(按此顺序进行加,减和乘),请检查它们的求值是否具有property K
    • 如果是这样,则返回单词。
    • 如果不是,请检查两个操作数表达式是否具有property N
      • 如果是这样,请使用填充表达式," times one"然后检查结果表达式的评估是否具有property 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,最大10,000)

y:表达式中子字符串“乘以一”的出现次数(最小0,最大1245)

图形

结论:

  • 表达式趋于以线性方式越来越无聊。
  • 超过99%的解决方案很无聊。

2
存在4个解决方案four
FUZxxl 2014年

@FUZxxl我从未否认过。如果您要回应If it does, return the words (4 is the only number with this property, unfortunately),您可能误解了本节。它说,这4是形成其自己的解决方案的唯一无操作符的表达式。
Chiru 2014年

@FUZxxl哦,好的。我刚刚发现在开始的部分中,我说X = [0; 10]∪{12},虽然稍后再说,4但有解决方法。我更正了时间间隔,谢谢。:)
Chiru 2014年

6

C,450个字符

编辑:删除 zero

编辑:仅使用plusminus

我搜索了添加字符并保持条件为真的最短表达式。我发现plus ten plus five长度为15,并将15加到字符串中。

我只需要用前15个数字的表达式来表达任何可能的数字就可以了。12是最大的不可能数字,因此足以将较小的数字硬编码为28。

4 =四个
11 =六加五
13 =八加五
14 =二十减六
15 =二十减五
16 =十八减二
17 =十四加三
18 = 22减4
20 =三十二减十二
21 =二十加二减一
22 =二十加四减二
23 =三十减八加一
24 =二十加八减四
25 =二十加八减三
27 =二十八减去六加五

我们可以将> 27的每个数字写为x * 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中删除Z实例吗?
Qwix

“加十二”是12个字母。这会有助于缩短您的代码吗?
isaacg 2014年

我会更简短一点,可惜空格不算数,plus twelve只有10个字母
Optokopper 2014年

好,我误读了规则。
isaacg 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.