高效计数


35

当我还是个孩子的时候,想算一算生活中的美元钞票时,我会大声数出:

一,二,三,四,五,六,七,八,九,十;
十一,十二,十三,十四,十五,十六,十七,十八,十九,二十;
21、22、23、24、25 ...

最终我厌倦了念出这些多音节数字。出于数学考虑,我创建了一种更有效的计数方法:

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

如您所见,我只会说出与前一个数字已更改的数字。这还有一个额外的优势,即它比数字的英文名称具有更大的重复性,因此需要较少的脑力来进行计算。

挑战

编写一个程序/函数,该程序接受一个正整数,然后输出/返回我将如何对其进行计数:即,最右边的非零数字和所有尾随的零。

例子

   1    1
   2    2
  10   10
  11    1
  29    9
  30   30
  99    9
 100  100
 119    9
 120   20
 200  200
 409    9
1020   20

不需要完整的测试用例列表。这是OEIS上的A274206

规则

  • 理论上,您的条目必须适用于所有正整数,而忽略精度和内存问题。
  • 输入和输出必须为十进制。
  • 您可以选择将输入和/或输出作为数字,字符串或数字数组。
  • 输入保证为正整数。您的输入可以为无效输入做任何事情。

这是,因此以字节为单位的最短代码获胜。


那么“以十进制表示”是否包含一个十进制数字列表,例如[1,0,2,0]-> [2,0]用于最后一个测试用例?(我不清楚“单项数组”这句话)。
乔纳森·艾伦

1
@JonathanAllan“单项数组”是指包含单个数字或代表整数的字符串的数组。我不认为允许数字数组是一个好主意,但是由于允许使用字符串,所以这似乎是一个任意限制(并且字符串在许多语言中与数组非常相似)。因此,除非有充分的理由,否则我将允许使用数字数组。
ETHproductions '02

5
当它,你偷了我的秘密:P
LegionMammal978 '17

1
我认为几乎每个人都从小就这样算。;)至少我也做得很好。:)
Kevin Cruijssen

7
@KevinCruijssen“小时候”吗?
Martin Ender

Answers:


19

Python 2,28个字节

f=lambda n:n%10or 10*f(n/10)

在线尝试!

递归公式非常清晰。如果最后一位非零,则输出。否则,删除最后一个零,计算出该输出,然后乘以10。


11

果冻6 3 个字节

通过将I / O用作数字十进制列表,可得到 -3字节。

ṫTṪ

在线测试套件

怎么样?

ṫTṪ - Main link: listOfDigits  e.g.  [1,    0,    2,    0]  or [1,      1,    9  ]
 T  - truthy indexes                 [1,          3      ]     [1,      2,    3  ]
ṫ   - tail (vectorises)              [[1,0,2,0],  [2,0]  ]     [[1,1,9],[1,9],[9]]
  Ṫ - tail pop                                    [2,0]                       [9]

如果我们不能采用十进制列表,则6字节为:

DµṫTṪḌ

您可以在这里看到。

这做同样的事情,但是先将整数转换为十进制列表,然后再转换回整数。


当我滚动浏览前几个答案时,我对自己说:“我敢打赌,这里有一个3字节的Jelly解决方案……”
DLosc

9

C,30 29 27字节

当我滥用两个C漏洞来打高尔夫球时,这一点感到自豪(在文章末尾有介绍);这是专门针对C(GCC)的


3)b=10;f(a){a=a%b?:b*f(a/b);}// 27个字节

2)b;f(a){b=a=a%10?:10*f(a/10);}// 29个字节

1)f(i){return i%10?:10*f(i/10);}// 30个字节

在线尝试(27字节版本)


首次尝试(30字节):滥用以下事实:在GCC中,如果未声明任何三进制值,则将返回条件值。因此,为什么我的三元运算符对于真值返回值是空白的。

第二次尝试(29个字节):滥用GCC中的内存错误,据我了解,如果一个函数没有返回值,则当该函数中有意义地利用了两个以上的变量时,第一个参数变量的最后一个设置值将被退回。
   (编辑:但是此“设置值”必须以某些方式设置,例如,用=或设置变量,+=但用设置%=不起作用;很奇怪)

第三次尝试(27字节):由于无论如何我都必须有意义地利用第二个变量(b)来适当地滥用上述内存错误,因此我也可以将其用作“ 10”的实际变量来替代。
   (注意:我应该能够a=a%b与之交换a%=b以保存另一个字节,但是不幸的是,这导致上面的内存漏洞利用程序停止了“工作”,所以我不能)


您可能要在答案的标题中添加“ GCC”,因为它是特定于GCC的(不适用于clang)。另外,“内存错误”可能只是未定义的行为,由于GCC使用特定的堆栈框架布局,因此碰巧可以正常工作。即使使用GCC,它也可能无法在其他平台上运行。
simon

@gurka完成,谢谢
Albert Renshaw

7

视网膜7 6字节

!`.0*$

在线尝试(所有测试用例)

在输入字符串的末尾输出一个数字匹配项,后跟任意零。尽管不是必需的,但这也适用于0


had,我认为[1-9](或[^0])可能是必要的\d。我想*每次都确保正确输出的贪婪。
ETHproductions'2

@ETHproductions这与的贪婪无关,*而是与从左到右搜索匹配项有关。\d0*?$也可以。
Martin Ender

使用正则表达式.0*$应该工作
12Me21'2

如果有(足够短的)方法仅输出最后一场比赛,则可以使用.0*
12Me21 '17

@ 12Me21唯一的方法是仅匹配最后一个匹配项,或使用替换或类似内容。它不会更短。
mbomb007 '17

7

Cubix,18 32字节

我想稍后必须花一些时间,看看是否可以压缩一下。但是现在就在这里。
原来我在想这是完全错误的方式。现在,该过程将mod(1,10,100,1000,...)递增地应用于输入整数,并打印出第一个非零的整数。有点无聊,但更短。

!N%*I1^\.u;u@O\;;r

在这里尝试

    ! N
    % *
I 1 ^ \ . u ; u
@ O \ ; ; r . .
    . .
    . .

总是很高兴看到Cubix的答案:)
Oliver

@obarakon得到了改进,即将推出。确实以错误的方式执行了此操作
MickyT

5

JavaScript,21个字节

f=n=>n%10||10*f(n/10)

测试用例


5

Java脚本 19 18字节

多亏了ETHproductions的一个字节打高尔夫球和Patrick Roberts的两个字节打高尔夫球

x=>x.match`.0*$`

返回一个字符串数组,该字符串数组与输入字符串末尾的正则表达式匹配,并带有任意字符,后跟最大可能的零。

在线尝试


5
我认为您不需要g,因为只有一场比赛可以找到。
ETHproductions '02

使用x=>x.match`.0*$`
Patrick Roberts


3

污垢,5个字节

d\0*e

在线尝试!

说明

       Find the longest substring of the input matching this pattern:
d      a digit, then
 \0*   zero or more 0s, then
    e  edge of input (which is handled as an Nx1 rectangle of characters).

3

Brachylog,2个字节

a₁

在线尝试!

a₁整数的后缀内建实现为:

brachylog_adfix('integer':1, 'integer':0, 'integer':0).
brachylog_adfix('integer':1, 'integer':I, 'integer':P) :-
    H #\= 0,
    H2 #\= 0,
    abs(P) #=< abs(I),
    integer_value('integer':Sign:[H|T], I),
    integer_value('integer':Sign:[H2|T2], P),
    brachylog_adfix('integer':1, [H|T], [H2|T2]).

Brachylog喜欢将整数视为数字列表,为此它使用了自定义实用程序谓词integer_value/2。有趣的integer_value/2是,由于它必须能够正确转换带有前导零的数字列表,因此最终还能够将整数转换成带有前导零的数字列表,因此谓词不希望这样做发生(大多数情况,尤其是类似的未点操作a)会禁止其数字列表的a₁首位为0。因此,虽然生成列表和字符串最短的后缀,但它会跳过以0开头的整数的任何后缀,除了删除重复项之外,这还意味着生成的第一个后缀是带有所有尾随零的最右边的非零数字。


2

脑筋急转弯,74字节

{({}<>)<>}(()){{}<>(({}<>)[((((()()()){}){}){}){}]<(())>){((<{}{}>))}{}}{}

在线尝试!

仅打印最后的非0和所有尾随的0。

说明:

{({}<>)<>}                    # Move everything to the other stack (reverse the input)
(())                          # Push a 1 to get started
{                             # do...
  {}<>                        #   pop the result of the equals check (or initial 1)
  (                           #   push...
    ({}<>)                    #     the top value from the other stack (also put this on the stack)
    [((((()()()){}){}){}){}]  #     minus the ASCII value of 0
    <(())>                    #     on top of a 1
  )                           #   close the push   
  {                           #   if not zero (ie. if not equal)
    ((<{}{}>))                #     replace the 1 from 3 lines back with a 0
  }{}                         #   end if and pop the extra 0
}                             # while the copied value != "0"
{}                            # pop the result of the equals check


2

TI基本(18字节)

If fPart(.1Ans
Return
Ans.1
prgmA
10Ans

2

R,33个字节

实现为未命名函数

function(x)rle(x%%10^(0:99))$v[2]

这将应用从10 ^ 0到10 ^ 99的mod。 rle用于减少结果,以便第二项始终是我们想要的结果。
在线尝试!


2

Zsh18 16字节

<<<${(M)1%[^0]*}

在线尝试! 在线尝试!

Bash,25个字节

r=${1%[^0]*}
echo ${1#$r}

在线尝试!


外壳程序需要调用外部程序才能使用正则表达式,因此我们必须解决问题。

${1%[^0]*}扩展非零字符开头的最短后缀相匹配,并将其删除。

  • 在Zsh中,添加(M)标志会使匹配的后缀保留而不是删除。
  • 在Bash中,${1% }扩展将删除剩下的所有内容作为前缀。

1

GNU sed17 14 +1(r标志)= 15字节

编辑:少了2个字节,感谢赖利

s:.*([^0]):\1:

它的工作原理是删除所有内容,直到最右边的非零数字,然后将其与任何现有的尾随零一起打印。该脚本可以一次运行处理多个测试,每个测试都在单独的一行上。

在线尝试!(所有测试示例)


1

Mathematica,26个字节

纯函数,它接受一个数字列表并输出一个数字列表:

#/.{___,x_,y:0...}:>{x,y}&

说明

#                           First argument
 /.                           Replace
   {                              start of list followed by
    ___,                          zero or more elements followed by
        x_,                       an element (referred to later as x) followed by
           y:0...                 a sequence of zero or more 0s (referred to later as y) followed by
                 }                end of list
                  :>            with
                    {x,y}         {x,y}
                         &   End of function.

这是可行的x,因为它找到的最左边的匹配项,该匹配项必须是列表的最右边的非零元素,因为它后面跟随着一个零个序列,其中more 0s,然后是列表的末尾。


1

Java 8,47字节

这是可分配给的lambda表达式IntUnaryOperator

x->{int m=1;for(;x%m<1;m*=10);return x%m*m/10;}

说明:将m乘以10,直到x%m不为0。 return x%m*m/10需要除法,因为m比所需结果大一个数量级。



1

MATL10 7字节

@B节省了3个字节。梅塔!

tfX>Jh)

输入和输出是一个数字数组。

在线尝试!

验证所有测试用例

说明

t     % Input string implicitly. Duplicate
f     % Push indices of non-zero digits
X>    % Keep maximum, say k
Jh    % Attach 1j to give [k, 1j]. This is interpreted as an index "k:end"
)     % Index into original string. Display implcitly

由于我们允许将输入和输出作为整数矢量进行处理,因此您可以48-完全删除它,节省3个字节:在线尝试!
B. Mehta

1

C#,30 28个字节

基于此JavaScript答案,所以我想所有功劳都归功于他。

打高尔夫球

i=a=>a%10<1?10*i(a/10):a%10;
  • -2通过去除字节()周围a由于Emigna

1
我认为您需要i在使用递归时为函数明确命名。
Emigna '17

@Emigna你是对的!我完全错过了:(
Metoniem '17

更新了它,但我不确定100%是否这样正确
Metoniem

1
我不知道在C#中对此达成共识。该语法是有效的,但仅在已经声明了委托的情况下才有效(否则i将在递归调用中未声明)。
艾米娜(Emigna)'17

1
括号中的a任何一种都不是必需的。
艾米尼亚(Emigna)'17

1

J,27个字节

10&|`(10*(p%&10))@.(0=10&|)

它基于xnor的公式,因此归功于他。


1

Kotlin,49个字节

lambda,可分配给 (List<Int>) -> List<Int>

{a->a.slice(a.indexOfLast{it in 1..9}..a.size-1)}
  • 隐含参数名称itindexOfLast
  • .. 用于建筑范围

1

Perl 5,12个字节

11,加1 -nE代替-e

say/(.0*$)/

1

05AB1E,9个字节

RD0Ê1k>£R

在线尝试! 或作为 测试套件

说明

R          # reverse input
 D         # duplicate
  0Ê       # check each for inequality with 0
    1k     # get the index of the first 1
      >    # increment
       £   # take that many digits from the input
        R  # reverse



@MagicOctopusUrn:仅检查最后一位数字。它应该是最后一个非零数字以及之后的所有数字。
Emigna '18 -4-12



1

05AB1E,4 个字节

ĀÅ¡θ

I / O作为数字列表。

在线尝试验证所有测试用例(测试套件包含联接以提高可读性)。

说明:

Ā     # Python-style truthify each digit in the (implicit) input-list (0 if 0; 1 if [1-9])
      #  i.e. [9,0,4,0,3,0,0] → [1,0,1,0,1,0,0]
 Å¡   # Split the (implicit) input-list on truthy values (1s)
      #  i.e. [9,0,4,0,3,0,0] and [1,0,1,0,1,0,0] → [[],[9,0],[4,0],[3,0,0]]
   θ  # And only leave the last inner list
      #  i.e. [[],[9,0],[4,0],[3,0,0]] → [3,0,0]
      # (after which it is output implicitly as result)


0

Haskell 57字节

f(x:s)a|x=='0'=f s$'0':a|1>0=x:a
t x=f(reverse.show$x)[]

Input    -> Output
t 120    -> "20"
t 30200  -> "200"
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.