Nième différences

26

En mathématiques, une façon de déterminer quel est le type d'une relation donnée (linéaire, quadratique, etc.) pour calculer les différences. Pour ce faire, vous prenez une liste de valeurs y pour lesquelles l'écart entre les valeurs x correspondantes est le même, et soustrayez chacune du nombre au-dessus, créant une liste de nombres plus courte que la liste précédente. Si la liste résultante est entièrement composée de nombres identiques, alors la relation a une différence de 1 (elle est linéaire). S'ils ne sont pas identiques, vous répétez le processus sur la nouvelle liste. S'ils sont maintenant identiques, la relation a une différence de 2 (elle est quadratique). S'ils ne sont pas identiques, vous continuez simplement ce processus jusqu'à ce qu'ils le soient. Par exemple, si vous avez la liste des valeurs y [1,6,15,28,45,66] pour l'augmentation incrémentielle des valeurs 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

Ta tâche:

Écrivez un programme ou une fonction qui, lorsqu'elle reçoit un tableau d'entiers en entrée, renvoie la différence de la relation décrite par le tableau, comme expliqué ci-dessus.

Contribution:

Un tableau d'entiers, qui peut être de n'importe quelle longueur> 1.

Sortie:

Un entier représentant la différence de la relation décrite par l'entrée.

Cas de test:

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

Notation:

Il s'agit du , le score le plus bas en octets dans chaque langue gagne pour cette langue. Le score le plus bas obtient la coche verte.

Gryphon - Rétablir Monica
la source
L'entrée peut-elle être "invalide" comme dans, si l'entrée n'est PAS conforme à la spécification fournie, devrions-nous commettre une erreur? Fournissez -1 comme sortie?
Magic Octopus Urn
Le comportement n'est pas défini pour une entrée non valide (peu m'importe ce que fait votre code)
Gryphon - Réinstallez Monica
Ne devrait pas [1,2,1]donner 2? [1,2,1] -> [1,-1] -> [-2]
HyperNeutrino
@HyperNeutrino, oui, désolé. J'y ai eu un pet cérébral
Gryphon - Rétablir Monica
Ajouter ce test [1,3,9,26,66,150,313,610]-> 6si vous le souhaitez
J42161217

Réponses:

10

Husk , 6 octets

Merci Leo de me laisser utiliser sa version qui fonctionne pour[1,1,1,1,1,1]

←VE¡Ẋ-

Essayez-le en ligne!

Explication

   ¡     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
la source
2
Chaque fois que quelqu'un disait que Husk était la nouvelle gelée, ils avaient raison. > _ <
Zacharý
Merde, j'allais poster ça . Bon travail cependant, +1!
Leo
@Leo, cas de test que je n'ai pas vu [1,1,1,1], puis-je utiliser le vôtre?
H.PWiz
@ H.PWiz bien sûr, continuez!
Leo
7

JavaScript (ES6), 47 octets

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

Cas de test

Arnauld
la source
7

MATL , 8 octets

`dta}x@q

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication

Cela compense les différences consécutives de manière itérative jusqu'à ce que le résultat soit entièrement nul ou vide. La sortie est le nombre requis d'itérations moins 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
la source
7

R , 50 44 octets

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

Essayez-le en ligne!

Prend un diffde l, le définit sur let vérifie si le résultat contient des valeurs non nulles. Dans le cas contraire, l' incrément F(initialisé FALSEimplicitement), et revient F*1à convertir FALSEà 0dans le cas où tous lest déjà identique.

Giuseppe
la source
Programme complet et +Fastuce pour 5 octets . Bonne réponse btw!
JayCe
5

Mathematica, 49 octets

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

merci @alephalpa pour -6 octets et @hftf -1 octet

et voici une autre approche de @hftf

Mathematica, 49 octets

Length@NestWhileList[Differences,#,!SameQ@@#&]-1&
J42161217
la source
(s=#;t=0;While[UnsameQ@@s,s=Differences@s;t++];t)&
alephalpha
1
UnsameQ[1,2,1]c'est faux; !SameQ[1,2,1]est vrai. Je ne pense pas non plus que la boucle manuelle enregistre les caractères: a Length@NestWhileList[Differences,#,!SameQ@@#&]-1&déjà la même longueur que la vôtre après avoir été remplacée UnsameQpar !SameQ.
hftf
4

Gelée , 7 octets

-Iß$E?‘

Essayez-le en ligne!

Explication

-Iß$E?‘  Input: array A
     ?   If
    E    All elements are equal
         Then
-          Constant -1
         Else
   $       Monadic chain
 I           Increments
  ß          Recurse
      ‘  Increment
miles
la source
Alternative non récursive:IÐĿE€ċ0
Erik the Outgolfer
4

Japt , 10 7 octets

è@=ä-)d

Essayez-le en ligne!

S'appuie sur le fait que le résultat est garanti dans la longueur du tableau d'entrée.

Explication

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

À la fin, cela mappera le tableau
[1, 3, 9, 26, 66, 150, 313, 610]à [true, true, true, true, true, true, false, false],
qui contient 6 trues.

Version précédente de 10 octets

@=ä-)e¥0}a

Essayez-le en ligne!

Justin Mariner
la source
4

Perl 6 , 37 octets

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

Essayez-le en ligne!

Explication: La fonction prend l'entrée comme une seule liste. Il construit ensuite une séquence récursive comme celle-ci: le premier élément est la liste d'origine ( $_), les éléments suivants sont retournés en {@(@$_ Z- .[1..*])}étant appelés sur l'élément précédent, et cela est itéré jusqu'à ce que la condition *.nonesoit vraie, ce qui ne se produit que lorsque la liste est soit vide ou ne contient que des zéros (ou, techniquement, d'autres valeurs de falsey). Nous prenons ensuite la liste et soustrayons 2 de celle-ci, ce qui la force d'abord au contexte numérique (et les listes dans le contexte numérique sont égales au nombre de leurs éléments) et, à la fin, renvoie 2 de moins que le nombre d'éléments dans le liste.

Le bloc étrange {@(@$_ Z- .[1..*])}prend simplement la liste donnée ( .[]- ce qu'on appelle la tranche Zen - l'indexation avec des crochets vides donne la liste entière), la zippe en utilisant l'opérateur moins ( Z-) avec la même liste sans le premier élément ( .[1..*]) et la force à une liste ( @(...)- nous en avons besoin parce que zip ne renvoie qu'un Seq, qui est fondamentalement une liste à sens unique qui ne peut être itérée qu'une seule fois. C'est quelque chose que nous n'aimons pas.) Et c'est tout.

Ramillies
la source
La modification @(.[] Z- .[1..*])en [.[] Z-.[1..*]]devrait économiser deux octets.
nwellnhof
4

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

Merci PunPun1000 pour 51 octets.
Merci Nevay pour 58 octets.

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

Essayez-le en ligne!

Essayez-le en ligne (version 198 octets)

Donc, c'est ma première publication ici dans PPCG (et la première fois que je fais un défi de golf de code). Toute critique constructive est la bienvenue et appréciée. J'ai essayé de suivre les directives de publication, si quelque chose ne va pas, n'hésitez pas à le signaler.

Version embellie:

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é
la source
3
Bienvenue sur le site!
DJMcMayhem
Au lieu d'importer ces modules, vous pouvez simplement utiliserjava.util.stream.IntStream k = java.util.Arrays.stream(a);
PunPun1000
En fait, vous pouvez apporter gratuitement quelques modifications. 1) publicn'a pas besoin d'être inclus dans le nombre d'octets. 2) Vous ne devriez pas accepter un deuxième paramètre, mais le supprimer peut en fait économiser des octets. 3) vous pouvez y supprimer certains supports inutiles
PunPun1000
4) Pas un économiseur mais vous devriez inclure un TIO si possible, voici un exemple avec ces suggestions à 198 octets TIO
PunPun1000
1
140 octets
Nevay
3

Haskell, 46 octets

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

cela revient simplement - zipWith(-)l$last lest la liste des différences l. et gc'est la fonction qui répond à la question.

fier haskeller
la source
la solution récursive était la bonne.
jferard
@jferard c'est très vrai
fier haskeller
3

Kotlin , 77 octets

premier message, a essayé de modifier la dernière réponse sur kotlin 2 fois; D

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

a pris une partie de test de @jrtapsell

TryItOnline

cab404
la source
Bienvenue chez PPCG! Belle première réponse, un outgolf aussi.
H.PWiz
3

APL (Dyalog Classic) , 22 17 octets

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

Essayez-le en ligne!

Merci à @ngn pour -5 octets!

Comment?

  • { ... }, la fonction
  • 1=≢∪⍵:0, si chaque élément est égal dans l'argument, retourne 0
  • 1+∇2-/⍵, sinon, renvoyer 1 + ndes différences (ce n-1qui signifie qu'en y ajoutant un donne n)
Zacharý
la source
il est plus court si vous sacrifiez la récursivité de la queue:{1=≢∪⍵:0⋄1+∇2-/⍵}
ngn
2

Gelée , 7 octets

IÐĿEÐḟL

Essayez-le en ligne!

Explication

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 octet merci à Jonathan Allan

HyperNeutrino
la source
1
@Gryphon Done! :)
HyperNeutrino
IÐĿEÐḟLpour sept (je vois que Miles a également trouvé un sept utilisant la récursivité).
Jonathan Allan,
@JonathanAllan Cool merci!
HyperNeutrino
2

05AB1E , 7 octets

[DË#¥]N

Essayez-le en ligne!

Explication

[         # start loop
 D        # duplicate current list
  Ë       # are all elements equal?
   #      # if so, break
    ¥     # calculate delta's
     ]    # end loop
      N   # push iteration counter
Emigna
la source
2

JavaScript (ES6), 58 octets

f=a=>+(b=a.slice(1).map((e,i)=>e-a[i])).some(e=>e)&&1+f(b)
Neil
la source
+0, pas assez Jquery: p. Vraiment cependant, +1, beau travail, je sais que je ne pourrais jamais jouer au golf à JS.
Zacharý
2

Python 2 , 65 octets

-7 octets grâce à 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

Essayez-le en ligne!

totalement humain
la source
Enregistrer un octet initialisant cà 1, décrémentation puis en utilisant print-c.
Jonathan Allan
Économisez six de plus en en faisant une fonction récursive: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
Est-ce juste moi ou le passage à un lambda récursif n'économise-t-il pas suffisamment d'octets? : P Merci!
totalement humain
Je pense que cela nécessite un max(...,0)pour passer les [1, 1, 1, 1, ...]cas de test.
Yonatan N
2

Dyalog APL, 19 octets

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

Explication:

≢                      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
la source
1
Est-ce que ça marche? ≢-1+∘≢2-/⍣{1=≢∪⍵}⊢
Zacharý
2

k , 21 octets

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

Cela fonctionne en k, mais pas en oK, car la boucle while de oK s'exécute avant de vérifier la condition (par opposition à la première vérification de la condition, puis à l'exécution du code). Par conséquent, en ok, l' 1 1 1 1 1exemple ne fonctionnera pas correctement.

Essayez oK en ligne!

Exécution de l'exemple k avec 1 1 1 1 1 1 dans l'interpréteur k.

Explication:

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

Haskell , 66 61 60 octets

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

Essayez-le en ligne!

Enregistré 5 octets grâce à Christian Sievers

1 octet enregistré grâce à fier-haskeller

iterate(z(-)) calcule les listes de différences.

or.z(/=) teste s'il y a des éléments non égaux dans ces listes.

length.takeWhile compte les listes de différences avec des éléments non égaux.

jferard
la source
Je pense que vous pouvez tester des éléments non égaux avecor.z(/=)
Christian Sievers
@ChristianSievers merci! C'était évident, mais je ne l'ai pas vu ...
jferard
Vous pouvez également utiliser z=(=<<tail).zipWith, un octet plus court
fier haskeller
@proudhaskeller et plus élégant, comme toujours avec des définitions sans points. Merci!
jferard
2

Japt , 7 octets

Même approche (mais dérivée indépendamment) que Justin avec une implémentation différente.

£=äaÃèx

Essaye-le


Explication

Entrée implicite du tableau U.

£   Ã

Cartographiez chaque élément.

äa

Prenez chaque paire séquentielle ( ä) d'éléments Uet réduisez-la par différence absolue ( a).

=

Réaffectez ce tableau à U.

èx

Count ( è) le nombre de sous-tableaux qui retournent vrai (c'est-à-dire non nul) lorsqu'ils sont réduits par addition.

Hirsute
la source
1

TI-Basic, 19 octets

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

Par défaut, les variables commencent à zéro. De plus, je n'ai jamais pensé utiliser IS>(quelque chose d'utile.

Timtech
la source
1

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

-1 octet grâce à Kevin Cruijssen

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

Doit être 0 lors de l'appel pour fonctionner correctement. Également inclus dans le nombre d'octets:

using System.Linq;

Essayez-le en ligne!

Explication:

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

Version itérative 84 + 18 octets:

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

Essayez-le en ligne!

Grzegorz Puławski
la source
1
Vous pouvez supprimer l'espace redondant à l'adresse (y,z)=>y-z. Mais belle réponse, +1 de ma part.
Kevin Cruijssen
@KevinCruijssen merci! Aussi, oups.
Grzegorz Puławski
1

Clojure, 62 octets

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

Nice =peut prendre n'importe quel nombre d'arguments, et un seul argument est identique à "lui-même". (apply = [1 2 3])est exécuté comme (= 1 2 3).

NikoNyrh
la source
Bien, exactement ce que j'essayais de faire, mais je luttais pour des différences compactes par paire. C'est génial, je dois m'en souvenir pour l'avenir.
MattPutnam
1

Pyth , 15 octets

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

Vérifiez tous les cas de test.

Comment?

Explication # 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.
M. Xcoder
la source
-1 octetWtl{Q=hZ=.+Q)Z
Dave
@ Dave Mieux encore: WP{Q=hZ=.+Q)Z. Merci!
M. Xcoder du
0

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

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

Essayez-le en ligne!

Saisissez une liste de nombres séparés par un espace.

Xcali
la source
0

Pyth, 10 octets

tf!t{.+FQt

Si nous pouvons indexer à partir de 1, nous pouvons enregistrer un octet en supprimant l'interlignage t.

Essayez-le en ligne

Explication

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.

la source
0

Kotlin , 83 octets

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

Embellie

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

Tester

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
la source
Si quelqu'un pouvait modifier pour corriger mes indices de langue s'il vous plaît, je n'arrive pas à les faire fonctionner
jrtapsell
Ce n'est lang-kotlinpas simplement kotlindans les indices de surlignage.
Ruslan
0

Swift 4 , 90 octets

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

Mise en œuvre alternative, basée sur la fermeture:

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

cas de test:

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 - Rétablir Monica
la source