Відсортований лексичний розділ числа


17

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

Плутати?

  • Вам надається додатне ціле число через STDIN (або найближчу альтернативу), аргумент командного рядка або аргумент функції в будь-якому зручному, однозначному форматі введення.
  • Ви повинні розділити десяткові цифри числа на суміжні, нероздільні групи.
  • Масив чисел, представлений цими розрядними групами, слід сортувати (у звичайному, не зменшуваному порядку) без перестановки груп .
  • У випадках, коли існує більше одного такого розділу, ви повинні розділити вхід на якомога більше номерів. У випадку зв’язків поверніть один такий результат.
  • Ви можете вивести масив в STDOUT (або найближчу альтернативу) або як повернене значення функції. У випадку STDOUT (або найближчої альтернативи) масив повинен бути надрукований у будь-якому зручному, однозначному форматі списку.
  • Розділені числа не повинні мати провідних нулів. Так, наприклад, 1002003не може бути надруковано як [1, 002, 003]або, [1, 2, 3]і є єдиною вірною відповіддю на це [100, 2003].

Тестові приклади:

123456 -> [1, 2, 3, 4, 5, 6]
345823 -> [3, 4, 5, 8, 23]
12345678901234567890 -> [1, 2, 3, 4, 5, 6, 7, 8, 90, 123, 456, 7890]
102 -> [102]
302 -> [302]
324142 -> [3, 24, 142] OR [32, 41, 42]
324142434445 -> [32, 41, 42, 43, 44, 45]
1356531 -> [1, 3, 5, 6, 531]
11121111111 -> [1, 1, 1, 2, 11, 11, 111]
100202003 -> [100, 202003]

Оцінка балів

Це код-гольф, тому найкоротший код в байтах виграє.

Відповіді:


10

Піта, 34

FNyUz#aYmv:zhdedC,+0N+NlzB)efqSTTY

Спробуйте його онлайн тут . Зауважте, це має часову (і просторову) складність O (n). Тому тестовий випадок 12345678901234567890займає занадто багато часу в онлайн-компіляторі. Замість цього використовуйте офлайн (1 хвилина на моєму ноутбуці).

Це лише моя перша спроба. Можливо, буде можливість покращитись.

Спочатку кілька ідей, як працює мій алгоритм.

  • Я інтерпретую введення як рядок, а не як число.
  • Тоді я створюю всі можливі підмножини [0, 1, 2, ..., len(n-1)]
  • Для кожного з цих підмножин (давайте взяти [1, 4, 5]) я розділив вхідний рядок на частину, використовуючи ці числа. [input[0:1], input[1, 4], input[4,5], input[5,len(input)]].
  • Згодом я намагаюся перетворити ці числа в рядки. Може виникнути дві проблеми. Pyth (або Python) видає виняток як для порожнього рядка, так і для рядка чисел, починаючи з 0. Тому я використовую try - catchблок (власне цикл нескінченності з негайним розривом). Якщо перетворення було успішним, я додаю результат до списку Y.
  • Після того як я обробив усі підмножини, я фільтрую список Yза результатами, які вже відсортовані та друкую останню (остання має найбільше груп).

Тепер детальне пояснення:

                            Implicit: z = input() (z is a String!)
                                      Y = empty list
FNyUz                       for each subset N of [0, 1, 2, ..., len(z)-1]:

     #                         start try-catch block (actually an infinite loop, 
                               but the Python implementation uses a try catch. 

      aY                          append to Y:
                C,+0N+Nlz            zip([0] + N, N + [len(z)])
        m                            map each element d to
          :zhded                     z[d[0]:d[-1]]
         v                           evaluated
                         B        if this didn't throw an exception already, end the infinite loop
                          ) end for loop   

 f    Y      filter Y for elements T, for which
  qSTT           sorted(T) == T
e            and print the last one (the subsets generated with yUz are sorted 
             by length, so the last one has the most groups)

Ви можете використовувати aYзамість~Y]
FryAmTheEggman

@FryAmTheEggman Я завжди про це забуваю a. Не знаю чому.
Якубе

@Jakube Можливо тому, що його немає в документах?
Sp3000

У мене було рішення для ~ 45 символів. Мені не було відомо про те, int("01")що помилка в Pyth (цього не відбувається в Python).
orlp

3
@Jakube haha, хоча і здається логічним, але загалом n- це довжина введення.
Оптимізатор

6

Математика, 134 127 байт

Це досить неефективно, оскільки генерує набагато більше розділів, ніж дійсні. 324142434445Тест виконується в протягом декількох секунд, але я б не спробувати 12345678901234567890.

f/@Last@Select[Needs@"Combinatorica`";f=FromDigits;SetPartitions[d=IntegerDigits@#],0<=##&@@f/@#&&Join@@#==d&&#~FreeQ~{0,__}&]&

Це визначає неназвану функцію, яка приймає ціле число і повертає список цілих чисел.

Пояснення

Порядок читання цього коду є повсюдно, тому я розбиваюсь у порядку, який він повинен читати (і оцінювати здебільшого):

  • d=IntegerDigits@#отримати десяткові цифри введення та призначити цьому списку d.
  • SetPartitions(що вимагає Needs@"Combinatorica`";) дає мені всі розділи цього. Однак він повертає набагато більше, ніж я насправді хочу, оскільки трактує дані як набір . Це робить його неефективним, але я використовую це, тому що найкоротший шлях, який я знаю, щоб отримати всі розділи списку, значно довший. Як приклад, якби список був {1, 2, 3}функцією, повертався б:

    {{{1, 2, 3}}, {{1}, {2, 3}}, {{1, 2}, {3}}, {{1, 3}, {2}}, {{1}, {2}, {3}}}
    

    Зауважте, що а) послідовні розділи розташовані в правильному порядку; б) розділи відсортовані від грубих до найтонших.

  • Select[...,...&] потім фільтрує цей список за анонімною функцією, переданою як другий аргумент.
    • Join @@ # == d перевіряє, що у нас насправді є розділ списку замість загального встановленого розділу.
    • #~FreeQ~{0, __} перевіряє, що жоден розділ не починається з ведучого нуля.
    • 0 <= ## & @@ f /@ #дещо незрозуміліше. Спочатку ми відображаємо FromDigitsкожен список у розділі, щоб відновити числа, представлені цифрами. Тоді ми застосовуємося 0 <= ##до тих чисел, де ##посилаються на всі числа. Якщо розділ є, {1, 23, 45}це розгортається до 0 <= 1 <= 23 <= 45, тож він перевіряє, чи масив відсортований.
  • Last@потім видає мені останній розділ, що залишився після фільтрації - це працює, тому що SetPartitionsвже сортували розділи, такі, що найкращі в кінці.
  • Нарешті, f/@відновлює числа з цифрових списків.

5

Пітон 3, 134 байти

def f(s,n=0,L=[],R=[],i=0):
 while s[i:]:i+=1;m=int(s[:i]);R=max([f(s[i:],m,L+[m]),R][m<n or"1">s[i:]>"":],key=len)
 return[L,R][s>""]

Це трохи безладно, але добре. Програма просто генерує всі дійсні розділи рекурсивно. Цікава частина полягає в тому, що забороняти провідні нулі все, що було потрібно, було додатковою or "1">s[i:]>""умовою.

Приймає введення як f("12345678901234567890")і повертає список вкладень.


4

Pyth, 62 61 60

JlzKkef&qJsml`dTqTSTolNmmibTcjKsC,z+m>Ndt>+*J]0jk2_JKNU^2-J1

Пояснення

Алгоритм працює, генеруючи всі двійкові числа між 0(включно) та 2^(n-1)(ексклюзивними), де nдовжина вводу.

Двійкові цифри кожної з них відображаються у роздільник ( N) на 1, а нічого на 0.

Потім ці символи вставляються між кожним вхідним символом, і результат ділиться на N, отримуючи список.

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

Jlz                                                   set J to len(input)
Kk                                                    set K to ""
e                                                     take the last of:
 f&                                                    only take lists where:
   qJsml`dT                                             sum of string lengths of items
                                                        is equal to length of input and
           qTST                                         list is in order
               olN                                       sort by length
                  m                                       map k over...
                   mibT                                    convert items to int (base-10)
                       c                        N           split by N
                        jK                                   join by ""
                          s                                   sum to combine tuples
                           C,z                                 zip input with
                              +                K                append [""] for equal lengths
                               m>Nd                              replace 1 with N, 0 with ""
                                   t                              take all but first
                                    >        _J                    take len(input) last values
                                     +                              pad front of binary with
                                      *J]0                           [0] times input's length
                                          jk2                        current k in binary
                                                 U^2-J1  range 0..2^(len(input)-1)-1

1

(Неконкурент) Pyth, 25 байт

ef&&Fmnhd\0T.A<V=NsMTtN./

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

Як це працює:

ef&&Fmnhd\0T.A<V=NsMTtN./  Q = eval(input())
                         ./  all partitions of Q
 f                       ./  filter all partitions of Q where:
  &                            both:
   &Fmnhd\0T                     neither substring starts with "0"
                               and:
            .A<V=NsMTtN          all entries are less than their proceeding ones
e                            returns the last amongst the filtered partitions

0

J, 109 байт

Дуже довго, але принаймні займає O (n * (2n)!) Пам'ять і O (n * log (n) * (2n)!) Час, де n - довжина вводу. (Тому не намагайтеся запускати його більш ніж з 5 цифр.)

f=.3 :0
>({~(i.>./)@:(((-:/:~)@(#$])*#)@>))<@".(' 0';' _1')rplc"1~(#~y-:"1' '-."#:~])(i.!2*#y)A.y,' '#~#y
)

Функція приймає вхід як рядок.

Приклади:

   f every '5423';'103';'1023'
  5 423
103   0
 10  23

Спосіб:

  • Додайте стільки ж пробілів до вводу, скільки їх довжина.
  • Перетворюйте його всіма можливими способами.
  • Перевірте, чи простір без простору такий, як вхідний (тобто це його розділ).
  • Замініть "0" на "_1", щоб визнати недійсними провідні нульові рішення.
  • Оцініть кожен рядок.
  • Знайдіть найдовший список, який також відсортований. Це повернене значення.

0

Haskell, 161 байт

(#)=map
f[x]=[[[x]]]
f(h:t)=([h]:)#f t++(\(a:b)->(h:a):b)#f t
g l=snd$maximum[(length x,x::[Int])|x<-[read#y|y<-f l,all((/='0').head)y],and$zipWith(>=)=<<tail$x]

Пробіг:

*Main> mapM_ (print . g) ["123456","345823","12345678901234567890","102","302","324142","324142434445","1356531","11121111111","100202003"]
[1,2,3,4,5,6]
[3,4,5,8,23]
[1,2,3,4,5,6,7,8,90,123,456,7890]
[102]
[302]
[32,41,42]
[32,41,42,43,44,45]
[1,3,5,6,531]
[1,1,1,2,11,11,111]
[100,202003]

Як це працює: хелперна функція fрозбиває список вхідних даних на всі можливі списки списків. gспочатку відкидає тих, хто починається з підспілу, 0а потім - без відповідного порядку. З’єднайте кожен список, що залишився, з його довжиною, візьміть максимум і знову відмовтеся від частини довжини.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.