Haz una secuencia

12

Una secuencia de enteros es una secuencia si la diferencia entre dos números consecutivos en esta secuencia es -1 o 1 y su primer elemento es 0.

Más precisamente: a1, a2, ..., an es una secuencia si:

For any k (1 ≤  k < n): |a[k] - a[k+1]|=1, 
a[1]=0

Entrada

  • n - número de elementos en la secuencia
  • s - suma de elementos en la secuencia

Salida

  • un conjunto de una secuencia / lista / matriz / etc. de longitud ncon suma de elementos s, si es posible
  • un conjunto / lista / matriz / etc vacío si no es posible

Ejemplos

Para la entrada 8 4, la salida podría ser [0 1 2 1 0 -1 0 1]o [0 -1 0 1 0 1 2 1]. Puede haber otras posibilidades.

Para la entrada 3 5, la salida está vacía [], ya que no se puede hacer.

Reglas

Este es un código de golf, la respuesta más corta en bytes gana. Los envíos deben ser un programa o función. La entrada / salida se puede dar de cualquiera de las formas estándar .

typedef
fuente
Por cierto, tengo una prueba de que todos los números representables como una secuencia de longitud l son todos los números entre (l-1)*l/2y -(l-1)*l/2que tienen la misma paridad que (l-1)*l/2.
orgulloso Haskeller
esto se puede usar para hacer un algoritmo eficiente (O (n)) para hacer una secuencia deseada
orgulloso haskeller

Respuestas:

7

CJam, 56 47 44 34 bytes

Aquí hay muchas posibilidades de mejora, pero aquí va el primer intento:

L0aa{{[~_(]_)2++}%}l~:N;(*{:+N=}=p

Créditos a Dennis por la forma eficiente de hacer la { ... }%parte.

Imprime la representación de matriz si es posible, de lo contrario ""

Pruébalo en línea aquí

Optimizador
fuente
Estoy confundido: la {}%parte de su código no se parece en nada a la mía (que es solo el código de @ PeterTaylor, que reemplaza los puntos con guiones bajos). Si aporté algo a su código, es el {}=operador ...
Dennis
Inicialmente tenía _{_W=)+}%\{_W=(+}%+cuál estaba haciendo primero dos copias, agregué 1 a la primera, restando 1 de la otra. Su ejemplo me hizo descubrir cómo hacerlo en un { ... }%bloque. Con respecto a esto { ... }=, ya lo había reducido tanto en mi experimentación, aunque todavía no lo publiqué.
Optimizador
Entiendo por la pregunta que, dada la entrada, 3 5la salida debería ser []y no""
Peter Taylor
1
@PeterTaylor "un conjunto / lista / matriz / etc vacío si no es posible" - Así que creo que solo tengo que dejarlo claro ...
Optimizer
Además, []pen CJam solo sale a "". Entonces es cómo el lenguaje representa matrices vacías.
Optimizador
6

JavaScript (E6) 79 82

F=(n,t,
  d=n+n*~-n/4-t/2,
  l=1,
  q=[for(x of Array(n))d<n--?++l:(d+=~n,--l)]
)=>d?[]:q

No hay necesidad de fuerza bruta o enumeración de todas las tuplas.

Vea una secuencia de longitud n como n -1 pasos, cada paso es un incremento o decremento.
Tenga en cuenta que solo puede cambiar un incremento por una disminución, la suma varía en 2, por lo que para cualquier longitud dada la suma es siempre par o siempre impar.
Teniendo todos los incrementos, la secuencia es 0, 1, 2, 3, ..., n-1 y sabemos que la suma es (n-1) * n / 2
Cambiando el último paso, la suma cambia en 2, entonces el el último paso pesa 2.
Cambiando el penúltimo paso, la suma cambia en 4, por lo que el último paso pesa 4. Esto se debe a que el paso sucesivo se basa en la suma parcial hasta el momento.
Al cambiar el paso anterior, la suma cambia en 6, por lo que el último paso pesa 6 (no 8, no son números binarios).
...
Cambiar el primer paso pesa (n-1) * 2

Algoritmo

Find the max sum (all increments)  
Find the difference with the target sum (if it's not even, no solution)  
Seq[0] is 0  
For each step  
  Compare current difference with the step weight
  if is less 
     we have an increment here, seq[i] = seq[i-1]+1 
  else 
     we have a decrement here, seq[i] = seq[i-1]-1.  
     Subtract we current weight from the current diff.
If remaining diff == 0, solution is Seq[]. Else no solution

Código sin golf

F=(len,target)=>{
  max=(len-1)*len/2
  delta = max-target
  seq = [last=0]
  sum = 0
  weight=(len-1)*2
  while (--len > 0)
  {
    if (delta >= weight)
    {
      --last
      delta -= weight;
    }
    else
    {
      ++last
    }  
    sum += last
    seq.push(last);
    weight -= 2;
  }  
  if (delta) return [];
  console.log(sum) // to verify

  return seq
}

Prueba en la consola Firefox / FireBug

F(8,4)

Salida

[0, -1, 0, -1, 0, 1, 2, 3]
edc65
fuente
5

GolfScript ( 41 39 bytes)

[][1,]@~:^;({{.-1=(+.)))+}%}*{{+}*^=}?`

Demostración en línea

Gracias a Dennis por 41-> 39.

Peter Taylor
fuente
Puedes acortar ,0=a ?. Un puerto directo a CJam sería 5 bytes más corto:L1,al~:S;({{_W=(+_)))+}%}*{:+S=}=p
Dennis
@Dennis oooh, esa es una forma práctica de obtener dos {}% de bloques. ¿Te importa si lo uso?
Optimizador
@Optimizer: no, pero en realidad no es mi trabajo.
Dennis
Estaba hablando del { ... }%bloque. En mi código, tenía dos, estaba tratando de reducirlo a 1. Tal como está el algoritmo real, creo que tanto Peter como yo publicamos el mismo algoritmo casi al mismo tiempo.
Optimizador
3

Mathematica, 73 bytes

f=FirstCase[{0}~Join~Accumulate@#&/@Tuples[{-1,1},#-1],l_/;Tr@l==#2,{}]&;

Solución simple de fuerza bruta.

Estoy generando todas las opciones de pasos. Luego los convierto en listas acumuladas para obtener las secuencias de una. Y luego estoy buscando el primero cuya suma es igual al segundo parámetro. Si no existe, el valor predeterminado es {}.

Martin Ender
fuente
Mathematica simplemente se abre paso en problemas relacionados con las matemáticas / combinación, ¿no? ;)
Optimizador
@Optimizer Estoy seguro de que CJam lo superará sin embargo. ;) En realidad, este mismo algoritmo no debería ser difícil de hacer en CJam.
Martin Ender
1
Definitivamente lo superará, pero solo por los nombres cortos de los métodos. El algoritmo no será tan sencillo.
Optimizador
@ Optimizador, ¿eh? Creo que es más sencillo con un simple bucle y filtro que esta composición de funciones.
Peter Taylor
3

Haskell, 56 bytes

n%s=[x|x<-scanl(+)0`map`mapM(\_->[1,-1])[2..n],s==sum x]

Explicación:

  • Construya una lista con las permutaciones de 1,-1y longitud n-1: replicateM n-1[-1,1]
    Ejemplo: replicateM 2 [-1,1]==[[-1,-1],[-1,1],[1,-1],[1,1]]
  • Construye la secuencia de una de ellas. scanltiene un bajo rendimiento, pero hace el trabajo correcto aquí.
  • Filtra todas las secuencias de una posible con longitud ndonde la suma ess
Johannes Kuhn
fuente
1
Una mejora simple es cambiar a una función infija. Aquí hay una pista para una mejora más intuitiva: importar Control.Monadsolo por usar, replicateMque ya es demasiado largo. ¿Qué otra función monádica puedes usar para simular replicateM?
orgulloso Haskeller
por cierto, debe devolver solo una solución, por lo que debe agregar head$a su solución.
orgulloso Haskeller
headno regresa []por [] :: [[a]]- y odio los errores.
Johannes Kuhn el
1
porque ha pasado un tiempo, te diré lo que quise decir. Podrías usar en mapM(\x->[1,-1])[2..n]lugar de sequencey replicate.
orgulloso haskeller
Interesante. Eso es aún más corto: P
Johannes Kuhn
2

Pitón, 138

from itertools import*
def f(n,s):
 for i in[list(accumulate(x))for x in product([-1,1],repeat=n-1)]:
  if sum(i)==s:return[0]+i
 return[]
monopolo
fuente
0

CJam, 65 58 54 bytes

Apenas más corto que mi solución de Mathematica, pero eso es principalmente mi culpa por no seguir usando CJam correctamente:

0]]l~:S;({{_1+\W+}%}*{0\{+_}%);}%_{:+S=}#_@\i=\0>\[]?p

Es literalmente el mismo algoritmo: obtener todas las n-1tuplas de {1, -1}. Encuentre el primero cuya acumulación es la misma que s, anteponga a 0. Imprima una matriz vacía si no se encuentra ninguna.

Martin Ender
fuente
0

CJam, 40

Otro enfoque en CJam.

ri,W%)\_:+ri-\{2*:T1$>1{T-W}?2$+\}/])!*p
jimmy23013
fuente
0

Rubí (136)

def one_sequences(n)
  n.to_s.chars.map(&:to_i).each_cons(2).to_a.select{|x|x[0] == 0 && (x[1] == 1 || x[1]
  == -1)}.count
end
Johnson
fuente
0

J, 47 caracteres

Comprueba cada secuencia como muchas otras respuestas. Intentará hacer una solución de O (n) más corta.

   f=.4 :'(<:@#}.])(|:#~y=+/)+/\0,|:<:2*#:i.2^<:x'

   8 f 4
0 1 2 1 0 1 0 _1

   3 f 5
[nothing]
randomra
fuente
0

APL 38

{⊃(↓a⌿⍨⍺=+/a←+\0,⍉1↓¯1*(⍵⍴2)⊤⍳2*⍵),⊂⍬}

Ejemplo:

     4 {⊃(↓a⌿⍨⍺=+/a←+\0,⍉1↓¯1*(⍵⍴2)⊤⍳2*⍵),⊂⍬}8
0 1 2 1 0 1 0 ¯1

Este, como muchos otros, simplemente fuerza bruta a través de cada combinación para encontrar uno que coincida, si no se encuentra no devuelve nada. En realidad, intenta algunas combinaciones más de una vez para acortar el código.

Moris Zucca
fuente