Nth Differences

26

W matematyce jednym ze sposobów ustalenia, jaki typ danej relacji (liniowy, kwadratowy itp.) Jest obliczenie różnic. Aby to zrobić, weź listę wartości y, dla których odstęp między odpowiednimi wartościami x jest taki sam, i odejmij każdą z liczb powyżej, tworząc listę liczb o jedną krótszą niż poprzednia. Jeśli wynikowa lista jest całkowicie złożona z identycznych liczb, wówczas relacja ma różnicę 1 (jest liniowa). Jeśli nie są identyczne, powtórz proces na nowej liście. Jeśli są teraz identyczne, relacja ma różnicę 2 (jest kwadratowa). Jeśli nie są identyczne, po prostu kontynuuj ten proces, aż będą. Na przykład, jeśli masz listę wartości y [1,6,15,28,45,66] do stopniowego zwiększania wartości 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

Twoje zadanie:

Napisz program lub funkcję, która, gdy otrzyma tablicę liczb całkowitych jako dane wejściowe, zwraca różnicę relacji opisanej przez tablicę, jak wyjaśniono powyżej.

Wkład:

Tablica liczb całkowitych, które mogą mieć dowolną długość> 1.

Wydajność:

Liczba całkowita reprezentująca różnicę relacji opisanej przez dane wejściowe.

Przypadki testowe:

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

Punktacja:

To jest , najniższy wynik w bajtach w każdym języku wygrywa dla tego języka. Najniższy wynik ogółem otrzymuje zielony znacznik wyboru.

Gryphon - Przywróć Monikę
źródło
Czy dane wejściowe mogą być „nieprawidłowe” jak w przypadku, jeśli dane wejściowe NIE mają być zgodne z podaną specyfikacją, czy powinniśmy popełnić błąd? Podaj -1 jako wynik?
Magic Octopus Urn
Zachowanie jest niezdefiniowane dla nieprawidłowych danych wejściowych (nie dbam o to, co robi twój kod)
Gryphon - Przywróć Monikę
Nie powinienem [1,2,1]dać 2? [1,2,1] -> [1,-1] -> [-2]
HyperNeutrino,
@HyperNeutrino, tak, przepraszam. Miałem tam pierdnięcie
Gryphon - Przywróć Monikę
Dodaj ten przypadek testowy [1,3,9,26,66,150,313,610]-> 6jeśli chcesz
J42161217

Odpowiedzi:

10

Łuska , 6 bajtów

Dzięki Leo za pozwolenie na użycie jego wersji, która działa[1,1,1,1,1,1]

←VE¡Ẋ-

Wypróbuj online!

Wyjaśnienie

   ¡     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
H.PWiz
źródło
2
Ilekroć ktoś mówił, że Łuska jest nową galaretką, mieli rację. > _ <
Zacharý
Cholera, zamierzałem to opublikować . Dobra robota, +1!
Leo
@Leo, przypadek testowy, którego nie widziałem [1,1,1,1], czy mogę użyć twojego?
H.PWiz
@ H.PWiz na pewno, kontynuuj!
Leo
7

JavaScript (ES6), 47 bajtów

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

Przypadki testowe

Arnauld
źródło
7

MATL , 8 bajtów

`dta}x@q

Wypróbuj online! Lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie

W ten sposób iteracyjnie obliczane są kolejne różnice, aż wynik będzie zerowy lub pusty. Dane wyjściowe to wymagana liczba iteracji minus 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
Luis Mendo
źródło
7

R , 50 44 bajtów

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

Wypróbuj online!

Trwa diffod l, przypisuje mu wartość l, i sprawdza, czy wynik zawiera żadnych wartości niezerowe. Jeśli tak, przyrost F(zainicjowany jako FALSEniejawnie) i powraca F*1do konwersji FALSE, aby 0w przypadku, gdy wszyscy lsą już identyczne.

Giuseppe
źródło
Pełny program i +Ftrick na 5 bajtów . Zgrabna odpowiedź btw!
JayCe
5

Mathematica, 49 bajtów

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

thanx @alephalpa dla -6 bajtów i @hftf -1 bajt

a oto inne podejście z @hftf

Mathematica, 49 bajtów

Length@NestWhileList[Differences,#,!SameQ@@#&]-1&
J42161217
źródło
(s=#;t=0;While[UnsameQ@@s,s=Differences@s;t++];t)&
alephalpha
1
UnsameQ[1,2,1]to fałsz; !SameQ[1,2,1]jest prawdziwy. Nie sądzę, instrukcja pętli zapisuje znaki albo: Length@NestWhileList[Differences,#,!SameQ@@#&]-1&jest już taka sama długość jak ty po wymianie UnsameQz !SameQ.
hftf
4

Galaretka , 7 bajtów

-Iß$E?‘

Wypróbuj online!

Wyjaśnienie

-Iß$E?‘  Input: array A
     ?   If
    E    All elements are equal
         Then
-          Constant -1
         Else
   $       Monadic chain
 I           Increments
  ß          Recurse
      ‘  Increment
mile
źródło
IÐĿE€ċ0
Nierekurencyjna
4

Japt , 10 7 bajtów

è@=ä-)d

Wypróbuj online!

Opiera się na tym, że gwarantowany wynik mieści się w zakresie tablicy wejściowej.

Wyjaśnienie

è@=ä-)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

Do końca, ten będzie mapować tablicę
[1, 3, 9, 26, 66, 150, 313, 610]do [true, true, true, true, true, true, false, false],
który zawiera 6 trues.

Poprzednia 10 bajtowa wersja

@=ä-)e¥0}a

Wypróbuj online!

Justin Mariner
źródło
4

Perl 6 , 37 bajtów

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

Wypróbuj online!

Objaśnienie: Funkcja przyjmuje dane wejściowe jako jedną listę. Następnie buduje sekwencję rekurencyjną w ten sposób: pierwszy element jest oryginalną listą ( $_), kolejne elementy są zwracane przez {@(@$_ Z- .[1..*])}wywołanie poprzedniego elementu, i to jest iterowane do momentu spełnienia warunku *.none, co dzieje się tylko wtedy, gdy lista jest albo puste lub zawiera tylko zera (lub, technicznie rzecz biorąc, inne wartości falsey). Następnie pobieramy listę i odejmujemy od niej 2, co wymusza ją najpierw w kontekście liczbowym (a listy w kontekście numerycznym są równe liczbie ich elementów), a na koniec zwraca 2 mniej niż liczba elementów w lista.

Dziwny blok {@(@$_ Z- .[1..*])}po prostu bierze podaną listę ( .[]- tak zwany plasterek Zen - indeksowanie pustymi nawiasami daje całą listę), zamyka ją za pomocą operatora minus ( Z-) z tą samą listą bez pierwszego elementu ( .[1..*]) i wymusza na liście ( @(...)- potrzebujemy tego, ponieważ zip zwraca tylko Seq, który jest w zasadzie listą jednokierunkową, którą można powtórzyć tylko raz. Którego nie lubimy.) I to jest to.

Ramillies
źródło
Zmiana @(.[] Z- .[1..*])na [.[] Z-.[1..*]]powinna zaoszczędzić dwa bajty.
nwellnhof
4

Java 8, 191 + 58 = 249 198 140 bajtów.

Dzięki PunPun1000 za 51 bajtów.
Dzięki Nevay za 58 bajtów.

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);}

Wypróbuj online!

Wypróbuj online (wersja 198 bajtów)

To pierwszy raz, kiedy piszę tutaj w PPCG (i po raz pierwszy wykonuję wyzwanie w golfa kodem). Każda konstruktywna krytyka jest mile widziana i doceniana. Starałem się postępować zgodnie z wytycznymi dotyczącymi publikowania, jeśli coś jest nie tak, zachęcamy do zwrócenia na to uwagi.

Wersja upiększona:

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);
}
J. Sallé
źródło
3
Witamy na stronie!
DJMcMayhem
Zamiast importować te moduły, których możesz po prostu użyćjava.util.stream.IntStream k = java.util.Arrays.stream(a);
PunPun1000,
Istnieje kilka zmian, które możesz wprowadzić za darmo. 1) publicnie musi być uwzględniany w liczbie bajtów. 2) Nie powinieneś akceptować drugiego parametru, ale usunięcie go może faktycznie zaoszczędzić bajty. 3) możesz usunąć niepotrzebne nawiasy klamrowe
PunPun1000,
4) Nie oszczędzaj, ale jeśli to możliwe, powinieneś dołączyć TIO, oto przykład z tymi sugestiami przy 198 bajtach TIO
PunPun1000,
1
140 bajtów
Nevay
3

Haskell, 46 bajtów

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

to po prostu się powtarza - zipWith(-)l$last lto lista różnic l. i gjest funkcją, która odpowiada na pytanie.

dumny haskeller
źródło
rozwiązanie rekurencyjne było dobre.
jferard
@jferard to bardzo prawda
dumny haskeller
3

Kotlin , 77 bajtów

pierwszy post, 2 razy próbował edytować ostatnią odpowiedź na 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}

wziął udział w testowaniu od @jrtapsell

TryItOnline

kabina404
źródło
Witamy w PPCG! Dobra pierwsza odpowiedź, także outgolf.
H.PWiz
3

APL (Dyalog Classic) , 22 17 bajtów

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

Wypróbuj online!

Dzięki @ngn za -5 bajtów!

W jaki sposób?

  • { ... }, funkcja
  • 1=≢∪⍵:0, jeśli każdy element jest taki sam w argumencie, zwróć 0
  • 1+∇2-/⍵, w przeciwnym razie zwróć 1+ nróżnic (co oznacza n-1, że dodanie jednego do niej daje n)
Zacharý
źródło
jest krótszy, jeśli poświęcisz rekurencyjność ogona:{1=≢∪⍵:0⋄1+∇2-/⍵}
ngn
2

Galaretka , 7 bajtów

IÐĿEÐḟL

Wypróbuj online!

Wyjaśnienie

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 bajt dzięki Jonathan Allan

HyperNeutrino
źródło
1
@Gryphon Done! :)
HyperNeutrino,
IÐĿEÐḟLna siedem (widzę, że Miles również znalazł siódemkę za pomocą rekurencji).
Jonathan Allan
@JonathanAllan Fajne dzięki!
HyperNeutrino,
2

05AB1E , 7 bajtów

[DË#¥]N

Wypróbuj online!

Wyjaśnienie

[         # start loop
 D        # duplicate current list
  Ë       # are all elements equal?
   #      # if so, break
    ¥     # calculate delta's
     ]    # end loop
      N   # push iteration counter
Emigna
źródło
2

JavaScript (ES6), 58 bajtów

f=a=>+(b=a.slice(1).map((e,i)=>e-a[i])).some(e=>e)&&1+f(b)
Neil
źródło
+0, za mało Jquery: p. Naprawdę jednak +1, niezła robota, wiem, że nigdy nie byłbym w stanie grać w golfa w JS.
Zacharý
2

Python 2 , 65 bajtów

-7 bajtów dzięki Jonathanowi Allanowi.

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

Wypróbuj online!

całkowicie ludzki
źródło
Zapisać bajt inicjalizacji cdo 1, zmniejszanie, a następnie przy użyciu print-c.
Jonathan Allan
Zaoszczędź jeszcze sześć, zmieniając go w funkcję rekurencyjną:f=lambda l,c=1:any(l)and f([j-i for i,j in zip(l,l[1:])],c-1)or-c
Jonathan Allan
Czy to tylko ja, czy przejście na rekurencyjną lambda nie oszczędza wystarczającej ilości bajtów? : P Dzięki!
całkowicieludzki
Myślę, że to wymaga max(...,0)zaliczenia [1, 1, 1, 1, ...]przypadków testowych.
Yonatan N
2

Dyalog APL, 19 bajtów

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

Wyjaśnienie:

≢                      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
marinus
źródło
1
czy to działa? ≢-1+∘≢2-/⍣{1=≢∪⍵}⊢
Zacharý
2

k , 21 bajtów

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

Działa to w k, ale nie w ok, ponieważ pętla while ok działa przed sprawdzeniem warunku (w przeciwieństwie do pierwszego sprawdzenia warunku, a następnie uruchomienia kodu). Dlatego w ok 1 1 1 1 1przykład nie będzie działał poprawnie.

Wypróbuj ok online!

Uruchamianie k przykładu z 1 1 1 1 1 1 w k interpretatorze.

Wyjaśnienie:

   (        )       \ /while(
    ~&/               /      not(min(
       1_=':          /              check equality of all pairs))) {
             (1_-':)  /    generate difference list
                      /    append to output }
#1_                   /(length of output) - 1
zgrep
źródło
~&/1_=':->1<#?
ngn
2

Haskell , 66 61 60 bajtów

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

Wypróbuj online!

Zaoszczędź 5 bajtów dzięki Christian Sievers

Oszczędność 1 bajtu dzięki dumnemu haskellerowi

iterate(z(-)) oblicza listy różnic.

or.z(/=) sprawdza, czy na tych listach nie ma równych elementów.

length.takeWhile zlicza listy różnic z nierównymi elementami.

Jferard
źródło
Myślę, że możesz przetestować elementy nierównomierne zor.z(/=)
Christian Sievers
@ChristianSievers dzięki! To było oczywiste, ale tego nie widziałem ...
Jferard
Możesz także użyć z=(=<<tail).zipWithjednego bajtu krótszego
dumny haskeller
@proudhaskeller i bardziej elegancki, jak zawsze z definicjami bez punktów. Dzięki!
Jferard
2

Java (OpenJDK 8) , 98 94 bajtów

a->{int o=0,i,z=1;for(;z!=0;o++)for(i=a.length-1,z=0;i>o;a[i]-=a[--i])z|=a[o]^a[i];return~-o;}

Wypróbuj online!

Nieważne
źródło
2

Japt , 7 bajtów

To samo podejście (ale niezależnie wyprowadzone) jak Justin z inną implementacją.

£=äaÃèx

Sprawdź to


Wyjaśnienie

Domniemane wejście tablicy U.

£   Ã

Mapuj nad każdym elementem.

äa

Weź każdą sekwencyjną parę ( ä) elementów Ui zmniejsz ją o różnicę bezwzględną ( a).

=

Ponownie przypisz tę tablicę do U.

èx

Count ( è) liczba podtablic, które zwracają wartość true (tzn. Niezerową), gdy zostaną zmniejszone przez dodanie.

Kudłaty
źródło
1

TI-Basic, 19 bajtów

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

Domyślnie zmienne zaczynają się od zera. Poza tym nigdy nie myślałem, że będę używał IS>(do czegoś użytecznego.

Timtech
źródło
1

C # (.NET Core) , 70 69 + 18 bajtów

-1 bajt dzięki Kevin Cruijssen

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

Należy podać 0, aby zadzwonić, aby działać poprawnie. Również uwzględniony w liczbie bajtów:

using System.Linq;

Wypróbuj online!

Wyjaśnienie:

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

Wersja iteracyjna 84 + 18 bajtów:

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

Wypróbuj online!

Grzegorz Puławski
źródło
1
Możesz usunąć zbędne miejsce w (y,z)=>y-z. Ale fajna odpowiedź, +1 ode mnie.
Kevin Cruijssen
@KevinCruijssen dziękuję! Poza tym, ups.
Grzegorz Puławski
1

Clojure, 62 bajty

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

Ładnie =może przyjmować dowolną liczbę argumentów, a pojedynczy argument jest identyczny z „samym”. (apply = [1 2 3])zostaje stracony jako (= 1 2 3).

NikoNyrh
źródło
Fajnie, dokładnie to, co próbowałem zrobić, ale walczyłem o kompaktowe pary różnic. To wspaniale, muszę to zapamiętać na przyszłość.
MattPutnam
1

Pyth , 15 bajtów

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

Sprawdź wszystkie przypadki testowe.

W jaki sposób?

Wyjaśnienie nr 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.
Pan Xcoder
źródło
-1 bajtWtl{Q=hZ=.+Q)Z
Dave
@Dave Nawet lepiej: WP{Q=hZ=.+Q)Z. Dzięki!
Pan Xcoder,
0

Perl 5 , 83 + 1 (-a) = 84 bajtów

sub c{$r=0;$r||=$_-$F[0]for@F;$r}for(;c;$i=0){$_-=$F[++$i]for@F;$#F--}say y/ //-$#F

Wypróbuj online!

Wprowadź jako listę liczb oddzielonych jednym spacją.

Xcali
źródło
0

Pyth, 10 bajtów

tf!t{.+FQt

Jeśli możemy indeksować od 1, możemy zapisać bajt, usuwając wiodące t.

Wypróbuj online

Wyjaśnienie

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.

źródło
0

Kotlin , 83 bajty

{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}

Upiększony

{
    // 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
}

Test

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
źródło
Jeśli ktoś mógłby edytować, aby naprawić moje wskazówki językowe, nie wydaje mi się, aby działały
jrtapsell
Nie chodzi lang-kotlintylko kotlino wskazówki dotyczące zakreślacza.
Ruslan
0

Swift 4 , 90 bajtów

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

Alternatywne wdrożenie oparte na zamknięciu:

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

przypadki testowe:

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!")
}
Alexander - Przywróć Monikę
źródło