N-ті відмінності


26

У математиці один із способів з'ясувати, який тип заданого відношення (лінійне, квадратичне тощо) - це обчислення різниць. Для цього ви берете список значень y, для яких розрив між відповідними значеннями x є однаковим, і віднімаєте кожне з числа, що знаходиться над ним, створюючи список чисел на один коротший, ніж попередній. Якщо отриманий список повністю складається з однакових чисел, то співвідношення має різницю 1 (воно лінійне). Якщо вони не ідентичні, то ви повторите процес у новому списку. Якщо вони тепер однакові, відношення має різницю 2 (воно квадратичне). Якщо вони не ідентичні, ви просто продовжуєте цей процес, поки вони не стануть. Наприклад, якщо у вас є список значень y [1,6,15,28,45,66] для поступового збільшення значень x:

First Differences:

1
6   1-6  =-5
15  6-15 =-9
28  15-28=-13
45  28-45=-17
66  45-66=-21

Second differences:

-5 
-9  -5+9  =4
-13 -9+13 =4
-17 -13+17=4
-21 -17+21=4

As these results are identical, this relation has a difference of 2

Ваше завдання:

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

Вхід:

Масив цілих чисел, який може бути будь-якої довжини> 1.

Вихід:

Ціле число, що представляє різницю відношення, описаного вхідним сигналом.

Випробування:

Input                            => Output
[1,2,3,4,5,6,7,8,9,10]           => 1
[1,4,9,16,25,36]                 => 2
[1,2,1]                          => 2 (when there is only one value left, all values are automatically identical, so the largest difference an array can have is equal to the length of the array-1)
"Hello World"                    => undefined behavior (invalid input)
[1,1,1,1,1,1,1,1,1]              => 0 (all elements are already identical)
[1, 3, 9, 26, 66, 150, 313, 610] => 6

Оцінка:

Це , найнижча оцінка байтів на кожній мові виграє за цю мову. Найнижчий бал в цілому отримує зелену галочку.


Чи може введення бути "недійсним", як у, якщо введення НЕ відповідає відповідним специфікаціям, ми повинні помилитися? Надати -1 як вихід?
Чарівна восьминога урна

Поведінка не визначена для недійсного введення (мені все одно, що робить ваш код)
Грифон - Поновіть Моніку

Не повинен [1,2,1]дати 2? [1,2,1] -> [1,-1] -> [-2]
HyperNeutrino

@HyperNeutrino, так, вибачте. У мене там був мозок-пердець
Грифон - Відновлення Моніки

Додайте цей тестовий випадок [1,3,9,26,66,150,313,610]-> 6якщо вам подобається
J42161217

Відповіді:


10

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

Дякую Лео за те, що дозволив мені використовувати його версію, для якої працює[1,1,1,1,1,1]

←VE¡Ẋ-

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

Пояснення

   ¡     Repeatedly apply function, collecting results in a list
    Ẋ-     Differences
 VE      Get the index of the first place in the list where all the elements are equal
←        Decrement

2
Кожен раз, коли хтось сказав, що Хеск - це нове желе, вони були дуже пристойними. > _ <
Zacharý

Чорт, я збирався це опублікувати . Хороша робота, хоча, +1!
Лев

@Leo, тест я не бачив [1,1,1,1], чи можу я використовувати ваш?
H.PWiz

@ H.PWiz впевнений, продовжуй!
Лев

7

JavaScript (ES6), 47 байт

f=a=>-a.every(x=>i=!x)||1+f(a.map(n=>n-a[++i]))

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


7

MATL , 8 байт

`dta}x@q

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

Це поєднує послідовні відмінності повторно, поки результат не буде нульовим чи порожнім. Вихід - необхідна кількість ітерацій мінус 1.

`      % Do... while
  d    %   Consecutive diffferences. Takes input (implicitly) the first time
  t    %   Duplicate
  a    %   True if any element is nonzero. This is the loop condition
}      % Finally (execute before exiting the loop)
  x    %   Delete. This removes the array of all zeros
  @    %   Push iteration index
  q    %   Subtract 1. Implicitly display
       % End (implicit). Proceed with next iteration if top of the stack is true

7

R , 50 44 байт

function(l){while(any(l<-diff(l)))F=F+1
F*1}

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

Приймає diffз l, встановлює його l, і перевіряє , якщо результат містить значення , відмінні від нуля. Якщо це станеться, приріст F(инициализируется як FALSEнеявно), і повертається , F*1щоб перетворити FALSEв 0в тому випадку, якщо всі lідентично вже.


Повна програма і +Fтрюк на 5 байт . Акуратна відповідь btw!
JayCe

5

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

(s=#;t=0;While[!SameQ@@s,s=Differences@s;t++];t)&  

ніж @alephalpa на -6 байт і @hftf -1 байт

і ось ще один підхід від @hftf

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

Length@NestWhileList[Differences,#,!SameQ@@#&]-1&

(s=#;t=0;While[UnsameQ@@s,s=Differences@s;t++];t)&
алефальфа

1
UnsameQ[1,2,1]є помилковим; !SameQ[1,2,1]правда. Я не думаю, що ручний цикл також не зберігає символи: Length@NestWhileList[Differences,#,!SameQ@@#&]-1&це вже та ж довжина, що і ваша після заміни UnsameQна !SameQ.
hftf


4

Japt , 10 7 байт

è@=ä-)d

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

Покладається на те, що результат гарантовано знаходиться в межах довжини вхідного масиву.

Пояснення

è@=ä-)d     Implcit input of array U
 @          For each value in U...
  =ä-)      Update U to be equal to its subsections, each reduced by subtraction
      d     Check if any values in that are truthy
è           Count how many items in that mapping are true

На завершення це буде відображати масив
[1, 3, 9, 26, 66, 150, 313, 610]до [true, true, true, true, true, true, false, false],
який містить 6 trues.

Попередня версія 10 байт

@=ä-)e¥0}a

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


4

Perl 6 , 37 байт

{($_,{@(.[] Z- .[1..*])}...*.none)-2}

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

Пояснення: Функція приймає дані як один список. Потім він будує рекурсивну послідовність на зразок цієї: перший елемент є початковим списком ( $_), наступні елементи повертаються, {@(@$_ Z- .[1..*])}викликаючи попередній елемент, і це повторюється, поки умова *.noneне відповідає дійсності, що відбувається лише тоді, коли список є або порожній або містить лише нулі (або, технічно, інші значення фальси). Потім ми захоплюємо список і віднімаємо з нього 2, що примушує його спершу до числового контексту (а списки в числовому контексті дорівнюють кількості їх елементів) і, врешті-решт, повертає на 2 менше, ніж кількість елементів у список.

Дивний блок {@(@$_ Z- .[1..*])}просто приймає даний список ( .[]- так називається дзен-фрагмент - індексація з порожніми дужками дає весь список), створює його за допомогою оператора мінус ( Z-) з тим самим списком без першого елемента ( .[1..*]) і примушує його до списку ( @(...)- нам це потрібно, тому що zip повертає лише Seq, що в основному є одностороннім списком, який можна повторити лише один раз. Що нам не подобається.) І це все.


Зміна @(.[] Z- .[1..*])до [.[] Z-.[1..*]]необхідно зберегти два байта.
nwellnhof

4

Java 8, 191 + 58 = 249 198 140 байт.

Дякую PunPun1000 за 51 байт.
Дякую Невай за 58 байт.

int f(int[]a){int x=a.length-1,b[]=new int[x];for(;x-->0;)b[x]=a[x+1]-a[x];return java.util.Arrays.stream(a).distinct().count()<2?0:1+f(b);}

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

Спробуйте в Інтернеті (версія 198 байт)

Отже, це вперше я публікую тут повідомлення в PPCG (і вперше колись роблю виклик з кодом для гольфу). Будь-яка конструктивна критика вітається і цінується. Я намагався дотримуватися вказівок щодо публікації повідомлень, якщо щось не вірно, не соромтесь це вказати.

Прикрашена версія:

int f(int[] a) {
    int x = a.length - 1, b[] = new int[x];
    for (; x-- > 0;) {
        b[x] = a[x + 1] - a[x];
    }
    return java.util.Arrays.stream(a).distinct().count() < 2 ? 0 : 1 + f(b);
}

3
Ласкаво просимо на сайт!
DJMcMayhem

Замість того, щоб імпортувати ці модулі, ви можете просто використовуватиjava.util.stream.IntStream k = java.util.Arrays.stream(a);
PunPun1000

Насправді є кілька змін, які ви можете внести безкоштовно. 1) publicне потрібно включати в число байтів. 2) Ви не повинні приймати другий параметр, але його видалення фактично може зберегти байти. 3) ви можете зняти там непотрібні дужки
PunPun1000

4) Не є заставкою, але вам слід включити TIO, якщо можливо, ось приклад із цими пропозиціями на 198 байт TIO
PunPun1000


3

Haskell, 46 байт

g l|all(==l!!0)l=0|0<1=1+g(zipWith(-)l$tail l)

це просто повторюється - zipWith(-)l$last lце список різниць l. іg є функцією, яка відповідає на питання.


рекурсивне рішення було хорошим.
jferard

@jferard це дуже правда
гордий haskeller

3

Котлін , 77 байт

перший пост, 2 рази намагався редагувати останню відповідь на kotlin; D

{var z=it;while(z.any{it!=z[0]})z=z.zip(z.drop(1),{a,b->a-b});it.size-z.size}

взяв тестову частину від @jrtapsell

TryItOnline


Ласкаво просимо до PPCG! Гарна перша відповідь, перевершив теж.
H.PWiz

3

APL (Dyalog Classic) , 22 17 байт

{1=≢∪⍵:01+∇2-/⍵}

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

Дякуємо @ngn за 5 байт!

Як?

  • { ... }, функція
  • 1=≢∪⍵:0, якщо кожен аргумент рівний в аргументі, поверніться 0
  • 1+∇2-/⍵в іншому випадку поверніть 1 + nрізниці (це n-1, таким чином, додавши до нього одне дає n)

це коротше, якщо ви {1=≢∪⍵:0⋄1+∇2-/⍵}
жертвуєте хворобою

2

Желе , 7 байт

IÐĿEÐḟL

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

Пояснення

IÐĿEÐḟL  Main link
 ÐĿ      While results are unique (which is never so it stops at [])
I        Take the increments, collecting intermediate values # this computes all n-th differences
    Ðḟ   Filter out
   E     Lists that have all values equal (the first n-th difference list that is all equal will be removed and all difference lists after will be all 0s)
      L  Take the length (this is the number of iterations required before the differences become equal)

-1 байт завдяки Джонатану Аллану


1
@Gryphon Готово! :)
HyperNeutrino

IÐĿEÐḟLдля семи (я бачу, Майлз також знайшов сім із використанням рекурсії).
Джонатан Аллан

@JonathanAllan Чудова подяка!
HyperNeutrino


2

JavaScript (ES6), 58 байт

f=a=>+(b=a.slice(1).map((e,i)=>e-a[i])).some(e=>e)&&1+f(b)

+0, недостатньо Jquery: с. Дійсно, хоча, +1, приємна робота, я знаю, що ніколи не зможу гольфувати в JS.
Zacharý

2

Python 2 , 65 байт

-7 байт завдяки Джонатану Аллану.

f=lambda l,c=1:any(l)and f([j-i for i,j in zip(l,l[1:])],c-1)or-c

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


Зберегти байти Ініціювання cв 1, що зменшується , а потім з допомогою print-c.
Джонатан Аллан

Збережіть ще шість, перетворивши їх на рекурсивну функцію:f=lambda l,c=1:any(l)and f([j-i for i,j in zip(l,l[1:])],c-1)or-c
Джонатан Аллан

Це тільки я або перехід на рекурсивну лямбда не економить достатню кількість байтів? : P Дякую!
повністюлюдсько

Я думаю, для цього потрібно max(...,0)пройти [1, 1, 1, 1, ...]тестові приклади.
Yonatan N

2

Діалог APL, 19 байт

≢-1+(≢2-/⍣{1=≢∪⍵}⊢)

Пояснення:

≢                      length of input
 -1+(             )    minus 1+
     ≢                 length of
      2-/              differences between elements
         ⍣             while
          {1=≢∪⍵}      there is more than 1 unique element
                 ⊢     starting with the input

1
Це працює? ≢-1+∘≢2-/⍣{1=≢∪⍵}⊢
Zacharý

2

k , 21 байт

#1_(~&/1_=':)(1_-':)\

Це працює в k, але не в oK, тому що цикл oK під час запуску перед тим, як перевірити умову (на відміну від спочатку перевірки умови, а потім запуску коду). Тому в oK 1 1 1 1 1приклад не працюватиме належним чином.

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

Running the k example with 1 1 1 1 1 1 in the k interpreter.

Пояснення:

   (        )       \ /while(
    ~&/               /      not(min(
       1_=':          /              check equality of all pairs))) {
             (1_-':)  /    generate difference list
                      /    append to output }
#1_                   /(length of output) - 1

~&/1_=':->1<#?
ngn

2

Haskell , 66 61 60 байт

z=(=<<tail).zipWith
f=length.takeWhile(or.z(/=)).iterate(z(-))

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

Збережено 5 байт завдяки Крістіану Сіверсу

Збережено 1 байт завдяки гордості-haskeller

iterate(z(-)) обчислює списки відмінностей.

or.z(/=) тести, якщо в цих списках є нерівні елементи.

length.takeWhile підраховує списки відмінностей з нерівними елементами.


Я думаю, ви можете перевірити на нерівні елементи зor.z(/=)
Крістіан Сіверс

@ChristianSievers дякую! Це було очевидно, але я цього не бачив ...
jferard

Ви також можете використовувати z=(=<<tail).zipWithодин байт коротше
гордий haskeller

@proudhaskeller і більш елегантний, як завжди, з точки зору вільних визначень. Спасибі!
jferard


2

Japt , 7 байт

Той самий підхід (але незалежно виведений) як Джастін з іншою реалізацією.

£=äaÃèx

Перевірте це


Пояснення

Неявне введення масиву U.

£   Ã

Мапа над кожним елементом.

äa

Візьміть кожну послідовну пару ( ä) елементів у Uта зменшіть її на абсолютну різницю ( a).

=

Призначте цей масив до U.

èx

èПідраховуйте ( ) кількість підмасивів, які повертають трити (тобто не нульові) при зменшенні додаванням.


1

TI-Basic, 19 байт

While max(abs(ΔList(Ans
ΔList(Ans
IS>(A,9
End
A

За замовчуванням змінні починаються з нуля. Крім того, ніколи не думав, що буду використовувати IS>(щось корисне.


1

C # (.NET Core) , 70 69 + 18 байт

-1 байт завдяки Kevin Cruijssen

g=a=>i=>a.Distinct().Count()>1?g(a.Zip(a.Skip(1),(y,z)=>y-z))(i+1):i;

Потрібно вказати 0 при виклику, щоб правильно працювати. Також включено до кількості байтів:

using System.Linq;

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

Пояснення:

g = a => i =>                      // Function taking two arguments (collection of ints and an int)
    a.Distinct()                   // Filter to unique elements
    .Count() > 1 ?                 // If there's more than one element
        g(                         //     Then recursively call the function with
            a.Zip(                 //     Take the collection and perform an action on corresponding elements with another one
                a.Skip(1),         //         Take our collection starting at second element
                (y, z) => y - z    //         Perform the subtraction
            )
        )(i + 1)                   //     With added counter
        : i;                       // Otherwise return counter

Ітеративна версія 84 + 18 байт:

a=>{int i=0;for(;a.Distinct().Count()>1;i++)a=a.Zip(a.Skip(1),(y,z)=>y-z);return i;}

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


1
Ви можете видалити зайвий простір на (y,z)=>y-z. Але приємна відповідь, +1 від мене.
Кевін Кройсейсен

@KevinCruijssen дякую! Також, ой.
Grzegorz Puławski

1

Clojure, 62 байти

#(loop[c % i 0](if(apply = c)i(recur(map -(rest c)c)(inc i))))

Добре =можна взяти будь-яку кількість аргументів, і один аргумент ідентичний "самому". (apply = [1 2 3])виконується як (= 1 2 3).


Приємно, саме те, що я намагався зробити, але я боровся за компактний парний розріз. Це геніально, я мушу це пам’ятати на майбутнє.
MattPutnam

1

Pyth , 15 байт

W.E.+Q=.+Q=hZ)Z

Перевірте всі тестові випадки.

Як?

Пояснення №1

W.E.+Q=hZ=.+Q)Z   ~ Full program.

W                 ~ While...
 .E.+Q            ~ ... The deltas of Q contain a truthy element.
      =hZ         ~ Increment a variable Z, which has the initial value of 0.
         =        ~ Transform the variable to the result of a function applied to itself...
          .+Q     ~ ... Operate on the current list and deltas.
             )Z   ~ Close the loop and output Z.

-1 байтWtl{Q=hZ=.+Q)Z
Дейв

Ще краще @ Dave: WP{Q=hZ=.+Q)Z. Спасибі!
Містер Xcoder



0

Pyth, 10 байт

tf!t{.+FQt

Якщо ми можемо індексувати від 1, ми можемо зберегти байт, видаливши ведучий t.

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

Пояснення

tf!t{.+FQt
 f        T  Find the first (1-indexed) value T...
     .+FQt   ... such that taking the difference T - 1 times...
  !t{        ... gives a set with more than one value in it.
t            0-index.

0

Котлін , 83 байти

{var z=it
var c=0
while(z.any{it!=z[0]}){c++
z=(0..z.size-2).map{z[it+1]-z[it]}}
c}

Прикрасили

{
    // Make input mutable
    var z=it
    // Count for returning
    var c=0
    // While the array is not identical
    while (z.any { it != z[0] }) {
        // Increment count
        c++
        // Update list to differences
        z = (0..z.size-2).map { z[it+1] - z[it] }
    }
    // Return count
    c
}

Тест

var n:(List<Int>)->Int =
{var z=it
var c=0
while(z.any{it!=z[0]}){c++
z=(0..z.size-2).map{z[it+1]-z[it]}}
c}

data class TestData(var input: List<Int>, var output: Int)

fun main(args: Array<String>) {
    val items = listOf(
        TestData(listOf(1,2,3,4,5,6,7,8,9,10), 1),
        TestData(listOf(1,4,9,16,25,36), 2),
        TestData(listOf(1,2,1), 2),
        TestData(listOf(1,1,1,1,1,1,1,1,1), 0),
        TestData(listOf(1, 3, 9, 26, 66, 150, 313, 610), 6)
    )

    val fails = items.map { it to n(it.input) }.filter { it.first.output != it.second }

    if (fails.isEmpty()) {
        println("Test passed")
    } else {
        fails.forEach {println("FAILED: $it")}
    }
}

TryItOnline


Якщо хтось міг редагувати, щоб виправити мої підказки, будь ласка, я не можу змусити їх працювати
jrtapsell

Це lang-kotlinне просто kotlin, в підказках підсвічування.
Руслан

0

Швидкий 4 , 90 байт

func f(_ a:[Int])->Int{return a.contains{$0 != a[0]} ?f(zip(a, a.dropFirst()).map(-))+1:0}

Альтернативна реалізація на основі закриття:

var f: ((_ input: [Int]) -> Int)!
f = {a in a.contains{$0 != a[0]} ?f(zip(a, a.dropFirst()).map(-))+1:0}

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

let testcases: [(input: [Int], expected: Int)] = [
    (input: [1,2,3,4,5,6,7,8,9,10],           expected: 1),
    (input: [1,4,9,16,25,36],                 expected: 2),
    (input: [1,2,1],                          expected: 2),
    (input: [1,1,1,1,1,1,1,1,1],              expected: 0),
    (input: [1, 3, 9, 26, 66, 150, 313, 610], expected: 6),
]

for (caseNumber, testcase) in testcases.enumerated() {
    let actual = f(testcase.input)
    assert(actual == testcase.expected,
        "Testcase #\(caseNumber) \(testcase.input) failed. Got \(actual), but expected \(testcase.expected)!")
    print("Testcase #\(caseNumber) passed!")
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.