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


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.