Сортированный лексический раздел номера

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)
Jakube
источник
Вы можете использовать aYвместо~Y]
FryAmTheEggman
@FryAmTheEggman Я всегда забываю a. Не знаю почему.
Якуб
@Jakube Может быть, потому что это не в документах?
Sp3000
У меня было решение для ~ 45 символов. Я не знал о том, int("01")что это ошибка в Pyth (этого не происходит в Python).
orlp
3
@Jakube хаха, хотя кажется логичным, но обычно nэто длина ввода.
Оптимизатор
6

Mathematica, 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}}}
    

    Обратите внимание, что a) все последовательные разделы расположены в правильном порядке, и b) разделы отсортированы от самого грубого до самого прекрасного.

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

Python 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")и возвращает список целых.

Sp3000
источник
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
PurkkaKoodari
источник
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», чтобы аннулировать лидирующие нулевые решения.
  • Оцените каждую строку.
  • Найдите самый длинный список, который также отсортирован. Это возвращаемое значение.
randomra
источник
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а затем те, у которых нет правильного порядка. Соедините каждый оставшийся список с его длиной, возьмите максимум и снова отбросьте часть длины.

Ними
источник