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.


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

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


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

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.


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&

(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

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!


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.


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

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,


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.


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


Witamy w PPCG! Dobra pierwsza odpowiedź, także outgolf.
— H.PWiz

3

APL (Dyalog Classic) , 22 17 bajtów

{1=≢∪⍵:0⋄1+∇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)

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


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

2

JavaScript (ES6), 58 bajtów

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

+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!


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

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

~&/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.


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

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.


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.


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!


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).


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.

-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ą.



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.

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


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!")
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.