N-te Unterschiede


26

In der Mathematik besteht eine Möglichkeit, die Art einer gegebenen Beziehung (linear, quadratisch usw.) herauszufinden, darin, die Differenzen zu berechnen. Dazu nehmen Sie eine Liste von y-Werten, für die der Abstand zwischen den entsprechenden x-Werten gleich ist, und subtrahieren jeden einzelnen von der darüber liegenden Zahl. Dabei wird eine Liste von Zahlen erstellt, die eine Nummer kürzer als die vorherige Liste ist. Wenn die resultierende Liste vollständig aus identischen Zahlen besteht, hat die Beziehung eine Differenz von 1 (sie ist linear). Wenn sie nicht identisch sind, wiederholen Sie den Vorgang in der neuen Liste. Wenn sie jetzt identisch sind, hat die Relation eine Differenz von 2 (sie ist quadratisch). Wenn sie nicht identisch sind, setzen Sie diesen Vorgang einfach fort, bis sie identisch sind. Wenn Sie beispielsweise die Liste der y-Werte [1,6,15,28,45,66] haben, um die x-Werte schrittweise zu erhöhen, gehen Sie wie folgt vor:

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

Deine Aufgabe:

Schreiben Sie ein Programm oder eine Funktion, die bei Angabe eines Arrays von Ganzzahlen als Eingabe die Differenz der durch das Array beschriebenen Beziehung zurückgibt, wie oben erläutert.

Eingang:

Ein Array von Ganzzahlen, das eine beliebige Länge> 1 haben kann.

Ausgabe:

Eine Ganzzahl, die die Differenz der durch die Eingabe beschriebenen Beziehung darstellt.

Testfälle:

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

Wertung:

Dies ist . Die niedrigste Punktzahl in Bytes in jeder Sprache gewinnt für diese Sprache. Die niedrigste Gesamtpunktzahl erhält das grüne Häkchen.


Kann die Eingabe wie in "ungültig" sein, wenn die Eingabe NICHT der angegebenen Spezifikation entsprechen soll, sollten wir einen Fehler machen? -1 als Ausgabe bereitstellen?
Magic Octopus Urn

Das Verhalten ist für ungültige Eingaben undefiniert (es ist mir egal, was Ihr Code tut)
Gryphon - Reinstate Monica

Sollte nicht [1,2,1]2 geben? [1,2,1] -> [1,-1] -> [-2]
HyperNeutrino

@HyperNeutrino, yep, sorry. Ich hatte dort einen Hirnfurz
Gryphon - Reinstate Monica

Fügen Sie diesen Testfall hinzu [1,3,9,26,66,150,313,610]-> 6wenn Sie
möchten

Antworten:


10

Schale , 6 Bytes

Danke Leo, dass ich seine Version verwenden durfte, die für funktioniert[1,1,1,1,1,1]

←VE¡Ẋ-

Probieren Sie es online!

Erläuterung

   ¡     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
Wann immer jemand sagte, dass Husk das neue Gelee ist, waren sie ziemlich verdammt richtig. > _ <
Zacharý

Verdammt, ich war im Begriff , zu veröffentlichen diese . Gute Arbeit, +1!
Leo

@Leo, Testfall, den ich nicht gesehen habe [1,1,1,1], kann ich deinen verwenden?
H.PWiz

@ H.PWiz na los!
Leo

7

JavaScript (ES6), 47 Byte

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

Testfälle


7

MATL , 8 Bytes

`dta}x@q

Probieren Sie es online! Oder überprüfen Sie alle Testfälle .

Erläuterung

Dadurch werden aufeinanderfolgende Differenzen iterativ kompensiert, bis das Ergebnis vollständig null oder leer ist. Die Ausgabe ist die erforderliche Anzahl von Iterationen 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


5

Mathematica, 49 Bytes

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

Danke @alephalpa für -6 Bytes und @hftf -1 Bytes

und hier ist ein anderer Ansatz von @hftf

Mathematica, 49 Bytes

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

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

1
UnsameQ[1,2,1]ist falsch; !SameQ[1,2,1]ist wahr. Ich glaube auch nicht, dass die manuelle Schleife Zeichen speichert: Sie Length@NestWhileList[Differences,#,!SameQ@@#&]-1&hat nach dem Ersetzen UnsameQdurch bereits die gleiche Länge wie Ihre !SameQ.
hftf


4

Japt , 10 7 Bytes

è@=ä-)d

Probieren Sie es online!

Beruht auf der Tatsache, dass das Ergebnis garantiert innerhalb der Länge des Eingabearrays liegt.

Erläuterung

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

Am Ende ordnet dies das Array
[1, 3, 9, 26, 66, 150, 313, 610]zu [true, true, true, true, true, true, false, false],
das 6 trues enthält .

Vorherige 10-Byte-Version

@=ä-)e¥0}a

Probieren Sie es online!


4

Perl 6 , 37 Bytes

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

Probieren Sie es online!

Erläuterung: Die Funktion nimmt die Eingabe als eine Liste. Anschließend wird eine rekursive Sequenz wie folgt erstellt: Das erste Element ist die ursprüngliche Liste ( $_), die nächsten Elemente werden zurückgegeben, indem {@(@$_ Z- .[1..*])}sie für das vorherige Element aufgerufen werden, und dies wird so lange wiederholt, bis die Bedingung erfüllt *.noneist, was nur dann der Fall ist, wenn die Liste eine der beiden ist leer oder enthält nur Nullen (oder technisch gesehen andere falsche Werte). Wir greifen dann die Liste und subtrahieren 2 davon, was sie zuerst in den numerischen Kontext zwingt (und Listen im numerischen Kontext sind gleich der Anzahl ihrer Elemente) und am Ende 2 weniger als die Anzahl der Elemente in der zurückgibt Liste.

Der seltsame Block {@(@$_ Z- .[1..*])}nimmt einfach die angegebene Liste ( .[]sogenanntes Zen-Slice - Indizieren mit leeren Klammern ergibt die gesamte Liste), komprimiert sie mit dem Minus-Operator ( Z-) mit derselben Liste ohne das erste Element ( .[1..*]) und zwingt sie zu einer Liste ( @(...)- Wir brauchen das, weil zip nur eine Seq zurückgibt, was im Grunde eine Einwegliste ist, die nur einmal wiederholt werden kann. Das ist etwas, das wir nicht mögen.) Und das ist es.


Das Ändern @(.[] Z- .[1..*])auf [.[] Z-.[1..*]]sollte zwei Bytes speichern.
Nwellnhof

4

Java 8, 191 + 58 = 249 198 140 Bytes.

Danke PunPun1000 für 51 Bytes.
Danke Nevay für 58 Bytes.

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

Probieren Sie es online!

Online testen (198-Byte-Version)

Dies ist also mein erster Beitrag hier in PPCG (und das erste Mal, dass ich eine Code-Golf-Herausforderung mache). Jede konstruktive Kritik ist willkommen und wird geschätzt. Ich habe versucht, die Richtlinien für das Posten zu befolgen. Wenn etwas nicht stimmt, kann ich Sie gerne darauf hinweisen.

Verschönerte Version:

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
Willkommen auf der Seite!
DJMcMayhem

Anstatt diese Module zu importieren, können Sie einfachjava.util.stream.IntStream k = java.util.Arrays.stream(a);
PunPun1000

In der Tat gibt es ein paar Änderungen, die Sie kostenlos vornehmen können. 1) publicmuss nicht in die Byteanzahl einbezogen werden. 2) Sie sollten keinen zweiten Parameter akzeptieren, aber wenn Sie ihn entfernen, können tatsächlich Bytes eingespart werden. 3) Sie können einige nicht benötigte Klammern dort entfernen
PunPun1000

4) Kein Sparer, aber Sie sollten wenn möglich einen TIO
einbinden.


3

Haskell, 46 Bytes

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

Dies ist einfach eine Rekursion - zipWith(-)l$last list die Differenzliste von l. und gist die Funktion, die die Frage beantwortet.


Die rekursive Lösung war die gute.
Jferard

@ jferard das ist sehr wahr
stolzer haskeller

3

Kotlin , 77 Bytes

Erster Beitrag, habe 2 mal versucht, die letzte Antwort auf kotlin zu bearbeiten; D

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

nahm am Testen von @jrtapsell teil

TryItOnline


Willkommen bei PPCG! Schöne erste Antwort, auch ein Outgolf.
H.PWiz

3

APL (Dyalog Classic) , 22 17 Bytes

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

Probieren Sie es online!

Danke an @ngn für -5 Bytes!

Wie?

  • { ... }, die Funktion
  • 1=≢∪⍵:0Wenn jedes Element im Argument gleich ist, geben Sie zurück 0
  • 1+∇2-/⍵Andernfalls geben Sie 1 + nder Differenzen zurück (was bedeutet n-1, dass eine dazu addiert wird n).

Es ist kürzer, wenn Sie die Schwanzrekursivität opfern:{1=≢∪⍵:0⋄1+∇2-/⍵}
ngn

2

Gelee , 7 Bytes

IÐĿEÐḟL

Probieren Sie es online!

Erläuterung

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 Byte danke an Jonathan Allan


1
@Gryphon Fertig! :)
HyperNeutrino

IÐĿEÐḟLfür sieben (ich sehe, dass Miles auch eine sieben mit Rekursion gefunden hat).
Jonathan Allan

@ JonathanAllan Cool, danke!
HyperNeutrino

2

05AB1E , 7 Bytes

[DË#¥]N

Probieren Sie es online!

Erläuterung

[         # 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 Byte

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

+0, nicht genug JQuery: p. Wirklich, +1, nette Arbeit, ich weiß, ich würde nie in der Lage sein, in JS Golf zu spielen.
Zacharý

2

Python 2 , 65 Bytes

-7 Bytes dank Jonathan Allan.

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

Probieren Sie es online!


Speichern Sie ein Byte - Initialisierung czu 1, Erniedrigen und dann mit print-c.
Jonathan Allan

Speichern Sie sechs weitere, indem Sie daraus eine rekursive Funktion machen: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

Bin es nur ich oder spart der Wechsel zu einem rekursiven Lambda nicht genug Bytes? : P Danke!
Totalhuman

Ich denke, das braucht eine max(...,0), um die [1, 1, 1, 1, ...]Testfälle zu bestehen.
Yonatan N

2

Dyalog APL, 19 Bytes

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

Erläuterung:

≢                      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
Funktioniert das? ≢-1+∘≢2-/⍣{1=≢∪⍵}⊢
Zacharý

2

k , 21 Bytes

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

Dies funktioniert in k, aber nicht in oK, da die while-Schleife von oK ausgeführt wird, bevor die Bedingung überprüft wird (im Gegensatz dazu, dass zuerst die Bedingung überprüft und dann der Code ausgeführt wird). Daher 1 1 1 1 1funktioniert das Beispiel in OK nicht ordnungsgemäß.

Versuchen Sie es online!

Das Beispiel k mit 1 1 1 1 1 1 im Interpreter k ausführen.

Erläuterung:

   (        )       \ /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 Bytes

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

Probieren Sie es online!

5 Bytes gespart dank Christian Sievers

Dank proud-haskeller 1 Byte gespart

iterate(z(-)) berechnet die Differenzlisten.

or.z(/=) prüft, ob diese Listen ungleiche Elemente enthalten.

length.takeWhile zählt die Differenzlisten mit ungleichen Elementen.


Ich denke, Sie können mitor.z(/=)
Christian Sievers

@ChristianSievers danke! Das war offensichtlich, aber ich habe es nicht gesehen ...
jferard

Sie können auch verwenden z=(=<<tail).zipWith, ein Byte kürzer
stolz haskeller

@proudhaskeller und eleganter, wie immer mit punktfreien Definitionen. Vielen Dank!
Jferard


2

Japt , 7 Bytes

Gleicher Ansatz (aber unabhängig abgeleitet) wie Justin mit einer anderen Implementierung.

£=äaÃèx

Probier es aus


Erläuterung

Implizite Eingabe eines Arrays U.

£   Ã

Ordnen Sie jedes Element zu.

äa

Nimm jedes sequentielle Paar ( ä) von Elementen auf Uund reduziere es um die absolute Differenz ( a).

=

Ordnen Sie das Array neu zu U.

èx

Count ( è) Die Anzahl der Sub-Arrays, die beim Reduzieren durch Addition die Wahrheit zurückgeben (dh nicht Null).


1

TI-Basic, 19 Bytes

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

Standardmäßig beginnen Variablen bei Null. Ich hätte nie gedacht, dass ich IS>(etwas Nützliches verwenden würde.


1

C # (.NET Core) , 70 69 + 18 Bytes

-1 Byte dank Kevin Cruijssen

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

Muss bei einem Anruf mit 0 angegeben werden, um ordnungsgemäß zu funktionieren. Ebenfalls in der Byteanzahl enthalten:

using System.Linq;

Probieren Sie es online!

Erläuterung:

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

Iterative Version 84 + 18 Bytes:

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

Probieren Sie es online!


1
Sie können den redundanten Speicherplatz unter entfernen (y,z)=>y-z. Aber nette Antwort, +1 von mir.
Kevin Cruijssen

@ KevinCruijssen danke! Auch hoppla.
Grzegorz Puławski

1

Clojure, 62 Bytes

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

Nizza =kann eine beliebige Anzahl von Argumenten annehmen, und ein einzelnes Argument ist identisch mit "sich selbst". (apply = [1 2 3])wird ausgeführt als (= 1 2 3).


Schön, genau das, was ich versucht habe, aber ich kämpfte um ein kompaktes paarweises Diff. Das ist großartig, das muss ich mir für die Zukunft merken.
MattPutnam

1

Pyth , 15 Bytes

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

Überprüfen Sie alle Testfälle.

Wie?

Erklärung # 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 ByteWtl{Q=hZ=.+Q)Z
Dave

@ Dave Noch besser: WP{Q=hZ=.+Q)Z. Vielen Dank!
Mr. Xcoder

0

Perl 5 , 83 + 1 (-a) = 84 Bytes

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

Probieren Sie es online!

Eingabe als Liste mit durch ein Leerzeichen getrennten Zahlen.



0

Pyth, 10 Bytes

tf!t{.+FQt

Wenn wir von 1 indexieren können, können wir ein Byte speichern, indem wir das führende Zeichen entfernen t.

Probieren Sie es online

Erläuterung

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 Bytes

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

Verschönert

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

Prüfung

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


Wenn jemand
Änderungen vornehmen

Es ist lang-kotlinnicht einfach kotlinin den Highlighter-Hinweisen.
Ruslan

0

Schnelle 4 , 90 Bytes

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

Alternative, abschlussbasierte Implementierung:

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

Testfälle:

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!")
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.