Складіть одну послідовність


12

Послідовність цілих чисел є однослідовою, якщо різниця між будь-якими двома послідовними числами в цій послідовності становить -1 або 1, а її перший елемент дорівнює 0.

Точніше: a1, a2, ..., an - це одна послідовність, якщо:

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

Вхідні дані

  • n - кількість елементів у послідовності
  • s - сума елементів у послідовності

Вихідні дані

  • односерійний набір / список / масив / тощо довжини nіз сумою елементів s, якщо це можливо
  • порожній набір / список / масив / тощо, якщо це неможливо

Приклади

Для введення 8 4, вихід може бути [0 1 2 1 0 -1 0 1]або [0 -1 0 1 0 1 2 1]. Можливі й інші можливості.

Для введення 3 5вихідний сигнал порожній [], оскільки його неможливо зробити.

Правила

Це кодовий гольф, найкоротша відповідь у виграші байтів. Подання повинні бути програмою або функцією. Введення / виведення можна надати будь-яким із стандартних способів .


До речі, у мене є доказ того, що всі числа, що представляються однією послідовністю довжини l, - це всі числа між якими (l-1)*l/2і -(l-1)*l/2мають однаковий паритет (l-1)*l/2.
гордий haskeller

це можна використати для створення ефективного алгоритму (O (n)), щоб скласти одну бажану послідовність
гордий haskeller

Відповіді:


7

CJam, 56 47 44 34 байт

Тут багато можливостей для вдосконалення, але тут робиться перша спроба цього:

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

Подяки Деннісу за ефективний спосіб виконувати { ... }%роль.

Якщо можливо, друкує представлення масиву, інакше ""

Спробуйте його онлайн тут


Мене бентежить: {}%частина вашого коду виглядає не так, як моя (це лише код @ PeterTaylor, замінюючи крапки підкресленнями). Якщо я щось доклав до вашого коду, це {}=оператор ...
Денніс

Я спочатку мав, _{_W=)+}%\{_W=(+}%+який спочатку робив дві копії, додав 1 до першого, віднімаючи 1 від іншого. Ваш приклад змусив мене зрозуміти, як це зробити в одному { ... }%блоці. Щодо цього { ... }=, я вже настільки скоротив його в експерименті, хоча ще не розміщений.
Оптимізатор

З питання я розумію, що з урахуванням вводу 3 5повинен бути вихід, []а ні""
Пітер Тейлор

1
@PeterTaylor "порожній набір / список / масив / тощо, якщо це неможливо" - Тож я думаю, що мені просто потрібно зробити це зрозумілим ...
Optimizer

Плюс []pв CJam просто виводить на "". Отже, як мова представляє порожні масиви.
Оптимізатор

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 як n -1 кроків, кожен крок - збільшення чи зменшення.
Зауважте, що ви можете поміняти розмір приросту лише для декременту, сума змінюється на 2, тому для будь-якої заданої довжини сума завжди парна або завжди непарна.
Маючи всі прирости, послідовність дорівнює 0, 1, 2, 3, ..., n-1, і ми знаємо, що сума дорівнює (n-1) * n / 2
Змінюючи останній крок, сума змінюється на 2, тому останній крок важить 2.
Змінюючи наступний на останній крок, сума змінюється на 4, тому останній крок важить 4. Це тому, що наступний крок будується на частковій сумі досі.
Змінюючи попередній крок, сума змінюється на 6, тому останній крок важить 6 (а не 8, це не двійкові числа).
...
Зміна першого кроку важить (n-1) * 2

Алгоритм

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

Невикористаний код

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
}

Тест у консолі Firefox / FireBug

F(8,4)

Вихідні дані

[0, -1, 0, -1, 0, 1, 2, 3]

5

GolfScript ( 41 39 байт)

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

Демонстрація в Інтернеті

Завдяки Деннісу за 41-> 39.


Можна скоротити ,0=до ?. Прямий порт до CJam був би на 5 байт коротшим:L1,al~:S;({{_W=(+_)))+}%}*{:+S=}=p
Денніс

@Dennis oooh, це зручний спосіб поїхати з двох {}% блоків. Розум, якщо я ним користуюся?
Оптимізатор

@Optimizer: Ні, але це не моя робота.
Денніс

Я говорив про { ... }%блок. У моєму коді у мене було два, намагався зменшити його до 1. Як і справжній алгоритм, я думаю, що ми з Петром розмістили той самий алгоритм майже в один і той же час.
Оптимізатор

3

Математика, 73 байти

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

Просте рішення грубої сили.

Я генерую всі варіанти кроків. Потім я перетворюю їх у накопичені списки, щоб отримати однопослідовності. І тоді я шукаю першого, сума якого дорівнює другому параметру. Якщо немає, значення за замовчуванням - {}.


Математика просто просвічує свої проблеми на математичні / комбінаційні проблеми, чи не так? ;)
Оптимізатор

@Optimizer Я впевнений, що CJam все ж переможе його. ;) Насправді цей самий алгоритм не повинен бути важким для виконання у CJam.
Мартін Ендер

1
Це, безумовно, переможе, але тільки через короткі назви методів. Алгоритм буде не таким прямим вперед.
Оптимізатор

@Optimizer, так? Я думаю, що це простіше простого циклу та фільтра, ніж ця функціональна композиція.
Пітер Тейлор

3

Haskell, 56 байт

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

Пояснення:

  • Створіть список із перестановками 1,-1та довжиною n-1: replicateM n-1[-1,1]
    Приклад: replicateM 2 [-1,1]==[[-1,-1],[-1,1],[1,-1],[1,1]]
  • Побудуйте одну послідовність із неї. scanlмає низьку продуктивність, але це робить правильну роботу тут.
  • Фільтруйте всі можливі одно послідовності з довжиною, nде сумаs

1
просте вдосконалення полягає у зміні функції на інфікс. ось натяк на більш неінтуїтивне вдосконалення: імпорт Control.Monadлише для використання, replicateMякий уже занадто довгий. яку ще монадичну функцію ви можете використовувати для імітації replicateM?
гордий haskeller

до речі, ви повинні повернути лише одне рішення, тож слід додати head$до свого рішення.
гордий haskeller

headне повертається []за [] :: [[a]]- і я ненавиджу помилки.
Йоганнес Кун

1
оскільки минув якийсь час, я скажу тобі, що я мав на увазі. Ви можете використовувати mapM(\x->[1,-1])[2..n]замість sequenceі replicate.
гордий haskeller

Цікаво. Це ще коротше: П
Йоганнес Кун

2

Пітона, 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[]

0

CJam, 65 58 54 байт

Ледь коротше, ніж моє рішення Mathematica, але я в основному винен, що все ще не використовую CJam належним чином:

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

Це буквально той самий алгоритм: отримати всі - n-1пари {1, -1}. Знайдіть першого, накопичення якого таке саме, як sі додати a 0. Роздрукуйте порожній масив, якщо його не знайдено.



0

Рубін (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

0

J, 47 символів

Перевіряє кожну послідовність, як і багато інших відповідей. Спробуємо зробити коротший O (n) рішення.

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

   8 f 4
0 1 2 1 0 1 0 _1

   3 f 5
[nothing]

0

APL 38

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

Приклад:

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

Цей, як і багато інших, просто грубить сили через кожну комбінацію, щоб знайти ту, яка відповідає, якщо не знайдена, нічого не повертає. Насправді він намагається деякі комбінації не один раз, щоб скоротити код.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.