¿Cuántos números consecutivos descendentes en mi número?

18

Llegó el 2019 y probablemente todos hayan notado la peculiaridad de este número: de hecho, está compuesto por dos subnúmeros (20 y 19) que representan una secuencia de números descendentes consecutivos.

Desafío

Dado un número x, devuelve la longitud de la secuencia máxima de números consecutivos y descendentes que se pueden formar tomando subnúmeros de x.

Notas:

  • sub-números no pueden contener ceros a la izquierda (por ejemplo, 1009no se puede dividir en 10, 09)
  • consecutiva y descendente significa que un número en la secuencia debe ser igual al número anterior -1, o (por ejemplo , no se puede dividir en y porque no son consecutivos )norteyo+1=norteyo-1525,2522 ≠ 5 - 1
  • la secuencia debe ser obtenido utilizando el número completo, por ejemplo, en 7321que no se puede descartar 7y obtener la secuencia 3, 2,1
  • sólo una secuencia puede obtenerse a partir del número, por ejemplo, 3211098no se puede dividir en dos secuencias 3, 2, 1y 10, 9,8

Entrada

  • Un número entero ( >= 0): puede ser un número, una cadena o una lista de dígitos

Salida

  • Un número entero dado el número máximo de sub-números decrecientes (tenga en cuenta que el límite inferior de este número es 1, es decir, un número está compuesto por sí mismo en una secuencia descendente de longitud uno)

Ejemplos:

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

Reglas generales:

  • Este es el , por lo que la respuesta más corta en bytes gana.
    No permita que los lenguajes de código de golf lo desalienten de publicar respuestas con idiomas que no sean de código. Trate de encontrar una respuesta lo más breve posible para 'cualquier' lenguaje de programación.
  • Las reglas estándar se aplican a su respuesta con las reglas de E / S predeterminadas , por lo que puede usar STDIN / STDOUT, funciones / método con los parámetros adecuados y programas completos de tipo retorno. Tu llamada.
  • Las lagunas predeterminadas están prohibidas.
  • Si es posible, agregue un enlace con una prueba para su código (es decir, TIO ).
  • Además, se recomienda agregar una explicación para su respuesta.
digEmAll
fuente
1
¿Está 210 -> 2,1,0mal el caso de prueba (lo mismo con 0 -> 0)? La tarea dice "los subnúmeros no pueden contener ceros a la izquierda ", ¿es cero un caso especial?
ბიმო
2
@BMO: bueno, aquí el tema es un poco filosófico ...: D para mí, 0 es un número sin cero
inicial
2
¿llamarías a estos ... números condescendientes ? xD lo siento, eso no fue divertido
HyperNeutrino
Lo sentimos, eliminé mi comentario en el que pregunté 212019. Parece que no leí todas las reglas.
ciclaminista

Respuestas:

6

Jalea ,  15  9 bytes

Bugfix gracias a Dennis

ŻṚẆDfŒṖẈṀ

Pruébalo en línea! (incluso321toma medio minuto ya que el código es al menosO(norte2) )

¿Cómo?

ŻṚẆ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
Jonathan Allan
fuente
6

JavaScript (ES6), 56 bytes

Un puerto de respuesta Python de ArBo es significativamente más corto. Sin embargo, falla en algunos casos de prueba debido a demasiada recursividad.

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

Pruébalo en línea!


JavaScript (ES6), 66 bytes

Toma la entrada como una cadena.

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++])

Pruébalo en línea!

Comentado

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
Arnauld
fuente
54 bytes implementando los cambios en mi código
ArBo
5

Perl 6 , 43 41 40 bytes

-1 byte gracias a nwellnhof

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

Pruébalo en línea!

Solución basada en expresiones regulares. Estoy tratando de encontrar una mejor manera de hacer coincidir una lista descendente, pero Perl 6 no hace bien las particiones

Explicación:

{                                        }  # 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
Jo King
fuente
40 bytes
nwellnhof
4

Python 3 , 232 228 187 181 180 150 149 bytes

-1 gracias a @ 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])])

Pruébalo en línea!

Código inicial sin golf:

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
Nishioka
fuente
1
s+1 forpuede ser s+1for, (t(n[:j])-t(n[j:j+i])==1)*t(n[0])posiblemente puede ser t(n[:j])-t(n[j:j+i])==1>=t(n[0]).
Jonathan Frech
Parece que la segunda sugerencia no funciona aunque no traería nada porque entonces necesitas espacio para separar la expresión if.
Nishioka
Es cierto ... alternativa 149 .
Jonathan Frech
4

Python 2 , 78 74 73 bytes

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)

Pruébalo en línea!

-1 byte gracias a Arnauld

Toma la entrada como una cadena. El programa se ejecuta rápidamente en el límite de profundidad de recursión de Python, pero puede finalizar la mayoría de los casos de prueba.

Cómo funciona

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
ArBo
fuente
1
¡Buena respuesta! a+c+1se puede acortar a a-~c.
Arnauld
3

05AB1E , 10 bytes

ÝRŒʒJQ}€gà

Extremadamente lento, por lo que el siguiente TIO solo funciona para casos de prueba por debajo de 750 ..

Pruébalo en línea .

Explicación:

Ý           # 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
Kevin Cruijssen
fuente
2
Golf de código: donde agregar 1 byte a su programa para pasar n!a n lg nsimplemente no vale la pena.
corsiKa
3

Pyth, 16 bytes

lef!.EhM.+vMT./z

Pruébelo en línea aquí , o verifique todos los casos de prueba a la vez aquí .

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
Sok
fuente
3

Jalea , 11 bytes

ŒṖḌ’Dɗ\ƑƇẈṀ

O(norte0,3)

Pruébalo en línea!

Cómo funciona

ŒṖḌ’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.
Dennis
fuente
3

Carbón , 26 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

F⊕Lθ

Bucle ide 0 a la longitud de la entrada.

F⊕Lθ

Bucle kde 0 a la longitud de la entrada.

⊞υ⭆κ⁻I…θ⊕ιλ

Calcule los primeros knúmeros en la secuencia descendente comenzando por el número dado por los primeros idígitos de la entrada, concatenelos y acumule cada cadena resultante en la lista vacía predefinida.

I﹪⌕υθ⊕Lθ

Encuentre la posición de la primera copia coincidente de la entrada y reduzca el módulo 1 más que la longitud de la entrada.

Ejemplo: para una entrada de 2019las siguientes cadenas se generan:

 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 luego se encuentra en el índice 12, que se reduce el módulo 5 para dar 2, la respuesta deseada.

Neil
fuente
3

Haskell, 87 bytes

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

La entrada es una lista de dígitos.

Pruébalo en línea!

La función #crea una lista de todas las divisiones posibles al observar ambas

  • anteponer el número actual aa todas las divisiones devueltas por una llamada recursiva con el resto de la entrada ( x<-b#c), pero solo si el siguiente número no es cero ( b>0) (o es el último número en la entrada ( c==[])) y aes uno mayor que el primero número de la división anterior respectiva x( a==x!!0+1).

y

  • agregar el siguiente dígito bde la lista de entrada al número actual ay continuar con el resto de la entrada ( (10*a+b)#c)

El caso base es cuando la lista de entrada está vacía (es decir, no coincide con el patrón (b:c)). La recursión comienza con el número actual asiendo 0( (0#)), que nunca llega a la primera rama ( aantes de todas las divisiones anteriores), porque nunca será mayor que cualquier número de divisiones.

Toma la longitud de cada división y encuentra el máximo ( maximum.map length).

Una variante con también 87 bytes:

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

que básicamente funciona de la misma manera, pero en lugar de mantener toda la división en una lista, solo mantiene un par (r,x)de la longitud de la división ry el primer número en la división x.

nimi
fuente
3

Python 3 , 302 282 271 bytes

-10 bytes gracias al consejo de @ElPedro.

Toma la entrada como una cadena. Básicamente, se necesitan segmentos cada vez mayores del número desde la izquierda, y ve si para ese segmento del número se puede formar una secuencia utilizando todos los números.

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

Pruébalo en línea!

Neil A.
fuente
1
Como está usando range3 veces, puede definir R=rangefuera de ambas funciones y luego usar en R(whatever)lugar de range(whatever)guardar 4 bytes.
ElPedro
3

Japt , 27 bytes

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

Pruébalo en línea! o marque la mayoría de los casos de prueba

Esto no tiene un buen puntaje, pero utiliza un método único y puede haber espacio para jugarlo mucho más. También funciona lo suficientemente bien como para que todos los casos de prueba que 201200199198no sean eviten el tiempo de espera.

Explicación:

ò                              #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
Kamil Drakari
fuente
Creo que esto funciona para el 27.
Shaggy
25 bytes
Shaggy
@Shaggy ambos fallan en la entrada 21201porque no imponen que el final de la secuencia se alinee correctamente (de mi versión original la línea "termina con una coma"). Esta o esta alternativa funciona.
Kamil Drakari
Ah ok. En ese caso: 26 bytes
Shaggy
@Shaggy That y las soluciones de 28 bytes que fallé 210porque no hay un delimitador después de 0. Aquí hay un byte fijo de 28 bytes que funciona.
Kamil Drakari
2

Haskell, 65 bytes

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

La entrada es una cadena.

Pruébalo en línea!

Completamente diferente a mi otra respuesta . Una fuerza bruta simple que prueba todas las listas de números descendentes consecutivos hasta encontrar una que sea igual a la lista de entrada.

Si limitamos el número de entrada de enteros de 64 bits, podemos ahorrar 6 bytes haciendo un bucle ya través [1..19], ya que el mayor entero de 64 bits tiene 19 dígitos y no hay necesidad de listas de prueba con más elementos.

Haskell, 59 bytes

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

Pruébalo en línea!

nimi
fuente
2

Python 2 , 95 bytes

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`)

Otra solución lenta de fuerza bruta.

Pruébalo en línea!

Dennis
fuente
2

Dyalog APL, 138 bytes

Un poco bocado, pero también funciona rápido para grandes números. Si lo prueba en línea , ponga el prefijo dfn en ⎕←y proporcione la entrada a la derecha como una lista de dígitos.

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

Explicación

Primero, el dfn interno a la derecha que construye recursivamente una lista de posibles formas de particionar (con ) la lista de dígitos. Por ejemplo, 1 0 1 0 ⊂ 2 0 1 9devuelve el vector anidado (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.

Usamos 1,para agregar una columna de 1s al comienzo y terminar con una matriz de particiones válidas para ⍵.

Ahora la función se entrena a la izquierda en parens. Debido al argumento izquierdo para el tren es la fila de la matriz de particiones y el argumento derecho es la entrada del usuario. El tren es un montón de horquillas con una cima como el diente izquierdo.

((≢⊂)×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.

Si la partición crea una secuencia de números descendentes, el tren devuelve la longitud de la secuencia. De lo contrario cero.

⍤1⊢aplica el tren de funciones entre la entrada del usuario y cada fila de la matriz de particiones, devolviendo un valor para cada fila de la matriz. es necesario desambiguar entre operando y argumento a la función derivada de .

⌈/ encuentra el máximo.

Podría encontrar un algoritmo más corto, pero quería probar de esta manera, que es lo más directo y declarativo que se me ocurre.

akhmorn
fuente
Bienvenido a PPCG! ¡Esta es una impresionante primera publicación!
Rɪᴋᴇʀ
1

TSQL, 169 bytes

Nota: esto solo se puede ejecutar cuando la entrada se puede convertir a un entero.

SQL recursivo utilizado para bucle.

Golfizado:

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=@

Sin golf:

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=@

Pruébalo

t-clausen.dk
fuente
0

R , 101 bytes

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}

Pruébalo en línea!

Han pasado más de 2 semanas sin ninguna respuesta R, así que decidí publicar la mía :)

El código es bastante rápido ya que utiliza un enfoque de fuerza bruta "limitado"

Código desenrollado y explicación:

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
}
digEmAll
fuente