N-е различия

26

В математике одним из способов выяснить, какой тип данного отношения (линейный, квадратичный и т. Д.) Является вычисление различий. Для этого вы берете список значений y, для которых промежуток между соответствующими значениями x одинаков, и вычитаете каждое из числа над числом над ним, создавая список чисел на один короче предыдущего списка. Если результирующий список полностью состоит из одинаковых чисел, то отношение имеет разность 1 (оно является линейным). Если они не идентичны, то вы повторите процедуру в новом списке. Если они теперь идентичны, отношение имеет разность 2 (она квадратичная). Если они не идентичны, вы просто продолжаете этот процесс, пока они не будут идентичны. Например, если у вас есть список значений y [1,6,15,28,45,66] для постепенно увеличивающихся значений 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

Твое задание:

Напишите программу или функцию, которая, когда в качестве входных данных передается массив целых чисел, возвращает разницу отношения, описанного массивом, как описано выше.

Входные данные:

Массив целых чисел, который может иметь любую длину> 1.

Выход:

Целое число, представляющее разность отношений, описываемых входными данными.

Тестовые случаи:

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

Подсчет очков:

Это , на этом языке выигрывает наименьшая оценка в байтах на каждом языке. Самая низкая оценка в целом получает зеленую галочку.

Грифон - Восстановить Монику
источник
Может ли вход быть «недействительным», как и в случае, если вход не соответствует предоставленной спецификации, если мы допустим ошибку? Обеспечить -1 как выход?
Волшебная Урна Осьминога
Поведение не определено для неверного ввода (мне все равно, что делает ваш код)
Грифон - Восстановить Монику
Не должны [1,2,1]дать 2? [1,2,1] -> [1,-1] -> [-2]
HyperNeutrino
@HyperNeutrino, да, прости. У меня там был мозговой пердеть
Грифон - Восстановить Монику
Добавьте этот тест [1,3,9,26,66,150,313,610]-> 6если хотите
J42161217

Ответы:

10

Шелуха , 6 байт

Спасибо Лео за предоставленную мне возможность использовать его версию, которая работает для[1,1,1,1,1,1]

←VE¡Ẋ-

Попробуйте онлайн!

объяснение

   ¡     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
источник
2
Всякий раз, когда кто-то говорил, что Хаск - это новое желе, они были чертовски правы. > _ <
Захари
Черт, я собирался опубликовать это . Хорошая работа, хотя, +1!
Лев
@ Лео, контрольный пример, которого я не видел [1,1,1,1], могу ли я использовать твой?
H.PWiz
@ H.PW уверен, продолжай!
Лев
7

JavaScript (ES6), 47 байт

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

Контрольные примеры

Arnauld
источник
7

MATL , 8 байт

`dta}x@q

Попробуйте онлайн! Или проверьте все тестовые случаи .

объяснение

Это вычисляет последовательные различия итеративно, пока результат не будет нулем или пустым. На выходе получается требуемое количество итераций минус 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 байта

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

Попробуйте онлайн!

Принимает diffиз l, устанавливает его l, и проверяет , если результат содержит значения , отличные от нуля. Если это произойдет, приращение F(инициализируется как FALSEнеявно), и возвращается , F*1чтобы преобразовать FALSEв 0в том случае, если все lидентично уже.

Giuseppe
источник
Полная программа и +Fтрюк на 5 байтов . Аккуратный ответ, кстати!
JayCe
5

Mathematica, 49 байтов

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

спасибо @alephalpa за -6 байт и @hftf -1 байт

а вот еще один подход от @hftf

Mathematica, 49 байтов

Length@NestWhileList[Differences,#,!SameQ@@#&]-1&
J42161217
источник
(s=#;t=0;While[UnsameQ@@s,s=Differences@s;t++];t)&
алефальфа
1
UnsameQ[1,2,1]является ложным; !SameQ[1,2,1]правда. Я не думаю, что ручной цикл также сохраняет символы: Length@NestWhileList[Differences,#,!SameQ@@#&]-1&уже такой же длины, как у вас, после замены UnsameQна !SameQ.
hftf
4

Желе , 7 байт

-Iß$E?‘

Попробуйте онлайн!

объяснение

-Iß$E?‘  Input: array A
     ?   If
    E    All elements are equal
         Then
-          Constant -1
         Else
   $       Monadic chain
 I           Increments
  ß          Recurse
      ‘  Increment
миль
источник
Нерекурсивная альтернатива:IÐĿE€ċ0
Эрик Аутгольфер,
4

Джапт , 10 7 байт

è@=ä-)d

Попробуйте онлайн!

Полагается на то, что результат гарантированно будет в пределах длины входного массива.

объяснение

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

В конце концов, это будет отображать массив
[1, 3, 9, 26, 66, 150, 313, 610]в [true, true, true, true, true, true, false, false],
который содержит6 true s.

Предыдущая 10-байтовая версия

@=ä-)e¥0}a

Попробуйте онлайн!

Джастин Маринер
источник
4

Perl 6 , 37 байт

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

Попробуйте онлайн!

Объяснение: Функция принимает входные данные как один список. Затем он создает рекурсивную последовательность следующим образом: первый элемент является исходным списком ( $_), следующие элементы возвращаются при {@(@$_ Z- .[1..*])}вызове предыдущего элемента, и это повторяется до тех пор, пока условие не *.noneстанет истинным, что происходит только тогда, когда список либо пусто или содержит только нули (или, технически, другие значения фальси). Затем мы берем список и вычитаем 2 из него, что приводит его сначала к числовому контексту (а списки в числовом контексте равны количеству их элементов) и, в конце, возвращает на 2 меньше, чем количество элементов в список.

Странный блок {@(@$_ Z- .[1..*])}просто берет заданный список ( .[]- так называемый фрагмент дзен - индексирование с пустыми скобками дает весь список), упаковывает его с помощью оператора минус ( Z-) с тем же списком без первого элемента ( .[1..*]) и выводит его в список ( @(...)- нам это нужно, потому что zip возвращает только Seq, который в основном является односторонним списком, который может повторяться только один раз. Это то, что нам не нравится.) И это все.

Ramillies
источник
Изменение @(.[] Z- .[1..*])к [.[] Z-.[1..*]]необходимо сохранить два байта.
nwellnhof
4

Java 8, 191 + 58 = 249 198 140 байт.

Спасибо PunPun1000 за 51 байт.
Спасибо Невею за 58 байт.

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

Попробуйте онлайн!

Попробуйте онлайн (198 байт)

Итак, это мой первый пост здесь, в PPCG (и первый раз, когда я выполняю соревнования по коду). Любая конструктивная критика приветствуется и ценится. Я старался следовать правилам публикации, если что-то не так, не стесняйтесь указывать на это.

Украшенная версия:

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
Добро пожаловать на сайт!
DJMcMayhem
Вместо того, чтобы импортировать эти модули, вы можете просто использоватьjava.util.stream.IntStream k = java.util.Arrays.stream(a);
PunPun1000
На самом деле, есть несколько изменений, которые вы можете сделать бесплатно. 1) publicне нужно включать в число байтов. 2) Вы не должны принимать второй параметр, но его удаление может реально сохранить байты. 3) там можно убрать ненужные скобки
PunPun1000
4) Не заставка , но вы должны включать в себя TIO , если это возможно, вот пример с этими предложениями в 198 байт TIO
PunPun1000
1
140 байтов
Невай
3

Haskell, 46 байтов

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

это просто рекурсы - zipWith(-)l$last lэто список различий l. и gявляется функцией, которая отвечает на вопрос.

гордый хаскеллер
источник
рекурсивное решение было хорошим.
jferard
@jferard, это очень верно
гордый haskeller
3

Котлин , 77 байт

первый пост, пытался редактировать последний ответ на kotlin 2 раза; D

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

принял участие в тестировании от @jrtapsell

TryItOnline

cab404
источник
Добро пожаловать в PPCG! Хороший первый ответ, тоже вне себя.
H.PWiz
3

APL (Dyalog Classic) , 22 17 байтов

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

Попробуйте онлайн!

Спасибо @ngn за -5 байтов!

Как?

  • { ... }, функция
  • 1=≢∪⍵:0, если каждый элемент равен в аргументе, вернуть 0
  • 1+∇2-/⍵в противном случае вернуть 1 + nразличий (то есть n-1, добавив к нему одно, вы получите n)
Zachary
источник
короче, если пожертвовать хвостовой рекурсивностью:{1=≢∪⍵:0⋄1+∇2-/⍵}
нгн
2

Желе , 7 байт

IÐĿEÐḟL

Попробуйте онлайн!

объяснение

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 байт благодаря Джонатану Аллану

HyperNeutrino
источник
1
@ Грифон Готово! :)
HyperNeutrino
IÐĿEÐḟLдля семи (я вижу, Майлз также нашел семерку, используя рекурсию).
Джонатан Аллан
@JonathanAllan Круто, спасибо!
HyperNeutrino
2

JavaScript (ES6), 58 байт

f=a=>+(b=a.slice(1).map((e,i)=>e-a[i])).some(e=>e)&&1+f(b)
Нил
источник
+0, недостаточно Jquery: с. Правда, +1, отличная работа, я знаю, что никогда не смогу играть в гольф в JS.
Захари
2

Python 2 , 65 байт

-7 байт благодаря Джонатану Аллану.

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

Попробуйте онлайн!

totallyhuman
источник
Сохранить байты Инициирования cв 1, уменьшающееся , а затем с помощью print-c.
Джонатан Аллан
Сохраните еще шесть, превратив это в рекурсивную функцию:f=lambda l,c=1:any(l)and f([j-i for i,j in zip(l,l[1:])],c-1)or-c
Джонатан Аллан
Это только у меня или переключение на рекурсивную лямбду не экономит достаточно байтов? : P Спасибо!
полностью человек
Я думаю, что это нужно, max(...,0)чтобы пройти [1, 1, 1, 1, ...]тестовые случаи.
Йонатан N
2

Дьялог АПЛ, 19 байт

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

Объяснение:

≢                      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
Это работает? ≢-1+∘≢2-/⍣{1=≢∪⍵}⊢
Захари
2

к , 21 байт

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

Это работает в k, но не в oK, потому что цикл while в oK выполняется перед проверкой условия (в отличие от первой проверки условия, а затем запуска кода). Таким образом, в ок, 1 1 1 1 1пример не будет работать должным образом.

Попробуй ОК онлайн!

Выполнение примера k с 1 1 1 1 1 1 в интерпретаторе k.

Объяснение:

   (        )       \ /while(
    ~&/               /      not(min(
       1_=':          /              check equality of all pairs))) {
             (1_-':)  /    generate difference list
                      /    append to output }
#1_                   /(length of output) - 1
zgrep
источник
~&/1_=':->1<#?
нгн
2

Haskell , 66 61 60 байт

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

Попробуйте онлайн!

Сохранено 5 байтов благодаря Christian Sievers

Сохранено 1 байт благодаря гордому haskeller

iterate(z(-)) вычисляет списки различий.

or.z(/=) проверяет, есть ли в этих списках неравные элементы.

length.takeWhile подсчитывает списки различий с неравными элементами.

jferard
источник
Я думаю, что вы можете проверить на or.z(/=)
Кристиан Сиверс
@ChristianSievers спасибо! Это было очевидно, но я этого не видел ...
17
Вы также можете использовать z=(=<<tail).zipWith, один байт короче
гордый haskeller
@proudhaskeller и более элегантный, как всегда с точечными определениями. Благодарность!
jferard
2

Japt , 7 байт

Тот же подход (но независимо получаемый), как у Джастина с другой реализацией.

£=äaÃèx

Попробуй это


объяснение

Неявный ввод массива U.

£   Ã

Карта над каждым элементом.

äa

Возьмите каждую последовательную пару ( ä) элементов Uи уменьшите ее на абсолютную разницу ( a).

=

Переназначить этот массив на U.

èx

Count ( è) количество подмассивов, которые возвращают true (т. Е. Не ноль) при уменьшении путем сложения.

мохнатый
источник
1

TI-Basic, 19 байтов

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

По умолчанию переменные начинаются с нуля. Кроме того, никогда не думал, что буду использовать IS>(что-нибудь полезное.

Timtech
источник
1

C # (.NET Core) , 70 69 + 18 байт

-1 байт благодаря Кевину Круйссену

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

Должно быть дано 0 при вызове для правильной работы. Также включено в число байтов:

using System.Linq;

Попробуйте онлайн!

Объяснение:

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

Итерационная версия 84 + 18 байт:

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

Попробуйте онлайн!

Гжегож Пулавски
источник
1
Вы можете удалить лишнее пространство в (y,z)=>y-z. Но хороший ответ, +1 от меня.
Кевин Круйссен,
@KevinCruijssen спасибо! Кроме того, упс.
Гжегож Пулавский
1

Clojure, 62 байта

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

Хорошо =может принимать любое количество аргументов, и один аргумент идентичен «самому себе». (apply = [1 2 3])исполняется как (= 1 2 3).

NikoNyrh
источник
Хорошо, именно то, что я пытался сделать, но я боролся за компактные попарные разности. Это замечательно, я должен помнить это на будущее.
MattPutnam
1

Pyth , 15 байт

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

Проверьте все контрольные примеры.

Как?

Объяснение № 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.
Мистер Xcoder
источник
-1 байтWtl{Q=hZ=.+Q)Z
Дейв
@ Дейв Еще лучше WP{Q=hZ=.+Q)Z. Благодарность!
г-н Xcoder
0

Perl 5 , 83 + 1 (-a) = 84 байта

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

Попробуйте онлайн!

Введите в виде списка чисел, разделенных одним пробелом.

Xcali
источник
0

Pyth, 10 байт

tf!t{.+FQt

Если мы можем индексировать от 1, мы можем сохранить байт, удалив ведущий t.

Попробуйте онлайн

объяснение

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

Котлин , 83 байта

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

украшенный

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

Тест

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
источник
Если кто-то может отредактировать, чтобы исправить мои языковые подсказки, пожалуйста, я не могу заставить их работать
jrtapsell
Это lang-kotlinне просто kotlinв подсказках.
Руслан
0

Swift 4 , 90 байт

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

Альтернативная реализация на основе замыкания:

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

контрольные примеры:

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!")
}
Александр - Восстановить Монику
источник