Скільки підрядних низхідних чисел у моєму номері?


18

Настав 2019 рік, і, напевно, всі помітили особливість цього числа: він насправді складається з двох підрядних чисел (20 та 19), що представляють собою послідовність послідовних низхідних чисел.

Виклик

Давши число x, поверніть довжину максимальної послідовності послідовних, низхідних чисел, які можна утворити, взявши підпункти x.

Примітки:

  • підрозрядні числа не можуть містити провідні нулі (наприклад, 1009не можна розділити на 10, 09)
  • послідовний і низхідний означає, що число в послідовності повинно бути рівним попередньому номеру -1, або нi+1=нi-1 (наприклад, 52не можна розділити на те, 5,2що не є послідовним 5і 2не є послідовним 2 ≠ 5 - 1)
  • послідовність повинна бути отримана з використанням повного числа, наприклад, 7321ви не можете відмовитися 7і отримати послідовність 3, 2,1
  • тільки одна послідовність може бути отримана з числа, наприклад , 3211098не може бути розділений на дві послідовності 3, 2, 1і 10, 9,8

Вхідні дані

  • Ціле число ( >= 0): може бути числом або рядком або списком цифр

Вихід

  • Єдине ціле число з урахуванням максимальної кількості знижувальних підрядних номерів (зауважте, що нижня межа цього числа є 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

Загальні правила:

  • Це , тому найкоротша відповідь у байтах виграє.
    Не дозволяйте мовам коду-гольфу відштовхувати вас від публікації відповідей з не кодовими гольф-мовами. Спробуйте придумати якомога коротшу відповідь на "будь-яку" мову програмування.
  • Для вашої відповіді застосовуються стандартні правила з правилами вводу / виводу за замовчуванням , тому вам дозволяється використовувати STDIN / STDOUT, функції / метод із відповідними параметрами та повним програмами типу повернення. Твій дзвінок.
  • Лазівки за замовчуванням заборонені.
  • Якщо можливо, додайте посилання з тестом для вашого коду (тобто TIO ).
  • Також настійно рекомендується додавати пояснення до своєї відповіді.

1
Перенесено з пісочниці: codegolf.meta.stackexchange.com/questions/2140/…
digEmВсі

1
Невже тестовий випадок 210 -> 2,1,0(те саме 0 -> 0)? У завданнях сказано, що " підрозряди не можуть містити провідні нулі ", нульовий це спеціальний випадок?
ბიმო

2
@BMO: ну, тут тема якась філософська ...: D для мене 0 - це число, у якому немає (непотрібного) нульового нуля, тому так нуль - це особливий випадок
digEmAll

2
Ви б назвали ці ... поблажливі номери? xD вибачте, що було навіть не смішно
HyperNeutrino

Вибачте, видалили мій коментар, в якому я запитав 212019. Здається, я не прочитав усіх правил.
cyclaminist

Відповіді:


6

Желе ,  15  9 байт

Виправлення завдяки Деннісу

ŻṚẆDfŒṖẈṀ

Спробуйте в Інтернеті! (навіть321займає півхвилини, оскільки код принаймніО(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 байт

Порт відповіді PyBo на ArBo значно коротший. Однак у деяких тестових випадках це не вдається через занадто велику рекурсію.

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}

Спробуйте в Інтернеті!

Розчин на основі Regex Я намагаюся придумати кращий спосіб встановити відповідність зі спадного списку, але 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

Пітон 3 , 232 228 187 181 180 150 149 байт

-1 спасибі @ Джонатану Фреху

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]).
Джонатан

Здається, що друга пропозиція не працює, хоча вона нічого не принесе, тому що тоді вам потрібно простір, щоб відокремити вираз від 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 байт завдяки Арнольду

Вводиться як рядок. Програма досить швидко наштовхується на межу глибини рекурсії 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.
Арнольд

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…θ⊕ιλ

Обчисліть перші kчисла у низхідній послідовності, починаючи з числа, заданого першими iцифрами введення, з'єднайте їх та накопичіть кожний результуючий рядок у попередньо визначеному порожньому списку.

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>0) (або це останнє число на вході ( c==[])) і aна одне більше першого номер відповідного попереднього розбиття x( a==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)довжини розбиття 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


@Shaggy обидва з них не вводяться, 21201оскільки вони не виконують вимоги, щоб кінець послідовності вирівнювався правильно (у моїй оригінальній версії рядок "закінчується комою"). Це або це альтернативні роботи.
Каміль Дракарі

Добренько. У такому разі: 26 байт
Shaggy

@Shaggy Це і 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

Діалог 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 на початку та в кінці матриці дійсних розділів для ⍵.

Тепер функція тренується зліва в паренах. Через лівий аргумент потягу - це рядок матриці розділів, а правий - аргумент користувача. Потяг - це купа вил, що розташовуються вгорі, як крайній лівий зубчик.

((≢⊂)×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
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.