Enésimas diferencias

26

En matemáticas, una forma de descubrir cuál es el tipo de una relación dada (lineal, cuadrática, etc.) es calcular las diferencias. Para hacerlo, tome una lista de valores y para los cuales el espacio entre los valores correspondientes de x es el mismo, y reste cada uno del número que está arriba, creando una lista de números uno más corto que la lista anterior. Si la lista resultante está completamente compuesta de números idénticos, entonces la relación tiene una diferencia de 1 (es lineal). Si no son idénticos, repite el proceso en la nueva lista. Si ahora son idénticos, la relación tiene una diferencia de 2 (es cuadrática). Si no son idénticos, simplemente continúe este proceso hasta que lo sean. Por ejemplo, si tiene la lista de valores de y [1,6,15,28,45,66] para aumentar gradualmente los valores de 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

Tu tarea:

Escriba un programa o función que, cuando se le da una matriz de enteros como entrada, devuelve la diferencia de la relación descrita por la matriz, como se explicó anteriormente.

Entrada:

Una matriz de enteros, que pueden tener cualquier longitud> 1.

Salida:

Un entero que representa la diferencia de la relación descrita por la entrada.

Casos de prueba:

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

Tanteo:

Este es el , el puntaje más bajo en bytes en cada idioma gana para ese idioma. La puntuación más baja en general obtiene la marca de verificación verde.

Gryphon - Restablece a Monica
fuente
¿Puede la entrada ser "inválida" como en, si la entrada NO se ajusta a las especificaciones proporcionadas, deberíamos error? Proporcionar -1 como salida?
Urna de pulpo mágico
El comportamiento no está definido para la entrada no válida (no me importa lo que haga su código)
Gryphon - Restablecer Mónica
No debería [1,2,1]dar 2? [1,2,1] -> [1,-1] -> [-2]
HyperNeutrino
@HyperNeutrino, sí, lo siento. Tuve un pedo cerebral allí
Gryphon - Restablece a Mónica
Agregue este caso de prueba [1,3,9,26,66,150,313,610]-> 6si lo desea
J42161217

Respuestas:

10

Casco , 6 bytes

Gracias Leo por dejarme usar su versión que funciona para[1,1,1,1,1,1]

←VE¡Ẋ-

Pruébalo en línea!

Explicación

   ¡     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
fuente
2
Cada vez que alguien decía que Husk era la nueva gelatina, tenían razón. > _ <
Zacharý
Maldición, iba a publicar esto . Buen trabajo, sin embargo, +1!
Leo
@Leo, caso de prueba que no vi [1,1,1,1], ¿puedo usar el tuyo?
H.PWiz
@ H.PWiz seguro, ¡adelante!
Leo
7

JavaScript (ES6), 47 bytes

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

Casos de prueba

Arnauld
fuente
7

MATL , 8 bytes

`dta}x@q

Pruébalo en línea! O verificar todos los casos de prueba .

Explicación

Esto compite las diferencias consecutivas de forma iterativa hasta que el resultado sea todo ceros o vacío. La salida es el número requerido de iteraciones menos 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
fuente
7

R , 50 44 bytes

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

Pruébalo en línea!

Toma un diffde l, lo establece ly comprueba si el resultado contiene valores distintos de cero. Si lo hace, la subasta F(inicializado como FALSEimplícitamente), y vuelve F*1a convertir FALSEa 0en el caso de que todos les idéntico ya.

Giuseppe
fuente
Programa completo y +Ftruco para 5 bytes . Buena respuesta por cierto!
JayCe
5

Mathematica, 49 bytes

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

Gracias @alephalpa para -6 bytes y @hftf -1 byte

y aquí hay otro enfoque de @hftf

Mathematica, 49 bytes

Length@NestWhileList[Differences,#,!SameQ@@#&]-1&
J42161217
fuente
(s=#;t=0;While[UnsameQ@@s,s=Differences@s;t++];t)&
alephalpha
1
UnsameQ[1,2,1]Es falso; !SameQ[1,2,1]es verdad. No creo que el bucle manual de guarda caracteres o bien: Length@NestWhileList[Differences,#,!SameQ@@#&]-1&ya es la misma longitud que la suya después de reemplazar UnsameQcon !SameQ.
hftf
4

Jalea , 7 bytes

-Iß$E?‘

Pruébalo en línea!

Explicación

-Iß$E?‘  Input: array A
     ?   If
    E    All elements are equal
         Then
-          Constant -1
         Else
   $       Monadic chain
 I           Increments
  ß          Recurse
      ‘  Increment
millas
fuente
Alternativa no recursiva:IÐĿE€ċ0
Erik the Outgolfer
4

Japt , 10 7 bytes

è@=ä-)d

Pruébalo en línea!

Se basa en el hecho de que el resultado está garantizado dentro de la longitud de la matriz de entrada.

Explicación

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

Al final, esto asignará la matriz
[1, 3, 9, 26, 66, 150, 313, 610]a [true, true, true, true, true, true, false, false],
que contiene 6 trues.

Versión anterior de 10 bytes

@=ä-)e¥0}a

Pruébalo en línea!

Justin Mariner
fuente
4

Perl 6 , 37 bytes

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

Pruébalo en línea!

Explicación: La función toma la entrada como una lista. Luego construye una secuencia recursiva como esta: el primer elemento es la lista original ( $_), los siguientes elementos son devueltos al {@(@$_ Z- .[1..*])}ser invocados en el elemento anterior, y eso se repite hasta que la condición *.nonesea ​​verdadera, lo que ocurre solo cuando la lista es está vacío o contiene solo ceros (o, técnicamente, otros valores de falsey). Luego tomamos la lista y le restamos 2, lo que lo fuerza primero al contexto numérico (y las listas en contexto numérico son iguales al número de sus elementos) y, al final, devuelve 2 menos que el número de elementos en el lista.

El bloque extraño {@(@$_ Z- .[1..*])}simplemente toma la lista dada ( .[]- llamada rebanada Zen - la indexación con corchetes vacíos produce la lista completa), la comprime usando el operador menos ( Z-) con la misma lista sin el primer elemento ( .[1..*]) y lo fuerza a una lista ( @(...)- necesitamos eso porque zip devuelve solo una Seq, que es básicamente una lista unidireccional que solo se puede iterar una vez. Lo cual es algo que no nos gusta). Y eso es todo.

Ramillies
fuente
Cambiar @(.[] Z- .[1..*])a [.[] Z-.[1..*]]debería guardar dos bytes.
nwellnhof
4

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

Gracias PunPun1000 por 51 bytes.
Gracias Nevay por 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);}

Pruébalo en línea!

Pruébelo en línea (versión de 198 bytes)

Entonces, esta es la primera vez que publico aquí en PPCG (y la primera vez que hago un desafío de código de golf). Cualquier crítica constructiva es bienvenida y apreciada. Traté de seguir las pautas para publicar, si algo no está bien, no dude en señalarlo.

Versión embellecida:

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é
fuente
3
Bienvenido al sitio!
DJMcMayhem
En lugar de importar esos módulos, puede usarlosjava.util.stream.IntStream k = java.util.Arrays.stream(a);
PunPun1000 el
De hecho, hay algunos cambios que puede hacer de forma gratuita. 1) publicno necesita ser incluido en el conteo de bytes. 2) No debería aceptar un segundo parámetro, pero eliminarlo puede ahorrar bytes. 3) puede eliminar algunos corchetes innecesarios allí
PunPun1000
4) No es un ahorrador, pero debe incluir un TIO si es posible, aquí hay un ejemplo con esas sugerencias en 198 bytes TIO
PunPun1000
1
140 bytes
Nevay
3

Haskell, 46 bytes

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

esto simplemente se repite - zipWith(-)l$last les la lista de diferencias de l. y ges la función que responde a la pregunta.

orgulloso Haskeller
fuente
La solución recursiva fue la buena.
jferard
@jferard eso es muy cierto
orgulloso Haskeller
3

Kotlin , 77 bytes

primera publicación, trató de editar la última respuesta en kotlin 2 veces; D

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

tomó parte de prueba de @jrtapsell

TryItOnline

cab404
fuente
Bienvenido a PPCG! Buena primera respuesta, un outgolf también.
H.PWiz
3

APL (Dyalog Classic) , 22 17 bytes

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

Pruébalo en línea!

¡Gracias a @ngn por -5 bytes!

¿Cómo?

  • { ... }, la función
  • 1=≢∪⍵:0, si cada elemento es igual en el argumento, devuelve 0
  • 1+∇2-/⍵, de lo contrario, devuelve 1 + nde las diferencias (que es n-1, por lo tanto, agregar una a ella da n)
Zacharý
fuente
es más corto si se sacrifica la cola-recursividad:{1=≢∪⍵:0⋄1+∇2-/⍵}
NGN
2

Jalea , 7 bytes

IÐĿEÐḟL

Pruébalo en línea!

Explicación

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 gracias a Jonathan Allan

Hiperneutrino
fuente
1
@Gryphon Hecho! :)
HyperNeutrino
IÐĿEÐḟLpara siete (veo que Miles también encontró un siete usando recursividad).
Jonathan Allan
@JonathanAllan Cool gracias!
HyperNeutrino
2

05AB1E , 7 bytes

[DË#¥]N

Pruébalo en línea!

Explicación

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

JavaScript (ES6), 58 bytes

f=a=>+(b=a.slice(1).map((e,i)=>e-a[i])).some(e=>e)&&1+f(b)
Neil
fuente
+0, no suficiente Jquery: p. Realmente, sin embargo, +1, buen trabajo, sé que nunca podría jugar golf en JS.
Zacharý
2

Python 2 , 65 bytes

-7 bytes gracias a 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

Pruébalo en línea!

totalmente humano
fuente
Guardar un byte de inicialización ca 1, decrementar y luego usar print-c.
Jonathan Allan
Ahorre seis más convirtiéndolo en una función recursiva: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
¿Soy solo yo o el cambio a una lambda recursiva no guarda suficientes bytes? : P Gracias!
totalmente humano
Creo que esto necesita un max(...,0)para pasar los [1, 1, 1, 1, ...]casos de prueba.
Yonatan N
2

Dyalog APL, 19 bytes

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

Explicación:

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

k , 21 bytes

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

Esto funciona en k, pero no en oK, porque el bucle while de oK se ejecuta antes de verificar la condición (en lugar de verificar primero la condición y luego ejecutar el código). Por lo tanto, en OK, el 1 1 1 1 1ejemplo no funcionará correctamente.

¡Prueba oK en línea!

Ejecutando el ejemplo k con 1 1 1 1 1 1 en el intérprete k.

Explicación:

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

Haskell , 66 61 60 bytes

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

Pruébalo en línea!

Guardado 5 bytes gracias a Christian Sievers

Guardado 1 byte gracias a proud-haskeller

iterate(z(-)) calcula las listas de diferencias.

or.z(/=) prueba si hay elementos no iguales en esas listas.

length.takeWhile cuenta las listas de diferencias con elementos no iguales.

jferard
fuente
Creo que puedes probar elementos no iguales conor.z(/=)
Christian Sievers
@ChristianSievers gracias! Eso era obvio, pero no lo vi ...
jferard
También puede usar z=(=<<tail).zipWith, un byte más corto
orgulloso haskeller
@proudhaskeller y más elegante, como siempre con definiciones sin puntos. ¡Gracias!
jferard
2

Japt , 7 bytes

El mismo enfoque (pero derivado de forma independiente) que Justin con una implementación diferente.

£=äaÃèx

Pruébalo


Explicación

Entrada implícita de la matriz U.

£   Ã

Mapa sobre cada elemento.

äa

Tome cada par secuencial ( ä) de elementos Uy reduzca la diferencia absoluta ( a).

=

Reasigna esa matriz a U.

èx

Count ( è) el número de sub-arrays que devuelven verdadero (es decir, distinto de cero) cuando se reduce por adición.

Lanudo
fuente
1

TI-Basic, 19 bytes

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

Por defecto, las variables comienzan en cero. Además, nunca pensé que estaría usando IS>(para algo útil.

Timtech
fuente
1

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

-1 byte gracias a Kevin Cruijssen

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

Debe recibir 0 cuando se llama para que funcione correctamente. También incluido en el recuento de bytes:

using System.Linq;

Pruébalo en línea!

Explicación:

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

Versión iterativa 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;}

Pruébalo en línea!

Grzegorz Puławski
fuente
1
Puede eliminar el espacio redundante en (y,z)=>y-z. Pero buena respuesta, +1 de mi parte.
Kevin Cruijssen
@KevinCruijssen gracias! Además, vaya.
Grzegorz Puławski
1

Clojure, 62 bytes

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

Muy bien =puede tomar cualquier número de argumentos, y un solo argumento es idéntico a "sí mismo". (apply = [1 2 3])se ejecuta como (= 1 2 3).

NikoNyrh
fuente
Bien, exactamente lo que estaba tratando de hacer, pero estaba luchando por una diferencia por pares compacta. Eso es genial, tendré que recordar eso para el futuro.
MattPutnam
1

Pyth , 15 bytes

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

Verifique todos los casos de prueba.

¿Cómo?

Explicación # 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.
Sr. Xcoder
fuente
-1 byteWtl{Q=hZ=.+Q)Z
Dave
@Dave Aún mejor: WP{Q=hZ=.+Q)Z. ¡Gracias!
Sr. 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

Pruébalo en línea!

Ingrese como una lista de números separados por un espacio.

Xcali
fuente
0

Pyth, 10 bytes

tf!t{.+FQt

Si podemos indexar desde 1, podemos guardar un byte eliminando el inicio t.

Pruébalo en línea

Explicación

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.

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

Embellecido

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

Prueba

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
fuente
Si alguien puede editar para corregir mis consejos idioma, por favor, me parece que no puede hacer que funcionen
jrtapsell
Es lang-kotlin, no simplemente kotlin, en las sugerencias de resaltador.
Ruslan
0

Swift 4 , 90 bytes

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

Implementación alternativa basada en cierre:

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

Casos de prueba:

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 - Restablece a Monica
fuente