Faça uma sequência

12

Uma sequência de números inteiros é uma sequência se a diferença entre dois números consecutivos nessa sequência for -1 ou 1 e seu primeiro elemento for 0.

Mais precisamente: a1, a2, ..., an é uma sequência se:

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

Entrada

  • n - número de elementos na sequência
  • s - soma dos elementos na sequência

Resultado

  • um conjunto / lista / matriz / etc de uma sequência de comprimento ncom a soma dos elementos s, se possível
  • um conjunto / lista / matriz / etc vazio, se não for possível

Exemplos

Para entrada 8 4, a saída pode ser [0 1 2 1 0 -1 0 1]ou [0 -1 0 1 0 1 2 1]. Pode haver outras possibilidades.

Para entrada 3 5, a saída está vazia [], pois não pode ser feita.

Regras

Este é um código de golfe, a resposta mais curta em bytes ganha. As submissões devem ser um programa ou função. A entrada / saída pode ser fornecida de qualquer uma das maneiras padrão .

typedef
fonte
A propósito, tenho uma prova de que todos os números representáveis ​​como uma sequência de comprimento l são todos os números entre (l-1)*l/2e -(l-1)*l/2que têm a mesma paridade que (l-1)*l/2.
haskeller orgulhoso
isso pode ser usado para fazer um algoritmo eficiente (S (n)) para fazer uma desejada uma sequência
haskeller orgulhoso

Respostas:

7

CJam, 56 47 44 34 bytes

Muitas possibilidades de aprimoramento aqui, mas aqui está a primeira tentativa:

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

Créditos a Dennis pela maneira eficiente de fazer a { ... }%peça.

Imprime a representação do array, se possível, caso contrário ""

Experimente online aqui

Optimizer
fonte
Estou confuso: a {}%parte do seu código não se parece nada com o meu (que é apenas o código de @ PeterTaylor, substituindo pontos por sublinhados). Se eu contribuiu nada ao seu código, é o {}=operador ...
Dennis
Inicialmente, eu tinha o _{_W=)+}%\{_W=(+}%+que estava primeiro fazendo duas cópias, adicionando 1 à primeira, subtraindo 1 da outra. Seu exemplo me fez descobrir como fazer isso em um único { ... }%bloco. Quanto a isso { ... }=, eu já o havia reduzido muito em minhas experiências, embora ainda não tenha sido publicado.
Optimizer
Eu entendo a partir da pergunta que a entrada dada 3 5a saída deve ser []e não""
Peter Taylor
1
@PeterTaylor "um vazio conjunto / lista / array / etc se não for possível" - Então eu acho que eu só tenho que deixar claro ...
Optimizer
Além disso, []pno CJam apenas gera "". Então é assim que a linguagem representa matrizes vazias.
Optimizer
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

Não há necessidade de força bruta ou enumeração de todas as tuplas.

Veja uma sequência de comprimento n como n -1 etapas, cada etapa sendo incrementada ou decrescente.
Observe que você só pode trocar um incremento por um decremento, a soma varia de 2; portanto, para qualquer comprimento determinado, a soma é sempre par ou sempre ímpar.
Tendo todos os incrementos, a sequência é 0, 1, 2, 3, ..., n-1 e sabemos que a soma é (n-1) * n / 2
Alterando o último passo, a soma muda em 2, então a o último passo pesa 2.
Alterando o próximo para o último passo, a soma muda em 4, então o último passo pesa 4. Isso ocorre porque o passo sucessivo se baseia na soma parcial até agora.
Alterando a etapa anterior, a soma muda em 6, então a última etapa pesa 6 (não 8, não são números binários).
...
Alterar o primeiro passo 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 ungolfed

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
}

Teste no console Firefox / FireBug

F(8,4)

Resultado

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

GolfScript ( 41 39 bytes)

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

Demonstração online

Agradecimentos a Dennis por 41-> 39.

Peter Taylor
fonte
Você pode reduzir ,0=para ?. Uma porta direta para CJam seria 5 bytes mais curta:L1,al~:S;({{_W=(+_)))+}%}*{:+S=}=p
Dennis
@Dennis oooh, essa é uma maneira prática de percorrer dois {}% de blocos. Se importa se eu usá-lo?
Optimizer
@ Otimizador: Eu não, mas não é realmente o meu trabalho.
Dennis
Eu estava falando sobre o { ... }%bloco. No meu código, eu tinha dois, estava tentando reduzi-lo para 1. Como foi o algoritmo real, acho que Peter e eu postamos o mesmo algoritmo quase ao mesmo tempo.
Optimizer
3

Mathematica, 73 bytes

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

Solução simples de força bruta.

Estou gerando todas as opções de etapas. Então eu as transformo em listas acumuladas para obter as seqüências únicas. E então eu estou procurando o primeiro cuja soma é igual ao segundo parâmetro. Se não houver, o valor padrão é {}.

Martin Ender
fonte
O Mathematica apenas brilha em problemas relacionados à matemática / combinação, não é? ;)
Otimizador
@Optimizer Tenho certeza que o CJam vai vencê-lo, no entanto. ;) Na verdade, esse mesmo algoritmo não deve ser difícil de executar no CJam.
Martin Ender
1
Definitivamente, será melhor, mas apenas por causa dos nomes curtos dos métodos. O algoritmo não será tão simples.
Optimizer
@Optimizer, não é? Eu acho que é mais direto com um loop e filtro simples do que essa composição de função.
Peter Taylor
3

Haskell, 56 bytes

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

Explicação:

  • Crie uma lista com as permutações 1,-1e comprimento n-1: replicateM n-1[-1,1]
    Exemplo: replicateM 2 [-1,1]==[[-1,-1],[-1,1],[1,-1],[1,1]]
  • Crie a sequência única a partir dela. scanltem um desempenho ruim, mas faz o trabalho certo aqui.
  • Filtre todas as sequências únicas possíveis com o comprimento em nque a soma és
Johannes Kuhn
fonte
1
Uma melhoria simples é alterar a para uma função infix. aqui está uma dica para uma melhoria mais não intuitiva: importar Control.Monadapenas para uso replicateMque já é muito longo. que outra função monádica você pode usar para simular replicateM?
proud haskeller
a propósito, você deve retornar apenas uma solução e adicionar head$à sua solução.
proud haskeller
headnão retorna []para [] :: [[a]]- e eu odeio erros.
Johannes Kuhn
1
porque já passou algum tempo, vou lhe dizer o que eu quis dizer. Você poderia usar em mapM(\x->[1,-1])[2..n]vez de sequencee replicate.
proud haskeller
Interessante. Isso é ainda mais curto: P
Johannes Kuhn
2

Python, 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
fonte
0

CJam, 65 58 54 bytes

Pouco mais curto que minha solução Mathematica, mas a culpa é minha por ainda não usar o CJam corretamente:

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

É literalmente o mesmo algoritmo: obter todos os n-1-tuplos de {1, -1}. Encontre o primeiro cuja acumulação é igual a s, acrescente a 0. Imprima uma matriz vazia se nenhuma for encontrada.

Martin Ender
fonte
0

CJam, 40

Outra abordagem no CJam.

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

Rubi (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
fonte
0

J, 47 caracteres

Verifica cada sequência como muitas outras respostas. Tentará fazer uma solução O (n) mais curta.

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

   8 f 4
0 1 2 1 0 1 0 _1

   3 f 5
[nothing]
randomra
fonte
0

APL 38

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

Exemplo:

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

Este, como muitos outros, apenas força bruta em todas as combinações para encontrar uma que combine, se não for encontrada, não retorna nada. Na verdade, ele tenta algumas combinações mais de uma vez para diminuir o código.

Moris Zucca
fonte