Реконструюйте арифметичну послідовність


23

Враховуючи скінченну арифметичну послідовність натуральних чисел з деякими членами, вилученими з середини, реконструюйте всю послідовність.

Завдання

Розглянемо арифметичну послідовність: список натуральних чисел, у яких різниця між будь-якими двома послідовними елементами однакова.

2 5 8 11 14 17

Тепер припустимо, що одне або більше цілих чисел вилучається з послідовності з дотриманням наступних обмежень:

  • Вилучені цілі числа будуть послідовними умовами послідовності.
  • Перше і останнє цілі числа в послідовності не будуть видалені.
  • Принаймні три цілі числа залишаться в послідовності.

Для вищезазначеної послідовності можливі видалення включають:

2 5 8 14 17  (removed 11)
2 5 17       (removed 8 11 14)
2 14 17      (removed 5 8 11)

Ваше завдання: Давши одну з цих часткових послідовностей, реконструюйте початкову повну послідовність.

Деталі

Ви можете припустити, що введення є дійсним (має рішення) і не містить хоча б одного терміна. Всі числа в послідовності будуть додатними (> 0) цілими числами. Послідовність може мати позитивну або негативну різницю між термінами (тобто вона може збільшуватися або зменшуватися). Це не буде постійною послідовністю (наприклад 5 5 5).

Ваше рішення може бути повноцінною програмою або функцією . Будь-який із методів введення та виведення за замовчуванням є прийнятним.

Вхід і вихід можуть бути рядком (з будь-яким розумним роздільником), списком рядків або списком чисел. Ви можете представляти цифри в будь-якій базі, яка зручна для вашої мови.

Будь ласка, вкажіть будь-які незвичайні методи / формати вводу-виводу у форматі, щоб інші могли легше перевірити ваш код.

Тестові справи

In: 2 5 8 14 17
Out: 2 5 8 11 14 17
In: 2 5 17
Out: 2 5 8 11 14 17
In: 2 14 17
Out: 2 5 8 11 14 17
In: 21 9 6 3
Out: 21 18 15 12 9 6 3
In: 10 9 5
Out: 10 9 8 7 6 5
In: 1 10 91 100
Out: 1 10 19 28 37 46 55 64 73 82 91 100

Це ; найкоротша відповідь на кожній мові виграє.



Було б цікаво мати внесок у форму2 5 ... 17
— schnaader

Відповіді:


9

Хаскелл , 63 байти

f(a:b:c)|s<-[a,b..last c],all(`elem`s)c=s
f a=r$f$r a
r=reverse

Спробуйте в Інтернеті!

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

EDIT: дякую @xnor за вказівку на помилку та надання рішення!


5
Хоча це досить, здається, це не завжди працює: [1,3,4,5]дає [1,3,5].
— xnor

1
І я думаю, що all(`elem`s)cслід виправити це з тим же числом байтів.
— xnor

6

05AB1E , 9 8 байт

Ÿs¥¿Äô€н

Спробуйте в Інтернеті!

Пояснення

  • Побудуйте діапазон [перший, ..., останній] з різницею +/- 1
  • Обчисліть дельти введення
  • Отримайте абсолютне значення gcd дельт
  • Розбийте весь асортимент на шматки такого розміру
  • Отримайте перший елемент кожного шматка

Збережено 1 байт , використовуючи gcd of deltasзамість того min delta, натхненний user202729


5

Brachylog v2, 9 байт

⊆.s₂ᵇ-ᵐ=∧

Спробуйте в Інтернеті!

Це подання функції. Інтерпретатора Brachylog можна зробити так, щоб він оцінював функцію як би повну програму, надаючи її Zяк аргумент командного рядка; у цьому випадку введення задається у форматі, наприклад, [1, 2, 4]а вихід повертається у подібному форматі, наприклад Z = [1, 2, 3, 4]. (Звичайно, для подання функції введення та вихід взагалі не мають будь-якого формату; вони просто списки.)

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

Пояснення

Програма має три основні частини.

⊆знаходить надмірність вхідного сигналу (тобто послідовності, яка має вхід як підряд). Коли є більше одного можливого виводу з програми Brachylog, вибраний вихід є першим результатом у послідовності зв'язку, а порядок tiebreak визначається першою командою в програмі, яка має свою думку про це; у цьому випадку ⊆визначає порядок, який надає перевагу коротким результатам над довгими. Таким чином, результат, який ми отримаємо, буде найкоротшим наслідком введення, який підкоряється обмеженням у решті програми.

.… ∧Використовується для виведення значення, яке воно бачить як вхідне (тобто надлишок в даному випадку), але також стверджує, що певна умова має відношення до нього. Іншими словами, ми виводимо найкоротший наступ, який підкоряється певній умові (і ігноруючи будь-які проміжні результати, які використовуються для того, щоб побачити, чи він підкоряється умові).

Нарешті, у нас є s₂ᵇ-ᵐ =, тобто "всі дельти послідовності рівні", умова, яку ми застосовуємо до виводу. (Зворотне значення з цього - це перелік дельт, а не сам надмір, тому нам потрібен .…, ∧щоб забезпечити вихід правильної речі.)

Brachylog стримується тут, не маючи жодних вбудованих елементів, які могли б обчислювати дельти, застосовуючи операцію для перекриття пар зі списку тощо. Натомість ми маємо сказати, що ми маємо на увазі прямо: s₂ᵇзнаходить усі ( ᵇ) підрядки ( s) довжиною 2 ( ₂) (використання ᵇпотрібно, щоб підтримувати зв'язок між невідомими в підрядках та надлишком; чим частіше використовується, ᶠце порушить це посилання). Потім -ᵐробиться віднімання кожної з цих пар для отримання дельти. Прикро писати п’ять байтів s₂ᵇ-ᵐдля того, для чого вбудована більшість сучасних мов для гольфу, але, мабуть, саме так іде кодовий гольф.


4

Python 2, 104 97 89 83 71 67 60 байт

Завдяки Chas Brown за збереження 4 байтів.
Завдяки ovs за збереження 7 байт.

Введіть список аргументами.

lambda a,b,*c:range(a,c[-1],min(b-a,c[0]-b,key=abs))+[c[-1]]

Спробуйте в Інтернеті!

Пояснення:

Оскільки вилучені є послідовними, достатньо перевірити відмінності між двома парами послідовних елементів.


Ви можете зберегти 3 байти, замінивши b if b%c else cна [c,b][b%c>0].
— Chas Brown

@ChasBrown Спасибі, хоча незабаром я придумав кращий підхід.
— Колера Су

1
Приємно з key=abs! Здається, що в майбутньому люди часто опускають f=частину, якщо не використовується рекурсивна функція; щоб ви могли зберегти 2 байти таким чином.
— Час Браун

1
Також замініть a[-1]-a[-2]на a[2]-a[1]- логіка однакова, і ви отримаєте ще 2 байти.
— Час Браун


4

Pyth , 11 байт

%hS.+SQ}hQe

Спробуйте тут!

Дякую Стівену Х. за збереження байта!

Pyth , 12 байт

%.aiF.+Q}hQe

Спробуйте тут!

Як це працює

% .aiF. + Q} hQe ~ Повна програма.

     . + Q ~ Отримайте дельти.
   iF ~ Зменшити на GCD.
 .a ~ Абсолютне значення.
% ~ Модульний. Отримати кожен n-й елемент ...
        } ~ Інклюзивний числовий діапазон між ...
         hQ ~ Перший елемент, і ...
           e ~ Останній елемент.

Сортуйте, Qщоб ви могли сортувати та брати перший елемент замість того, abs(GCD(Q))як у %hS.+SQ}hQe11 байт. Тестовий набір
— Стівен Х.

3

Желе , 8 байт

ṂrṀmIg/$

Спробуйте в Інтернеті!

Примітки:

  • Працюйте лише над якоюсь старою версією Jelly. ( Це зробити , наприклад) (де gвикористання fractions.gcd, які мають результат знак такий же , як вхідний знак, замість того math.gcd, що завжди повертає позитивне значення).

  • Посилання TIO вище - це посилання Python 3 TIO, код Python складається з вихідного коду Jelly з комісії, про який я згадав вище, за винятком всього (3 файлу), упакованого в один і той же файл (для запуску TIO) і dictionary.pyбув зменшений до лише деякі рядки. Тим dictionary.pyне менш, не має відношення до цієї відповіді, оскільки в ній не використовується стислий рядок. ( “...»конструкція)

Пояснення:

По-перше, через те, що безперервний сегмент видалено і залишається щонайменше 3 елементи, у старому списку залишаються два послідовних числа, і дельти будуть кратними кроком. Тому список gcdрізниць (з Iприростом) буде абсолютним значенням кроку.

На щастя gcd, підписано (див. Примітку вище)

Отже програма:

ṂrṀ

Зростаючий цілий діапазон від Ṃінімату до Ṁосі.

m

Модульний, виберіть кожен n-й елемент.

Ig/$

Monadic ( $) ланцюговий комбінат I(збільшення, різниця) та g/(зменшення gcdнад елементами списку). Якщо прирости будуть позитивними, то значення gcdбуде позитивним, і список, що повертається, буде ліворуч праворуч (збільшується), і навпаки.


Так! Уражає відповідь 05AB1E на 1 байт!
— користувач202729

Використовуючи gcdзамість того, щоб minнас зв'язали. Шкода, я отримую gcd зі знаком, інакше я б о 7;)
— Emigna

3

MATL , 13 байт

1)0GdYkG0)3$:

Спробуйте в Інтернеті!

Пояснення:

Consider the example input [2 14 17]:
           # implicit input, STACK: [[2 14 17]]
1)         # push 1, index, STACK: [2]
0G         # push 0, duplicate input, STACK: [2, 0, [2 14 17]]
d          # take differences, STACK: [2, 0, [12, 3]]
Yk         # get value in [12, 3] nearest to 0, STACK: [2, 3]
G0)        # get last element in input, STACK: [2, 3, 17]
3$:        # 3-input :, computes 2:3:17, the range from 2 to 17 by 3
           # STACK: [[2 5 8 11 14 17]], implicit output.


3

JavaScript (ES6), 92 90

Відредагуйте 2 байти, збережені через Арнольд

Легко, оскільки досить перевірити відмінності між першими двома та останніми двома. Але все ще неймовірно довго.

s=>(e=(z=s.pop(a=s[0]))-s.pop(d=s[1]-a),[...Array((z-(a-=d=e*e>d*d?d:e))/d)].map(_=>a+=d))

Менше гольфу

s=>{
  a =s[0]
  b =s[1]
  z = s.pop()
  y = s.pop()
  d = b-a
  e = z-y
  d = e*e>d*d?d:e  
  n = (z-a)/d+1
  return [...Array(n)].map((_,i) => a + i*d)
}

Тест

var F=
s=>(e=(z=s.pop(a=s[0]))-s.pop(d=s[1]-a),[...Array((z-(a-=d=e*e>d*d?d:e))/d)].map(_=>a+=d))

var test=`In: 2 5 8 14 17 Out: 2 5 8 11 14 17
In: 2 5 17 Out: 2 5 8 11 14 17
In: 2 14 17 Out: 2 5 8 11 14 17
In: 21 9 6 3 Out: 21 18 15 12 9 6 3
In: 10 9 5 Out: 10 9 8 7 6 5
In: 1 10 91 100 Out: 1 10 19 28 37 46 55 64 73 82 91 100`.split`\n`
.map(r=>r.split`Out`.map(x=>x.match(/\d+/g)))

test.forEach(([i,k])=>{
  var o=F(i.slice(0))
  var ok = o+''==k
  console.log(ok?'OK':'KO',i+' => '+o)
})


a-=d=e*e>d*d?d:eмає працювати і зберігати 2 байти.
— Арнольд

@Arnauld це справді працює спасибі
— edc65

2

Мова Вольфрама (Mathematica) , 50 байт

Range[#&@@#,#[[-1]],#&@@Differences@#~SortBy~Abs]&

Спробуйте в Інтернеті!


Чи включає "список чисел" наявність чисел як окремих аргументів? Якщо так, то, схоже, ви можете зберегти гарну кількість байтів.
— numbermaniac

@numbermaniac Я так не думаю, оскільки не існує вбудованого, який отримує останні дані ...
— JungHwan Min

Ааа ... правда. Забули про це.
— numbermaniac

Ви можете використовувати {##}і , Last@{##}але краще , що я міг би отримати з цим було 51 байт.
— numbermaniac


1

Haskell , 73 69 байт

f(h:t)=do(#)<-[(-),(+)];[h,h#minimum(abs<$>zipWith(-)t(h:t))..last t]

Спробуйте в Інтернеті!


1
Я знайшов рішення в 63 байти, але воно сильно відрізняється від вашого. Чи варто робити окремий пост?
— користувач1472751

@ user1472751 Я не Laikoni, але цей сайт був призначений для конкуренції, а також співпраці. Тож я б опублікував це.
— H.PWiz

@ user1472751 Приємний підхід! Будь ласка, продовжуйте та публікуйте це як власну відповідь.
— Лайконі

1

J , 49, 47 46 байт

(0-[:<./2|@-/\]){.@[&]\({.<.{:)+[:i.{:(+*)@-{.

Натхненний рішенням Еміньї.

Як це працює:

 (0-[:<./2|@-/\]){.@[&]\({.<.{:)+[:i.{:(+*)@-{. - fork of 3 verbs

                        ({.<.{:)+[:i.{:(+*)@-{. - generates a list in the entire range of values
                                     {:     -{. - last minus first element  
                                       (+*)@    - adds the signum of the difference
                                 [:i.           - makes a list 
                       ({.<.{:)                 - the smallest of first and last elements                                     
                               +                - adds the offset to the list (translates all elements according to the first one)

 (0-[:<./2|@-/\])                               - finds the step
         2|@-/\]                                - the absolute differences between all consecutive elements
    [:<./                                       - the smallest one
  0-                                            - negate (for splitting)

                 {.@[&]\                        - splits the list from the right verb into left verb's result sublists and takes their first elements

Спробуйте в Інтернеті!


1

Лушпиння , 9 байт

m←C▼Ẋ≠⁰…⁰

Спробуйте в Інтернеті!

Велике спасибі H.PWiz, що вдвічі зменшив кількість байтів, вказавши, що застосування …у списку позначає його! ...


@ HP.Wiz X_X Я не знав, що Хеск перераховує такі діапазони ... Ви впевнені, що не хочете опублікувати його як свою окрему відповідь?
— Містер Xcoder

@ HP.Wiz Дякую, луо !
— Містер Xcoder

Також, можна F⌋замінити на ▼?
— H.PWiz

@ H.PWiz @ _ @ Чому це навіть працює?
— Містер Xcoder

Найменша (абсолютна) різниця буде початковою різницею. Єдиною причиною gcdбуло боротися з негативними дельтами
— H.PWiz

1

C # (.NET Core) , 167 + 13 = 180 145 + 13 = 158 байт

a=>{int x=a[1]-a[0],y=a[2]-a[1],d=x*x<y*y?x:y,s=Math.Abs((a[a.Length-1]-a[0])/d),i=0,j=a[0];var r=new int[s+1];for(;i<=s;j+=d)r[i++]=j;return r;}

Спробуйте в Інтернеті!

+13 для using System;

Дивно, але цей виклик мав більше нюансів, які я спочатку передбачав.

Подяка

-22 байти збережено через деякі акуратні спрощення від @DLosc.

DeGolfed

a=>{
    int x = a[1]-a[0],        // difference between first and second numbers
        y = a[2]-a[1],        // difference between second to last and last numbers
        d = x*x < y*y? x : y, // smallest absolute value difference
        s = Math.Abs((a[a.Length-1] - a[0]) / d), // number of steps in the reconstructed sequence (not the number of elements)
        i = 0,                // step position
        j = a[0];             // next number in reconstructed sequence

    var r = new int[s+1];

    // reconstruct the sequence
    for(; i <= s; j+=d)
        r[i++]=j;

    return r;
}





0

Japt , 12 байт

ÌõUg Uäa ñ g

Спробуй це


Пояснення

Створити масив цілих чисел ( õ) від останнього елемента вхідного масиву ( Ì) до першого ( Ug). Обчисліть крок між елементами, отримавши всі дві пари елементів з вхідних даних і зменшивши їх на абсолютну різницю ( Uäa), потім сортуючи ( ñ) цей масив і взявши перший елемент ( g).

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