我的号码中有多少个连续的降序号?


18

2019年已经到来,也许每个人都注意到了这个数字的特殊性:实际上它是由两个子数字(20和19)组成的,代表两个连续的降序数字。

挑战

给定一个数字x,返回可以通过采用的子数字形成的连续的,递减数字的最大序列的长度x

注意事项:

  • 子数字不能包含前导零(例如1009,不能拆分为1009
  • 连续和降序表示该序列中的数字必须等于先前的数字-1,或者ni+1=ni1(例如52,不能分割为,5,2因为5并且2不连续,2 ≠ 5 - 1
  • 顺序必须使用完整的电话号码,如获得7321你不能放弃7,并获得序列321
  • 只能从数来获得的一个序列,例如3211098不能被分成两个序列3211098

输入值

  • 整数(>= 0):可以是数字,字符串或数字列表

输出量

  • 给定最大数目的递减子数字的单个整数(请注意,此数字的下限为1,即一个数字由其自身以长度为1的降序组成)

例子 :

2019         --> 20,19           --> output : 2
201200199198 --> 201,200,199,198 --> output : 4
3246         --> 3246            --> output : 1
87654        --> 8,7,6,5,4       --> output : 5
123456       --> 123456          --> output : 1
1009998      --> 100,99,98       --> output : 3
100908       --> 100908          --> output : 1
1110987      --> 11,10,9,8,7     --> output : 5
210          --> 2,1,0           --> output : 3
1            --> 1               --> output : 1
0            --> 0               --> output : 1
312          --> 312             --> output : 1
191          --> 191             --> output : 1

通用规则:

  • 这是,因此最短答案以字节为单位。
    不要让代码高尔夫球语言阻止您发布使用非代码高尔夫球语言的答案。尝试针对“任何”编程语言提出尽可能简短的答案。
  • 标准规则适用于具有默认I / O规则的答案,因此允许您使用STDIN / STDOUT,具有适当参数的函数/方法以及返回类型的完整程序。你的来电。
  • 默认漏洞是禁止的。
  • 如果可能的话,请添加一个带有测试代码的链接(即TIO)。
  • 另外,强烈建议为您的答案添加说明。


1
测试用例是否210 -> 2,1,0错误(与相同0 -> 0)?任务说“ 子数字不能包含前导零 ”,零是一种特殊情况吗?
ბიმო

2
@BMO:好吧,这里的话题有点儿系统化...:D对我来说,0是一个没有(无用的)前导零的数字,所以是零是一个特例
digEmAll

2
你会叫这些... 居高临下的数字吗?xD对不起,那甚至还不是很有趣
HyperNeutrino

抱歉,删除了我询问的评论212019。似乎我没有阅读所有规则。
cyclaminist

Answers:


6

果冻 15  9 字节

错误修复感谢丹尼斯

ŻṚẆDfŒṖẈṀ

在线尝试!321因为代码至少为O(N2)所以甚至需要半分钟)

怎么样?

ŻṚẆDfŒṖẈṀ - Link: integer, n
Ż         - [0..n]
 Ṛ        - reverse
  Ẇ       - all contiguous slices (of implicit range(n)) = [[n],...,[2],[1],[0],[n,n-1],...,[2,1],[1,0],...,[n,n-1,n-2,...,2,1,0]]
   D      - to decimal (vectorises)
     ŒṖ   - partitions of (implicit decimal digits of) n
    f     - filter discard from left if in right
       Ẉ  - length of each
        Ṁ - maximum

6

JavaScript(ES6),56个字节

ArBo的Python答案的端口大大缩短了。但是,由于太多的递归,它在某些测试用例上失败了。

f=(n,a=0,c=0,s)=>a<0?f(n,a-~c):n==s?c:f(n,--a,c+1,[s]+a)

在线尝试!


JavaScript(ES6),66个字节

将输入作为字符串。

f=(s,n=x='',o=p=n,i=0)=>s[i++]?o==s?i:f(s,--n,o+n,i):f(s,p+s[x++])

在线尝试!

已评论

f = (               // f = recursive function taking:
  s,                //   s = input number, as a string
  n =               //   n = counter
  x = '',           //   x = position of the next digit to be added to p
  o = p = n,        //   o = generated output; p = prefix
  i = 0             //   i = number of consecutive descending numbers
) =>                //
  s[i++] ?          // increment i; if s[i] was defined:
    o == s ?        //   if o is matching s:
      i             //     stop recursion and return i
    :               //   else:
      f(            //     do a recursive call with:
        s,          //       s unchanged
        --n,        //       n - 1
        o + n,      //       (n - 1) appended to o
        i           //       i unchanged (but it was incremented above)
      )             //     end of recursive call
  :                 // else:
    f(              //   this is a dead end; try again with one more digit in the prefix:
      s,            //     s unchanged
      p + s[x++]    //     increment x and append the next digit to p
    )               //   end of recursive call

通过实现对我的代码的更改来获得54个字节
ArBo

5

Perl 6的43个41 40字节

-1字节感谢nwellnhof

{/(<-[0]>.*?|0)+<?{[==] 1..*Z+$0}>/;+$0}

在线尝试!

基于正则表达式的解决方案。我正在尝试从降序列表中找到更好的匹配方法,但是Perl 6的分区效果不佳

说明:

{                                        }  # Anonymous code block
 /                                /;        # Match in the input
   <-[0]>.*?      # Non-greedy number not starting with 0
            |0    # Or 0
  (           )+  # Repeatedly for the rest of the number
                <?{             }>  # Where
                        1..*Z+$0       # Each matched number plus the ascending numbers
                                       # For example 1,2,3 Z+ 9,8,7 is 10,10,10
                   [==]                # Are all equal
                                    +$0  # Return the length of the list


4

Python 3中232个 228 187 181 180 150 149字节

-1感谢@ Jonathan Frech

e=enumerate
t=int
h=lambda n,s=1:max([1]+[i-len(n[j:])and h(n[j:],s+1)or s+1for j,_ in e(n)for i,_ in e(n[:j],1)if(t(n[:j])-t(n[j:j+i])==1)*t(n[0])])

在线尝试!

初始非高尔夫代码:

def count_consecutives(left, right, so_far=1):
    for i,_ in enumerate(left, start=1):
        left_part_of_right, right_part_of_right = right[:i], right[i:]
        if (int(left) - int(left_part_of_right)) == 1:
            if i == len(right):
                return so_far + 1
            return count_consecutives(left_part_of_right, right_part_of_right, so_far + 1)
    return so_far

def how_many_consecutives(n):
    for i, _ in enumerate(n):
        left, right = n[:i], n[i:]
        for j, _ in enumerate(left, start=1):            
            left_part_of_right = right[:j]
            if int(left) - int(left_part_of_right) == 1 and int(n[i]) > 0:     
                return count_consecutives(left, right)
    return 1

1
s+1 for可以s+1for(t(n[:j])-t(n[j:j+i])==1)*t(n[0])可能是t(n[:j])-t(n[j:j+i])==1>=t(n[0])
乔纳森·弗雷奇

似乎第二个建议虽然不能带来任何好处,但它不起作用,因为那样一来,您就需要空间来将expression与分开if
西冈

正确...替代149
乔纳森·弗雷奇

4

Python 2中78个 74 73字节

l=lambda n,a=0,c=0,s="":c*(n==s)or a and l(n,a-1,c+1,s+`a-1`)or l(n,a-~c)

在线尝试!

-1字节感谢Arnauld

将输入作为字符串。该程序很快就会遇到Python的递归深度限制,但是它可以完成大多数测试用例。

怎么运行的

l=lambda n,                              # The input number, in the form of a string
         a=0,                            # The program will attempt to reconstruct n by
                                         #  building a string by pasting decreasing
                                         #  numbers, stored in a, after each other.
         c=0,                            # A counter of the amount of numbers
         s="":                           # The current constructed string
              c*(n==s)                   # Return the counter if s matches n
              or                         # Else
              a and l(n,a-1,c+1,s+`a-1`) # If a is not yet zero, paste a-1 after s
              or                         # Else
              l(n,a-~c)                  # Start again, from one higher than last time

1
好答案!a+c+1可以缩短为a-~c
Arnauld

3

05AB1E,10 个字节

ÝRŒʒJQ}€gà

极慢,因此下面的TIO仅适用于750以下的测试用例。

在线尝试

说明:

Ý           # Create a list in the range [0, (implicit) input]
            #  i.e. 109 → [0,1,2,...,107,108,109]
 R          # Reverse it
            #  i.e. [0,1,2,...,107,108,109] → [109,108,107,...,2,1,0]
  Œ         # Get all possible sublists of this list
            #  i.e. [109,108,107,...,2,1,0]
            #   → [[109],[109,108],[109,108,107],...,[2,1,0],[1],[1,0],[0]]
   ʒ  }     # Filter it by:
    J       #  Where the sublist joined together
            #   i.e. [10,9] → "109"
            #   i.e. [109,108,107] → "109108107"
     Q      #  Are equal to the (implicit) input
            #   i.e. 109 and "109" → 1 (truthy)
            #   i.e. 109 and "109108107" → 0 (falsey)
       g   # After filtering, take the length of each remaining inner list
            #  i.e. [[109],[[10,9]] → [1,2]
         à  # And only leave the maximum length (which is output implicitly)
            #  i.e. [1,2] → 2

2
代码高尔夫-在程序中添加1字节n!n lg n只是不值得的。
corsiKa

3

Pyth,16个字节

lef!.EhM.+vMT./z

在此处在线尝试,或在此处一次验证所有测试用例。

lef!.EhM.+vMT./z   Implicit: z=input as string
             ./z   Get all divisions of z into disjoint substrings
  f                Filter the above, as T, keeping those where the following is truthy:
          vMT        Parse each substring as an int
        .+           Get difference between each pair
      hM             Increment each
   !.E               Are all elements 0? { NOT(ANY(...)) }
 e                 Take the last element of the filtered divisions
                     Divisions are generated with fewest substrings first, so last remaining division is also the longest
l                  Length of the above, implicit print

3

果冻,11字节

ŒṖḌ’Dɗ\ƑƇẈṀ

Øñ0.3

在线尝试!

怎么运行的

ŒṖḌ’Dɗ\ƑƇẈṀ  Main link. Argument: n (integer)

ŒṖ           Yield all partitions of n's digit list in base 10.
        Ƈ    Comb; keep only partitions for which the link to the left returns 1.
       Ƒ       Fixed; yield 1 if calling the link to the left returns its argument.
      \          Cumulatively reduce the partition by the link to the left.
     ɗ             Combine the three links to the left into a dyadic chain.
  Ḍ                  Undecimal; convert a digit list into an integer.
   ’                 Decrement the result.
    D                Decimal; convert the integer back to a digit list.

3

木炭,26字节

F⊕LθF⊕Lθ⊞υ⭆κ⁻I…θιλI﹪⌕υθ⊕Lθ

在线尝试!链接是详细版本的代码。说明:

F⊕Lθ

i从0 循环到输入的长度。

F⊕Lθ

k从0 循环到输入的长度。

⊞υ⭆κ⁻I…θ⊕ιλ

ki输入的第一个数字给出的数字开始,以降序计算第一个数字,将它们连接起来,并将每个结果字符串累加到预定义的空列表中。

I﹪⌕υθ⊕Lθ

查找输入的第一个匹配副本的位置,并将其模数比输入的长度减少1。

示例:对于2019以下字符串的输入,将生成:

 0
 1  0
 2  0-1
 3  0-1-2
 4  0-1-2-3
 5  
 6  2
 7  21
 8  210
 9  210-1
10  
11  20
12  2019
13  201918
14  20191817
15  
16  201
17  201200
18  201200199
19  201200199198
20  
21  2019
22  20192018
23  201920182017
24  2019201820172016

2019 然后在索引12处找到,将其取模5以得到2,即所需的答案。


3

Haskell,87个字节

maximum.map length.(0#)
a#(b:c)=[a:x|c==[]||b>0,x<-b#c,a==x!!0+1]++(10*a+b)#c
a#b=[[a]]

输入是数字列表。

在线尝试!

函数#通过查看两个列表来构建所有可能拆分的列表

  • 仅在下一个数字不为零()(或者它是输入()中的最后一个数字)并且比第一个大一个时,才将当前数字放在a递归调用与其余输入(x<-b#c)一起返回的所有拆分之前相应的前一个分割的编号()。b>0c==[]axa==x!!0+1

  • b输入列表中的下一位数字附加到当前数字上a,然后与其余的输入((10*a+b)#c)继续

基本情况是输入列表为空(即与模式不匹配(b:c))。递归开始与当前的数量a存在0(0#)),它从来没有碰到第一支路(前添加a到所有以前的拆分),因为它永远不会比任何数量的分裂更大。

取每个拆分的长度并找到最大值(maximum.map length)。

也有87个字节的变体:

fst.maximum.(0#)
a#(b:c)=[(r+1,a)|c==[]||b>0,(r,x)<-b#c,a==x+1]++(10*a+b)#c
a#b=[(1,a)]

基本上以相同的方式工作,但不是将整个拆分保留在列表中,而是仅保留(r,x)拆分长度的一对和split中r的第一个数字x


3

Python 3中302个 282 271字节

-10个字节,感谢@ElPedro的提示。

将输入作为字符串。基本上,它从左开始增加数字的较大切片,然后查看是否可以使用所有数字形成该编号的切片。

R=range
I=int
L=len
def g(n,m,t=1):
 for i in R(1,L(m)+1):
  if I(m)==I(n[:i])+1:
   if i==L(n):return-~t
   return g(n[i:],n[:i],t+1)
 return 1
def f(n):
 for i in R(L(n)):
  x=n[:i]
  for j in R(1,L(x)+1):
   if (I(x)==I(n[i:i+j])+1)*I(n[i]):return g(n[i:],x)
 return 1

在线尝试!


1
由于您使用了range3次,因此可以R=range在这两个函数之外定义,然后使用R(whatever)代替而不是range(whatever)保存4个字节。
ElPedro

3

Japt,27个字节

ò pÊÔpÊqÊfl²i1Uì q"l?"¹ÌèÊÉ

在线尝试!检查大多数测试用例

这得分不高,但是使用了一种独特的方法,可能还有更多打高尔夫的空间。除了201200199198避免超时之外,它还可以很好地执行所有测试用例。

说明:

ò                              #Get the range [0...input]
  pÊ                           #Add an "l" to the end
    Ô                          #Reverse it
     pÊ                        #Add an "l" to the end
       qÊ                      #Add an "l" between each number and turn to a string
         f            ¹        #Find the substrings that match this regex:
          l²                   # The string "ll"
            i1                 # With this inserted between the "l"s:
              Uì               #  All the digits of the input
                 q"l?"         #  With optional spaces between each one
                       Ì       #Get the last match
                        èÊ     #Count the number of "l"s
                          É    #Subtract 1

我想,适用于27
长毛


@Shaggy这两个输入都失败,21201因为它们不强制序列结尾正确对齐(在我的原始版本中,“以逗号结尾”行)。这种这种替代方法有效。
卡米尔·德拉卡里

喔好吧。在这种情况下:26个字节
粗毛的

@Shaggy That和我遇到的28字节解决方案失败了,210因为0后面没有定界符。是一个固定的28字节,可以工作。
卡米尔·德拉卡里

2

Haskell,65个字节

f i=[y|x<-[0..],y<-[1..length i],i==(show=<<[x+y-1,x+y-2..x])]!!0

输入是一个字符串。

在线尝试!

与我的其他答案完全不同。一种简单的蛮力,尝试所有连续降序的列表,直到找到等于输入列表的列表。

如果我们限制输入数量64位整数,我们可以通过循环保存6个字节y通过[1..19],因为最大的64位整数有19位,而且也没有必要用更多的元素测试列表。

Haskell,59个字节

f i=[y|x<-[0..],y<-[1..19],i==(show=<<[x+y-1,x+y-2..x])]!!0

在线尝试!


2

Python 2,95个字节

lambda n:max(j-i for j in range(n+1)for i in range(-1,j)if''.join(map(str,range(j,i,-1)))==`n`)

另一个缓慢的暴力解决方案。

在线尝试!


2

Dyalog APL,138个字节

一点点,但它也适用于大量数字。如果您在线尝试,请在dfn ⎕←前面加上前缀,并在右侧以数字列表形式提供输入。

{⌈/⍵((≢⊂)×1∧.=2-/10⊥¨⊂)⍨⍤1⊢1,{⍬≡1↓⍵:↑⍬1⋄0=⊃⍵:0,∇1↓⍵⋄↑,0 1∘.,⊂⍤1∇1↓⍵}1↓⍵}

说明

首先,右侧的内部dfn递归构造了一系列可能的方式来对数字列表进行分区。例如1 0 1 0 ⊂ 2 0 1 9返回嵌套向量(2 0)(1 9)

{
   ⍬≡1↓⍵: ↑⍬1       ⍝ Edge case: If ⍵ is singleton list, return the column matrix (0 1)
   0=⊃⍵: 0,∇1↓⍵     ⍝ If head of ⍵ is 0, return 0 catenated to this dfn called on tail ⍵
   ↑,0 1∘.,⊂⍤1∇1↓⍵  ⍝ Finds 1 cat recursive call on tail ⍵ and 0 cat recursive call on ⍵. 
}                    ⍝ Makes a matrix with a row for each possibility.

我们1,通常在开头添加一列1s,最后以valid的有效分区矩阵结尾。

现在功能列在左侧。由于火车的左参数是分区矩阵的行,右参数是用户输入。火车是一堆叉子,最顶端的叉在上面。

((≢⊂)×1∧.=2-/10⊥¨⊂)⍨     ⍝ ⍨ swaps left and right arguments of the train.
                  ⊂       ⍝ Partition ⍵ according to ⍺. 
             10⊥¨         ⍝ Decode each partition (turns strings of digits into numbers)
          2-/             ⍝ Difference between adjacent cells
      1∧.=                ⍝ All equal 1?
   ⊂                      ⍝ Partition ⍵ according to ⍺ again
  ≢                       ⍝ Number of cells (ie number of partitions)
     ×                    ⍝ Multiply.

如果分区创建了一个降序序列,那么火车将返回序列的长度。否则为零。

⍤1⊢在用户输入和分区矩阵的每一行之间应用功能序列,为矩阵的每一行返回一个值。消除的派生函数的操作数与参数之间的歧义是必要的

⌈/ 找到最大值。

可以找到一个较短的算法,但是我想尝试这种方式,这是我能想到的最直接和最声明的方式。


欢迎来到PPCG!这是令人印象深刻的第一篇文章!
Rɪᴋᴇʀ

1

TSQL,169字节

注意:仅当输入可以转换为整数时才能执行此操作。

递归sql用于循环。

打高尔夫球:

DECLARE @ varchar(max) = '1211109876';

WITH C as(SELECT left(@,row_number()over(order by 1/0))+0t,@+null z,0i
FROM spt_values UNION ALL
SELECT t-1,concat(z,t),i+1FROM C WHERE i<9)SELECT
max(i)FROM C WHERE z=@

取消高尔夫:

DECLARE @ varchar(max) = '1211109876';

WITH C as
(
  SELECT
    left(@,row_number()over(order by 1/0))+0t,
    @+null z,
    0i
  FROM
    spt_values
  UNION ALL
  SELECT
    t-1,
    concat(z,t),
    i+1
  FROM C
  WHERE i<9
)
SELECT max(i)
FROM C
WHERE z=@

试试看


0

R,101字节

function(a,N=nchar(a)){for(x in 1:N)F=max(F,which(Reduce(paste0,seq(substr(a,1,x),,-1,N),a=T)==a));F}

在线尝试!

已经有2个多星期没有任何R答案了,所以我决定发表我自己的:)

该代码非常快,因为它使用了“有限的”蛮力方法

展开代码和说明:

function(a){                  # get string a as input (e.g. "2019")

  N = nchar(a)                # set N = length of a (e.g. 4)
  Y = 0                       # initialize Y = 0 (in the actual code we abuse F)

  for(x in 1:N){              # for x in 1 ... N    

    S = substr(a,1,x)         # get the first x characters of a (e.g. "20" for x=2)

    Q = seq(S,,-1,N)          # create a decreasing sequence (step = -1) 
                              # of length N starting from S converted into integer
                              # (e.g. Q = c(20,19,18,17) for x=2)

    R = Reduce(paste0,Q,a=T)  # concatenate all the increasing sub-sequences of Q
                              # (e.g. R = c("20","2019","201918","20191817") for x=2)

    I = which(R == a)         # Get the index where R == a, if none return empty vector
                              # (e.g. I = 2 for x=2)

    Y = max(Y,I)              # store the maximum index found into Y
  }
  return(Y)                   # return Y
}
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.