Partizione lessicale ordinata di un numero


17

La sfida è davvero semplice: dato un numero, dividi le sue cifre in una matrice di numeri più piccoli in modo che i numeri risultanti non siano decrescenti. Il problema è che devi dividerlo in modo tale che la lunghezza dell'array sia massima.

Confuso?

  • Ti viene dato un numero intero positivo tramite STDIN (o l'alternativa più vicina), argomento della riga di comando o argomento della funzione in qualsiasi formato di input comodo e inequivocabile.
  • Devi suddividere le cifre decimali del numero in gruppi contigui e disgiunti.
  • L'array di numeri rappresentato da questi gruppi di cifre deve essere ordinato (nell'ordine consueto, non decrescente) senza riordinare i gruppi .
  • Nei casi in cui esiste più di una di queste partizioni, è necessario suddividere l'input nel maggior numero possibile. In caso di parità, restituire uno di questi risultati.
  • È possibile generare l'array su STDOUT (o l'alternativa più vicina) o come valore di ritorno della funzione. Nel caso di STDOUT (o alternativa più vicina), l'array deve essere stampato in qualsiasi formato di elenco comodo e inequivocabile.
  • I numeri di divisione non dovrebbero avere zero iniziali. Quindi, ad esempio, 1002003non può essere stampato come o [1, 002, 003]o [1, 2, 3]e l'unica risposta valida è [100, 2003].

Casi test:

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]

punteggio

Questo è code-golf, quindi vince il codice più breve in byte.

Risposte:


10

Pyth, 34

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

Provalo online qui . Nota, questo ha una complessità nel tempo (e nello spazio) di O (n). Pertanto, il test case 12345678901234567890richiede troppo tempo nel compilatore online. Usa invece quello offline (1 minuto sul mio laptop).

Questo è solo il mio primo tentativo. Potrebbe esserci qualche margine di miglioramento.

Innanzitutto alcune idee su come funziona il mio algoritmo.

  • Interpreto l'input come stringa e non come numero.
  • Quindi creo tutti i possibili sottoinsiemi di [0, 1, 2, ..., len(n-1)]
  • Per ciascuno di questi sottoinsiemi (prendiamo [1, 4, 5]), ho diviso la stringa di input in parte usando questi numeri. [input[0:1], input[1, 4], input[4,5], input[5,len(input)]].
  • Successivamente provo a convertire questi numeri in stringhe. Possono esserci due problemi. Pyth (o Python) genera un'eccezione per una stringa vuota e per una stringa di numeri che iniziano con 0. Quindi uso un try - catchblocco (in realtà un ciclo infinito con una pausa immediata). Se la conversione ha avuto esito positivo, aggiungo il risultato a un elenco Y.
  • Dopo aver gestito tutti i sottoinsiemi, filtrare l'elenco Yper i risultati, che sono già ordinati e stampare l'ultimo (l'ultimo ha il maggior numero di gruppi).

Ora la spiegazione dettagliata:

                            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)

Puoi usare aYinvece di~Y]
FryAmTheEggman il

@FryAmTheEggman Mi dimentico sempre a. Non so perché.
Jakube,

@Jakube Forse perché non è nei documenti?
Sp3000,

Ho avuto una soluzione per ~ 45 caratteri. Non ero a conoscenza del fatto che int("01")si tratta di un errore in Pyth (questo non accade in Python).
orlp

3
@Jakube haha, anche se sembra logico, ma generalmente nè la lunghezza dell'input.
Ottimizzatore

6

Mathematica, 134 127 byte

Questo è piuttosto inefficiente poiché genera molte più partizioni di quelle valide. Il 324142434445test case dura pochi secondi, ma non ci proverei 12345678901234567890.

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

Ciò definisce una funzione senza nome che accetta un numero intero e restituisce un elenco di numeri interi.

Spiegazione

L'ordine di lettura di questo codice è un po 'ovunque, quindi analizzerò nell'ordine in cui è destinato a essere letto (e valutato per la maggior parte):

  • d=IntegerDigits@#ottenere le cifre decimali dell'input e assegnare questo elenco a d.
  • SetPartitions(che richiede Needs@"Combinatorica`";) mi dà tutte le partizioni di questo. Tuttavia, restituisce molto più di quanto io voglia in realtà poiché tratta l'input come un set . Questo è ciò che lo rende inefficiente, ma lo sto usando perché il modo più breve che conosco per ottenere tutte le partizioni di elenco è molto più lungo. Ad esempio, se l'elenco fosse {1, 2, 3}la funzione ritornerebbe:

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

    Si noti che a) le partizioni consecutive sono tutte nell'ordine giusto eb) le partizioni sono ordinate dal più grossolano al più fine.

  • Select[...,...&] quindi filtra questo elenco dalla funzione anonima passata come secondo argomento.
    • Join @@ # == d verifica che in realtà abbiamo una partizione di elenco anziché una partizione set generale.
    • #~FreeQ~{0, __} controlla che nessuna partizione inizi con uno zero iniziale.
    • 0 <= ## & @@ f /@ #è un po 'più oscuro. Per prima cosa mappiamo FromDigitssu ciascun elenco nella partizione per recuperare i numeri rappresentati dalle cifre. Quindi applichiamo 0 <= ##quei numeri, dove si ##riferisce a tutti i numeri. Se la partizione è {1, 23, 45}quindi questa si espande 0 <= 1 <= 23 <= 45, quindi verifica che l'array sia ordinato.
  • Last@ poi mi dà l'ultima partizione rimasta dopo il filtro - questo funziona perché SetPartitions le partizioni sono già state ordinate, in modo che le migliori siano alla fine.
  • Infine, f/@recupera i numeri dagli elenchi delle cifre.

5

Python 3, 134 byte

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>""]

È un po 'disordinato, ma vabbè. Il programma genera ricorsivamente solo tutte le partizioni valide. La parte interessante è che per impedire lo zero iniziale, tutto ciò che era necessario era un ulterioreor "1">s[i:]>"" condizione .

Accetta input come f("12345678901234567890")e restituisce un elenco di ints.


4

Pyth, 62 61 60

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

Spiegazione

L'algoritmo funziona generando tutti i numeri binari tra 0(compreso) e 2^(n-1)(esclusivo), dove nè la lunghezza dell'input.

Le cifre binarie di ciascuna sono quindi mappate su un separatore ( N) per 1 e niente per 0.

Questi caratteri vengono quindi inseriti tra ciascun carattere di input e il risultato viene diviso per N , ottenendo un elenco.

I valori negli elenchi vengono quindi analizzati in numeri interi e gli elenchi vengono ordinati per lunghezza. Quindi non resta che filtrare quelli non ordinati e quelli che sono stati divisi agli zero iniziali, dopo di che viene selezionato l'elenco più lungo.

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

(NON COMPETING) Pyth, 25 byte

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

Provalo online!

Come funziona:

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 byte

Molto lungo ma occupa almeno O (n * (2n)!) Memoria e O (n * log (n) * (2n)!) Tempo in cui n è la lunghezza dell'ingresso. (Quindi non provare a eseguirlo con più di 5 cifre.)

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

La funzione accetta l'input come stringa.

Esempi:

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

Metodo:

  • Aggiungi lo stesso numero di spazi all'input della sua lunghezza.
  • Permettilo in ogni modo possibile.
  • Controlla se la stringa senza spazio è uguale all'input (ovvero è una sua partizione).
  • Sostituisci "da 0 a" _1 per invalidare le soluzioni zero iniziali.
  • Valuta ogni stringa.
  • Trova l'elenco più lungo che viene anche ordinato. Questo è il valore di ritorno.

0

Haskell, 161 byte

(#)=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]

Prova:

*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]

Come funziona: la funzione helper fsuddivide l'elenco di input in ogni possibile elenco di elenchi secondari. gprima scarta quelli con un elenco secondario che inizia con 0e poi quelli senza il giusto ordine. Associa ogni elenco rimanente alla sua lunghezza, prendi il massimo e scarta di nuovo la parte lunghezza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.