到四的距离


13

此挑战基于此视频。我建议您在尝试此挑战之前先观看一下。

首先我们定义一个函数。此函数(OEIS)以整数n作为输入,并输出n的英语表示形式的字母数(不带空格或连字符)。例如,“三个”有5个字母,因此3个映射到5。

如视频中所示(以任何数字开头),重复此过程最终将得到4,该数字将永远映射到其自身。

这是一个粗略的有向图,显示了小于16的数字的轨道。

  12 11
    \|      
15 2 6 1 10 14 13
  \ \|/ /  /  /
   7 3-/  8--/
    \|   /
 9 0 5--/
  \ \|
   \-4

您面临的挑战是确定一个数字将要达到的四个步骤(即,有向图上的水平),然后确定一个数字将要执行的步骤数(或此功能必须应用于一个数字的次数)。

形成英文数字

以下是有关如何应对这一挑战的英文单词的简要说明:

数字1到19是:

一,二,三,四,五,六,七,八,九,十,十一,十二,十三,十四,十五,十六,十七,十八,十九

对于大于19的数字,过程如下:

如果数字有百位,则以百位中的数字名称开头并“百位”。

例如

100 -> "onehundred"

如果余数少于20,则附加余数的英语表示。

例如

714 -> "sevenhundredfourteen"

否则,如果十位数不为零,请附加适当的表示形式:

2-> twenty
3-> thirty
4-> forty
5-> fifty
6-> sixty
7-> seventy
8-> eighty
9-> ninety

例如

470 -> "fourhundredseventy"

最后,如果有一个数字,则附加其表示

例如

681 -> "sixhundredeightyone"

进一步规定

  • 对于大于100的数字,在计算字母数时应省略“和”。例如577是具有23个字母的“五百七十七”。

  • 您的程序必须接受通过标准方法输入的所有大于0且小于1,000的整数。

  • 您的程序必须输出标准输出方法所需的步骤数。

  • 这是代码高尔夫,因此以最少的字节数获胜的解决方案。

测试用例

1 -> 3
4 -> 0
7 -> 2
23 -> 5
577 -> 6
600 -> 4 

1
相关我以为这是骗子,但我找不到。
詹姆斯

“和”发生了什么?或者更确切地说,为什么要忽略呢?
乔纳森·艾伦

@JonathanAllan cuz'Murica
LegionMammal978 '09

Answers:


5

JavaScript(ES6),106个字节

f=(n,a="03354435543668877998")=>n-4&&1+f(7*(n>99)-(-a[n/100|0]-(a[n%=100]||a[n%10])-"0066555766"[n/10|0]))

尽管存在数字转换开销,但字符串似乎是编码长度的最佳方法。


天哪,这几乎就是我(几乎发布的)答案的样子,仅短11个字节。
ETHproductions's

@ETHproductions好事,我在发布之前先打了16个字节!
尼尔

2

Python,带有num2words,97 113 115 94 93 92字节

16个字节(忘了num2words适用的实际上不改变任何的测试情况的结果,即使断字23577每一个具有连字符)
2个字节(忘了,包括f=虽然递归)
-20字节(使用re
-8 @Wheat向导(使用~,替换n!=4n-4和...一行导入> _ <)获得
-1个字节@@ Cyoce(来自的空格4 and

import re,num2words as w
f=lambda n:n-4and-~f(len(re.sub('\W|and','',w.num2words(n))))

只计算步骤数;也适用于巨大和负整数(\W在num2words结果中找到空格,逗号和连字符):

>>> for test in (1,4,7,23,577,600,-1*2**96,3**96):
...     print('test: {0}  ->  {1}'.format(test, f(test)))
...
test: 1  ->  3
test: 4  ->  0
test: 7  ->  2
test: 23  ->  5
test: 577  ->  6
test: 600  ->  4
test: -79228162514264337593543950336  ->  4
test: 6362685441135942358474828762538534230890216321  ->  5

这是最后一种情况,分步进行:

sixquattuordecillionthreehundredsixtytwotredecillionsixhundredeightyfiveduodecillionfourhundredfortyoneundecilliononehundredthirtyfivedecillionninehundredfortytwononillionthreehundredfiftyeightoctillionfourhundredseventyfourseptillioneighthundredtwentyeightsextillionsevenhundredsixtytwoquintillionfivehundredthirtyeightquadrillionfivehundredthirtyfourtrilliontwohundredthirtybillioneighthundredninetymilliontwohundredsixteenthousthreehundredtwentyone
fourhundredfiftyone
nineteen
eight
five

1
不要你需要f=你的lambda函数之前
特设Garf猎人

1
尝试import re,num2words as r代替两个不同的语句。
Ad Hoc Garf Hunter

1
n-4n!=4
Ad Hoc Garf Hunter

1
@WheatWizard num2wordswre仍然是re-请注意,这两个模块和功能被称为num2words
乔纳森·艾伦

1
确定最后一个,and 1+可以替换and-~为保存一个字节
Ad Hoc Garf Hunter


1

Mathematica,89个字节

Length@FixedPointList[StringLength@StringReplace[IntegerName@#,{" "->"","-"->""}]&,#]-2&

典型的Mathematica:内置函数不错,长函数名称不好。FixedPointList重复地将其第一个参数(一个函数)应用于第二个参数,直到答案不变为止,列出所有结果;结果包括原始输入和重复输出的两个副本,因此-2在末尾。Mathematica的内置IntegerName包含空格和连字符,因此我们需要手工删除它们。

令人讨厌的是,IntegerName的输出包含字符“-”(Unicode#8208),而不是普通的连字符。这就是为什么此提交为89个字节而不是88个字节的原因。(而且我不能在上面的代码前加四个空格并让它接受Unicode字符(有帮助吗?),因此如果剪切和粘贴,上面的代码将无法正确工作)


1

Python 2.7版,344个 216 208字节:

x=`input()`;c=0;y=lambda v:dict(zip(range(0,10),[0]+v));l=[3,3,5,4,4,3,5,5,4];d=y(l);e=y([3,6,6,6,5,5,7,7,6]);f=y([i+7for i in l])
while x!='4':x=`sum([q[int(r)]for q,r in zip([d,e,f],x[::-1])])`;c+=1
print c

与其他Python答案不同,它不使用任何外部库。通过输入stdin并输出到stdout

重复使用所有测试用例!

说明

首先创建3个词典,每个词典将每个数字的英语单词表示长度与它在闭区间[1,9]中分别表示的数字成对(十,十和几百)。例如,在字典中的第一个条目d1:3作为1拼写one英语和具有3信件。

然后,将某个字符串输入中的每个数字位置x分配给其相应的字典,此后,将每个位置中的每个数字与其对应的字典中的值进行匹配。例如,假设输入数字为23。将20在十位将与字典配对e,其中与匹配6,并3在那些地方会用字典配对d,其中与匹配5。然后,将这些匹配位数加在一起以表示的数量,其被分配给的英语表示的长度x作为一个字符串和,只要x!='4',while循环的推移,增加c1每次代表迄今已采取的步骤数。因此,23对应于11,而对应于,然后对应于63然后转向5,最后转向4,从而导致5总步骤。

最终,一旦循环结束,c就输出来stdout表示“距离四”,在这种情况下为5


1

Java 556 295字节

感谢@KevinCruijssen保存261个字节

  void int(n) {int s[]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,9,8,6,9,9,11,10,6,6,5,5,7,7,6};int c=0,t=(int)Math.pow(10,(int)Math.log10(n)),v=1;while(n>0){if(n/100>0)c+=(s[n/100]+7);else {if(n>0&n<25){c+=s[n];break;}else{c+=s[(n/10)+22];}}n=n%t;t=t/10;}while(c!=4){v++;c=s[c];}System.out.print(v);}


取消高尔夫:

  void int(n) {

    int s[]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,9,8,6,9,9,11,10,6,6,5,5,7,7,6};
     int c=0,t=(int)Math.pow(10,(int)Math.log10(n)),v=1;
         while(n>0){
            if(n/100>0)
                c+=(s[n/100]+7);
            else {if(n>0&n<25){
                c+=s[n];
            break;
            }
            else{
                c+=s[(n/10)+22];

            }
            }
            n=n%t;
            t=t/10;
        }

        while(c!=4)
        {
            v++;
        c=s[c];
        }
System.out.print(v);
}

我认为您的代码有误,因为s++在字符串数组上是不可能的..:S
Kevin Cruijssen

@KevinCruijssen我将S(counter)声明为INT,STRING也是如此.... java会自动将其确定为INT。
Numberknot

好吧,如果我在ideone或Eclipse IDE中运行您的代码,它将失败,因为您有两个s.. Btw,您可以像下面这样大量使用代码:int c(int n){int s[]={0,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8,6,9,9,11,10,6,5,5,5,7,6,6},c=0,t=(int)Math.pow(10,(int)Math.log10(n)),x=1;while(n>0)if(n/100>0)c+=s[n/100]+7;else{if(n>0&n<25){c+=s[n];break;}else c+=s[(n/10)+22];}n%=t;t/=10;}for(;c!=4;x++,c=s[c]);return x;}
Kevin Cruijssen 2016年

我很震惊……我的代码发生了什么,感谢@KevinCruijssen ..并且我正在更正...再次感谢。
Numberknot

Np :)我认为不使用if-else并闯入那里可能会以某种方式打高尔夫球(但我将其留给其他人使用),但是您的初始代码是应对挑战的理想基础,因此+1从我。
凯文·克鲁伊森
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.