Encuentra el número que falta en una cadena no delimitada

19

El desafío es identificar el número que falta en una cadena de enteros no delimitados.

Se le da una cadena de dígitos (la entrada válida coincidirá con la expresión regular ^[1-9][0-9]+$). La cadena representa una secuencia de enteros. Por ejemplo, 1234567891011. Todos los números en la secuencia están en el rango de 1e 2147483647inclusive.

La secuencia es una serie de números donde cada número es uno mayor que su predecesor. Sin embargo, esta secuencia puede contener uno y solo un número faltante de la secuencia. Es posible que una cadena dada tampoco contenga números faltantes de la secuencia. La cadena siempre contendrá al menos dos números de la secuencia.

El código debe generar o devolver el valor faltante, o 0(esto es un 0- no un valor falso) en el caso de que no se hayan encontrado valores faltantes.

Las siguientes son entradas válidas y su salida / retorno:

input                         output    actual sequence (for refrence)
123467                        5         1 2 3 4 _ 6 7
911                           10        9 __ 11
123125126                     124       123 ___ 125 126
8632456863245786324598632460  8632458   8632456 8632457 _______ 8632459 8632460  
123                           0         1 2 3
8632456863245786324588632459  0         8632456 8632457 8632458 8632459  

Si bien todo esto se describe como una 'cadena' como entrada, si el lenguaje es capaz de manejar números arbitrariamente grandes ( dcy mathematica, los estoy mirando a ustedes dos), la entrada puede ser un número arbitrariamente grande en lugar de una cadena si eso hace El código más fácil.

Como referencia, esto se inspiró en la pregunta de Programmers.SE: Encuentra el número faltante en secuencia en la cadena

Comunidad
fuente
44
¿Estás seguro de que esto no es ambiguo?
Martin Ender
@ MartinBüttner Lo he pensado un poco y no he podido encontrar una situación en la que una secuencia que aumenta en 1 (que podría ser el problema) tenga una situación ambigua.
¿Hay una entrada en OEIS para la lista de enteros que son una secuencia concatenada que falta exactamente un elemento?
mbomb007
@ mbomb007 No lo creo, ya que hay infinitas listas diferentes. Y que esta es solo una cuerda grande. No estoy seguro de cómo lo definirías. Para el caso, una pregunta interesante de CS sería "cuál es el lenguaje que acepta todas estas cadenas". Ciertamente no es regular. Dudo que sea CF.
1
Hice la secuencia el tema de un desafío: codegolf.stackexchange.com/q/73513/34718
mbomb007

Respuestas:

5

Haskell, 115 112 bytes

g b|a<-[b!!0..last b]=last$0:[c|c<-a,b==filter(/=c)a]
maximum.map(g.map read.words.concat).mapM(\c->[[c],c:" "])

La primera línea es una definición de función auxiliar, la segunda es la función principal anónima. Verifique los casos de prueba (tuve que ejecutar pruebas más cortas debido a restricciones de tiempo).

Explicación

Esta es una solución de fuerza bruta: divida la cadena en palabras de todas las formas posibles, analice las palabras en enteros, vea si es un rango con un elemento faltante (devuelve ese elemento y, de lo 0contrario), y tome el máximo sobre todas las divisiones. La verificación de rango con elemento faltante se realiza en la función auxiliar g, que toma una lista by devuelve el único elemento en el rango [head of b..last of b]que no está b, o 0si no existe.

g b|                         -- Define g b
    a<-[b!!0..last b]=       -- (with a as the range [head of b..last of b]) as:
    last$0:[...]             --  the last element of this list, or 0 if it's empty:
            c|c<-a,          --   those elements c of a for which
            b==filter(/=c)a  --   removing c from a results in b.
mapM(\c->[[c],c:" "])        -- Main function: Replace each char c in input with "c" or "c "
map(...)                     -- For each resulting list of strings:
  g.map read.words.concat    --  concatenate, split at spaces, parse to list of ints, apply g
maximum                      -- Maximum of results (the missing element, if exists)
Zgarb
fuente
2

JavaScript (ES6), 117 bytes

s=>eval(`for(i=l=0;s[i];)for(n=s.slice(x=i=m=0,++l);s[i]&&!x|!m;x=s.slice(x?i:i+=(n+"").length).search(++n))m=x?n:m`)

Explicación

Enfoque bastante eficiente. Termina instantáneamente para todos los casos de prueba.

Obtiene cada subcadena desde el comienzo de la cadena de entrada como un número ny inicializa el número que falta ma 0. Luego elimina repetidamente ndesde el inicio de la cadena, incrementa ny busca la cadena. Si index of n != 0, lo comprueba m. Si m == 0, establece m = ny continúa, si no, faltan varios números, así que deja de verificar desde esta subcadena. Este proceso continúa hasta que se haya eliminado toda la cadena.

var solution =

s=>
  eval(`                     // use eval to use for loops without writing {} or return
    for(
      i=                     // i = index of next substring the check
      l=0;                   // l = length of initial substring n
      s[i];                  // if it completed successfully i would equal s.length
    )
      for(
        n=s.slice(           // n = current number to search for, initialise to subtring l
          x=                 // x = index of n relative to the end of the previous n
          i=                 // set i to the beginning of the string
          m=0,               // m = missing number, initialise to 0
          ++l                // increment initial substring length
        );
        s[i]&&               // stop if we have successfully reached the end of the string
        !x|!m;               // stop if there are multiple missing numbers
        x=                   // get index of ++n
          s.slice(           // search a substring that starts from the end of the previous
                             //     number so that we avoid matching numbers before here
            x?i:             // if the previous n was missing, don't increment i
            i+=(n+"").length // move i to the end of the previous number
          )
          .search(++n)       // increment n and search the substring for it's index
      )
        m=x?n:m              // if the previous number was missing, set m to it
  `)                         // implicit: return m
<input type="text" id="input" value="8632456863245786324598632460" />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>

usuario81655
fuente
2

JavaScript (ES6) 114

s=>eval("for(d=0,n=-9,z=s;z=z.slice((n+'').length);z.search(++n)?z.search(++n)?n=(z=s).slice(x=0,++d):x=n-1:0);x")  

Menos golf y explicado

f=s=>{
  d = 0  // initial digit number, will be increased to 1 at first loop 
  n = -9 // initial value, can not be found
  z = s  // initializa z to the whole input string
  // at each iteration, remove the first chars of z that are 'n' 
  // 'd' instead of 'length' would be shorter, but the length can change passing from 9 to 10 
  for(; z=z.slice((n+'').length); ) 
  {
    ++n; // n is the next number expected in sequence
    if (z.search(n) != 0)
    {
      // number not found at position 0
      // this could be the hole
      // try to find the next number
      ++n;
      if (z.search(n) != 0)
      {
        // nope, this is not the correct sequence, start again
        z = s; // start to look at the whole string again
        x = 0; // maybe I had a candidate result in xm but now must forget it
        ++d;   // try a sequence starting with a number with 1 more digit
        n = z.slice(0,d) // first number of sequence
      }
      else
      {
        // I found a hole, store a result in x but check the rest of the string
        x = n-1
      }
    }
  }      
  return x // if no hole found x is 0
}

Prueba

F=s=>eval("for(d=0,n=-9,z=s;z=z.slice((n+'').length);z.search(++n)?z.search(++n)?n=(z=s).slice(x=0,++d):x=n-1:0);x")

console.log=x=>O.textContent+=x+'\n'

elab=x=>console.log(x+' -> '+F(x))

function test(){ elab(I.value) }

;['123467','911','123125126','8632456863245786324598632460',
  '123','124125127','8632456863245786324588632459']
.forEach(t=>elab(t))
<input id=I><button  onclick='test()'>Try your sequence</button>
<pre id=O></pre>

edc65
fuente
2

C, 183 168 166 163 bytes

n,l,c,d,b[9];main(s,v,p)char**v,*p;{for(;s>1;)for(d=s=0,n=atoi(strncpy(b,p=v[1],++l)),p+=l;*p&&s<2;)p+=memcmp(p,b,c=sprintf(b,"%d",++n))?d=n,s++:c;printf("%d",d);}

Sin golf

n,l,c,d,b[9];

main(s,v,p)char**v,*p;
{
    /* Start at length 1, counting upwards, while we haven't
       found a proper number of missing numbers (0 or 1) */
    for(;s>1;)
        /* Start at the beginning of the string, convert the
           first l chars to an integer... */
        for(d=s=0,n=atoi(strncpy(b,p=v[1],++l)),p+=l;*p&&s<2;)
            /* If the next number is missing, then skip, otherwise
               move forward in the string.... */
            p+=memcmp(p,b,c=sprintf(b,"%d",++n))?d=n,s++:c;

    printf("%d",d); /* print the missing number */
}
Cole Cameron
fuente
2
¿Cómo funciona esto para entradas como 891112donde los números tienen diferentes longitudes?
Zgarb
@ Zgarb Funciona bien. La sprintfllamada devuelve la longitud del número faltante, independientemente de si es más largo que el anterior o no.
Cole Cameron
¡OK gracias! Tener un +1.
Zgarb