Другой путь вперед


23

Учитывая список целых чисел, производите прямую разницу в указанном порядке / глубине.

Для списка целых чисел:

(10, 18, -12, 4, 8, -3, -5, 67, 9, 14)

Различия вперед на разных ордерах / глубинах:

0   10,   18,  -12,    4,    8,   -3,   -5,  67,  9,  14
1      8,  -30,   16,    4,  -11,   -2,   72, -58,  5
2       -38,   46,  -12,  -15,    9,   74, -130, 63
3           84,  -58,   -3,   24,   65, -204, 193
4            -142,   55,   27,   41, -269, 397
5               197,  -28,   14, -310, 666
6                 -225,   42, -324, 976
7                    267, -366, 1300
8                      -633, 1666
9                         2299

Так что с вводом

4, (10, 18, -12, 4, 8, -3, -5, 67, 9, 14)

Вы бы вернули список

(-142,   55,   27,   41, -269, 397)

вход

Вход может быть через STDIN или функциональные параметры.

Целое число, указывающее глубину для возврата. Это будет 0 к длине списка минус 1

Список целых чисел для расчета прямой разницы для

Выход

Выход может быть через STDOUT или возвращен функцией.

Прямые различия для указанной глубины в виде списка целых чисел

правила

Встроенные и сторонние функции, которые делают это напрямую, не допускаются.

Стандартные ограничения лазейки применяются.

Самый короткий код выигрывает

Ответы:


19

J 15 9 7 байт

Очень просто. Принимает глубину и список как левый и правый аргументы.

-~/\~&2

Как явное определение без всяких наговорок, это сводится к

4 : '(2 -~/\ ])^:x y'
  • -~/\~&2 y- Разница форвардов y.
  • x -~/\~&2 y- xЧетвертое различие y.

Если бы я сделал серьезное (т.е. не относящееся к гольфу) определение этой функции, я, вероятно, сделал бы что-то вроде этого:

(}. - }:) : ($:@[&0)

Монадический случай вычисляет прямую разность, тогда как двоичный случай вычисляет x-е прямую разность.

Еще проще, но не совсем равным:

+/\inv

+/\дает вектор сумм префиксов аргумента. inv(определяется как ^:_1) это соединение, которое инвертирует глагол. Это работает везде, где J знает, как инвертировать глагол, а в случае +/\J знает, как это сделать.


3
Это показывает силу наречий и союзов, как -единственный глагол в этой функции.
Рандомра

14

Python, 61 59 байт

f=lambda n,L:n and f(n-1,[x-y for x,y in zip(L[1:],L)])or L

Здесь мы выполняем вычитание, архивируя все, кроме последнего списка, со всеми, кроме первого в списке. zip(L[1:],L)эквивалентно zip(L[1:],L[:-1]), в связи zipс характером взятия минимальной длины двух списков:

>>> zip([1,2,3],[4,5])
[(1, 4), (2, 5)]

Альтернатива такая же длинная (только Python 2):

f=lambda n,L:n and f(n-1,map(int.__sub__,L[1:],L[:-1]))or L

К сожалению, Python 2 не обрезает конец списка, поэтому я не могу этого сделать map(int.__sub__,L,L[1:]). Досадно, что Python 3 делает , но mapбольше не возвращает список, так что в итоге получается больше байта (60 байт):

f=lambda n,L:n and f(n-1,list(map(int.__sub__,L[1:],L)))or L

Однако, если мы позволим вводу быть глубиной, за которой следует список, такой как f(3, 2, 5, 6, 7, 5, 10, 25)(т.е. глубина 3 и список [2, 5, 6, 7, 5, 10, 25]), то это будет 56 байтов :

f=lambda n,*T:n and f(n-1,*map(int.__sub__,T[1:],T))or T

Вот еще одна альтернатива, которая действительно раздражает любого, кто видел это в рабочем коде (этот уничтожает первоначальный список):

f=lambda n,L:n and f(n-1,[L[1]-L.pop(0)for _ in L[1:]])or L

Ваш последний код неверен. Вам нужно будет L[1]-L.pop(0)вместо этого.
mbomb007

@ mbomb007 Спасибо за улов. Это было неловко - у меня были аргументы вокруг неправильного пути все время.
Sp3000

Это было близко, но что-то вроде любой другой глубины поменяло знаки.
mbomb007

9

Mathematica 23 57 23 байта

Предложение Мартина Бюттнера, использующее возможность вычитания.

 Rest@#-Most@#&~Nest~##&

например

Rest@# - Most@# &~Nest~## & @@ {{10, 18, -12, 4, 8, -3, -5, 67, 9, 14}, 4}

{-142, 55, 27, 41, -269, 397}


Rest@#-Most@# выполняет вычитание, которое дает различия.

Nest выполняет указанную операцию указанное количество раз, работая всегда с самым последним списком.


7

Haskell, 40 34 байта

n#l=iterate(zipWith(-)=<<tail)l!!n

Пример использования: 4 # [10,18,-12,4,8,-3,-5,67,9,14]какие выходы [-142,55,27,41,-269,397].

Как это работает: повторно рассчитать разницу между соседними элементами и сохранить промежуточные результаты в списке. Возьмите nэлемент th из этого списка.

Редактировать: @Zgarb нашел 6 байтов для сохранения. Потрясающе!


Вы можете использовать функцию монады и сократить лямбда до (zipWith(-)=<<tail).
Згарб

7

JavaScript (ES6), 52 49 байт

Простая рекурсивная функция, используемая mapдля сканирования массива и sliceудаления первого элемента при каждом рекурсивном вызове.

Редактировать 3 байта сохранено, спасибо @DocMax, действительно умное предложение

F=(n,l)=>n?F(n-1,l.slice(1).map((a,k)=>a-l[k])):l

Тест в консоли Firefox / FireBug

for(i=0;i<10;i++)console.log(F(i,[10, 18, -12, 4, 8, -3, -5, 67, 9, 14]))

[10, 18, -12, 4, 8, -3, -5, 67, 9, 14]
[8, -30, 16, 4, -11, -2, 72, -58, 5]
[-38 , 46, -12, -15, 9, 74, -130, 63]
[84, -58, -3, 24, 65, -204, 193]
[-142, 55, 27, 41, -269, 397 ]
[197, -28, 14, -310, 666]
[-225, 42, -324, 976]
[267, -366, 1300]
[-633, 1666]
[2299]


1
Кусочек перед тем карте , чтобы эффективно избежать необходимости pи сохранить 3 символов: H=(n,l)=>n?H(n-1,l.slice(1).map((a,k)=>a-l[k])):l.
DocMax

6

CJam, 15 байтов

l~{{_@-\}*;]}*p

Принимает ввод как массив в стиле CJam, а затем глубину:

[10 18 -12 4 8 -3 -5 67 9 14] 4

и печатает результат в виде массива в стиле CJam.

Проверьте это здесь.

объяснение

l~              "Read and eval input.";
  {         }*  "Repeat this block N times, which computes the forward differences.";
   {    }*      "Fold this block onto the list - this is quite an abuse of folding semantics.";
    _           "Duplicate the current element (for the use in the next difference).";
     @          "Pull up the other copy of the last element.";
      -         "Subtract.";
       \        "Swap the difference and the other copy of the current element.";
          ;     "Discard the last element.";
           ]    "Wrap everything in an array again.";

5

Java, 122 119 байт

int[]a(int[]a,int b){if(b<1)return a;int e=a.length-1,c[]=new int[e],i=e;for(;i-->0;)c[i]=a[i+1]-a[i];return a(c,b-1);}

Пример использования: http://ideone.com/ALgYez

3 байта благодаря Geobits: v)>


Вы должны избавиться от второго int и просто назначить i=eс другими.
Geobits

5

> <> 53 50 байтов

l:[2-&\~~]r1-:?!vr
&}-@:$/!?&:-1
:;!? &&  lo*84n~<       

Использование: Предварительно заполните стек (-v в интерпретаторе Python) сначала глубиной, а затем целыми числами.

Например:

forward.fish -v 3 2 5 6 7 5 10 25

Возвращает

2 -3 10 3

Спасибо Sp3000 за помощь.


1
Можно ли использовать ?!и перемещать некоторые компоненты, а не 0=??
Sp3000

Хорошо поймал! Это помогает куче
Cirpis

5

Прелюдия , 95 92 79 78 байт

?    (1-vv- # ) v  !
  ?     #   ^   #
?(1-)   1  (#)  1)(#)
  1   #(# ) 1  (#

Формат ввода

N
M
n_1
n_2
...
n_M

где Nглубина различий и Mколичество целых чисел во входных данных. Добавление Mбыло необходимо, потому что Prelude не может отличить a 0от конца ввода. Вывод также в виде целого числа, разделенного символом новой строки. Мне пришлось принять слегка скорректированную спецификацию Prelude, которую мы разработали для этой задачи , потому что стандартная Prelude считывает целые числа как байтовые значения, что делает невозможным ввод отрицательных чисел. По сути, это интерпретатор Python с дополнительным NUMERIC_INPUTфлагом.

Для справки есть только 48 38 37 непробельных символов - остальные были просто необходимы для правильного выравнивания кода.

объяснение

В Prelude каждая строка представляет собой отдельный «голос», который работает в своем собственном стеке. Программа выполняется колонка за колонкой, где отдельные голоса используются для работы «параллельно». Все команды представляют собой одиночные символы, а круглые скобки представляют собой циклы типа Brainfuck (которые вводятся и повторяются всякий раз, когда вершина стека отлична от нуля). Обратите внимание, что вертикальная позиция закрывающей круглой скобки не имеет значения - помещение ее в другой голос по-прежнему считается совпадающим с самой последней открывающей скобкой, и стек, который проверяется на условие цикла, всегда является тем голосом, в котором он (появился. Теперь к этой программе ...

Программа в основном может быть разделена на две части. Две нижние строки просто используются для большинства циклов в программе (за исключением основного цикла N), передавая 1s вперед и назад. Две верхние строки содержат основной цикл и фактическое различие. Следующая аннотация имеет транспонированный код, поэтому я могу комментировать отдельные столбцы:

? ?   # Read two integers. Read instructions are processed top to bottom, so the first voice 
      # reads N and the third voice reads M.
  (   # Start a loop on the third voice. This loop will execute M times, reading the input list
      # and pushing M 1s onto the fourth voice - i.e. a unary representation of M.
 ?11  # Read an integer onto the second voice, push 1s onto the third and fourth voice.
  -   # Subtract the 1 from the third voice, decrementing M down to 0.
  )   # End of loop, if the third voice is not 0 yet, to back two columns.
(     # Start a loop on the first voice. This is the main loop and will execute N times. Each
      # iteration will compute the forward differences once and thereby shorten the list by one
      # element and also reduce the stack of 1s on the bottom voice by one.
1  #  # Push a 1 onto the first voice and pop a 1 from the last. Together with the next column,
      # this decrements both N and (the unary) M.
-  (  # Subtract the 1 from the first voice (decrementing N), and start a loop on the fourth 
      # voice over whatever is left of M (the length of the resulting difference list). Note 
      # that this column is *not* part of the loop, so the - on the first voice will only be 
      # executed once. This loop builds the differences in reverse order on the first voice.
v#1#  # Pop a 1 from the fourth voice and push a 1 onto the third. This loops over M while
      # shifting its unary representation to the other stack. In addition, shift the top stack
      # element from the second to the first voice.
v     # Copy the next element from the second voice to the first, without popping.
-  )  # Subtract the two elements on the first voice and end the loop if the fourth voice is 
      # empty. Note that his column *is* part of the loop.
  (   # Start a loop on the third voice. This is another loop over M, shifting the stack of 1s 
      # back to the fourth voice, and reversing the differences by shifting them onto the 
      # second.
#^#1  # As stated above, shift an element from the first to the second voice, a 1 from the
      # third to the fourth.
  )   # End the loop. After this point, we're back to the original situation, except that the
      # second voice has been replaced by its differences. The bottom stack element the
      # previous list is also still on that stack, but the decreasing loop lengths on the third
      # and fourth voices ensures that this element is never touched again.
)     # End the main loop when N has been reduced to 0.
   (  # Start another loop over the remaining list length, shifting and reversing the result.
v#1#  # Shift a 1 back to the third voice and an element from the second to the first voice.
  )   # End the loop. Note that this parenthesis is not on the same voice as the corresponding
      # opening parenthesis, but its exact position is irrelevant. Moving it to this voice
      # saves a byte.
  (   # Start one last loop over the length of the result.
! #   # Pop a 1 from the third voice while printing (and popping) one element of the result.
  )   # End the loop.

5

Python, 70 68 67 59 байт

f=lambda x,n:n and f([x[1]-x.pop(0)for i in x[1:]],n-1)or x

Версия без гольфа, прежде чем я стал рекурсивным:

def f(x,n):
    for j in range(n):
        for i in range(len(x)-1):
            x[i]=x[i+1]-x[i]
    return x[:-n]

5

R, 48 39 46 44 байтов

Рекурсия!

function(x,y)if(x)Recall(x-1,diff(y)) else y
  • xчисло итераций для выполнения и yвектор целых чисел.
  • if(x)верно пока x>0.
  • Recall вызывает текущую функцию, но с новыми аргументами.
  • Diff выводит различия между последовательными элементами списка / вектора.

Предыдущие версии:

#does not work for x=0:
function(x,y){for(i in 1:x)y=diff(y);y}

#does not use diff function:
function(x,y){for(i in 1:x)y=y[-1]-head(y,-1);y}

y[-1]       is a list minus its first element
head(y,-1)  is a list minus its last element

Есть ли лучший способ повторить функцию сравнения х раз? Использование цикла for кажется чрезмерным.
freekvd

Существует Reduce, но я думаю, это будет стоить больше символов.
MickyT

Есть одна маленькая проблема. При вызове с глубиной 0 он возвращает глубину 2
MickyT

Пошел другой подход, проблема решена, но пришлось добавить 7 символов.
freekvd

2
Хорошее использование Recall().
Алекс А.

3

Python, 92 87 86 байт

def a(b,c):
 if c<1:return b
 d=[];e=b[0]
 for f in b[1:]:d+=f-e,;e=f
 return a(d,c-1)

Это мой первый питон гольф. Любые предложения будут оценены :)

5 6 байт благодаря Sp3000: D


Я бы порекомендовал понимание списка.
mbomb007

Вы можете превратить appendв d+=f-e,. В общем, для Code-Golf вам никогда не понадобится использовать L.appendиз-за этого.
Sp3000

3

c, 68 55 байтов

f(int *l){for(--l[-1]?f(l):0;*l;l++)*l=l[1]-*l;*--l=0;}

Это может занять немного свободы с входной спецификацией немного. Массив int сконструирован таким образом, что элемент 0 - это глубина, а элементы с 1 по (n + 1) - это элементы списка ввода от 0 до n. Затем адрес элемента 1 передается функции.

Массив должен заканчиваться нулем. Массив редактируется на месте.

Например:

#include <stdio.h>

f(int *l){for(--l[-1]?f(l):0;*l;l++)*l=l[1]-*l;*--l=0;}

int main (int argc, char **argv)
{
  int list[] = {4, 10, 18, -12, 4, 8, -3, -5, 67, 9, 14, 0};
  int *elem;

  f(list + 1);

  for (elem = list + 1; *elem; elem++) {
    printf("%d, ", *elem);
  }
}

http://ideone.com/m5PDgF


Почему вы оставили место в int *l?
Джонатан Фрех

2

Powershell 115 111 байт

$p={param($a, $b)0..($a-1)|%{$b=@($l=$b.length;for($i=0;$i-lt$l;$i++){$b[$i+1]-$b[$i]})[0..($l-2)]};$b-join','}

Выполнить так:

.$p 4 @(10,18,-12,4,8,-3,-5,67,9,14)

Выход:

-142,55,27,41,-269,397

Перемещение фигурной скобки в другое место позволяет отображать каждый шаг к ответу.

8,-30,16,4,-11,-2,72,-58,5
-38,46,-12,-15,9,74,-130,63
84,-58,-3,24,65,-204,193
-142,55,27,41,-269,397

2

STATA, 126 байт

di _r(a)_r(b)
token $b
gl $c=wordcount($b)
forv x=1/$a{
gl $c--
forv y=1/$c{
loc `y'=``y'+1'-``y''
}
}
forv z=1/$c{
di ``z''
}

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

Сначала он преобразует список целых чисел (который он рассматривает как 1 длинную строку) в список локальных переменных с именами 1,2,3, ... Затем он вычисляет прямые разности, устанавливая значение y-й локальной переменной равным значение y + 1-й локальной переменной минус значение y-й локальной переменной (то есть 18-10 = 8), которая перезаписывает существующие значения только после использования. Это делает это $ a (значение глобальной переменной a) раз. Затем он отображает значение каждой локальной переменной, по 1 за раз.


+1 за объяснение. Это удивительно запутанный способ обработки списков.
Згарб

@ Zgarb, я не знаю, как STATA может принимать входные данные в виде массива / списка, кроме как через файл (который не будет работать здесь из-за другого ввода). Вот почему это должно работать так.
отмечается

2

T-SQL, слишком много :)

Когда я впервые увидел эту проблему, я подумал, есть ли способ сделать это в запросе. Хотя это тривиально для большинства языков, для SQL-запросов это не так уж и много.

Входные данные идут в переменные @ (для глубины) и @L для целочисленного списка. @L - определяемый пользователем тип таблицы

CREATE TYPE L AS TABLE(n INT IDENTITY(0,1),v INT)

Настройка входа

DECLARE @L L,@ INT=4
INSERT @L(v)values(10),(18),(-12),(4),(8),(-3),(-5),(67),(9),(14)

Запрос с некоторыми комментариями

WITH R AS( 
    -- Recursive query to calculate the level of a pascal triangle with alternating negatives
    -- For 4 this is 1 -4  6 -4  1  
    SELECT 1c,0g UNION ALL SELECT-c*(@-g)/(g+1),g+1FROM r WHERE g<@
    ),
    O AS( 
    --Multiple N values of list by reversed pascal triangle values
    --shifting the start for each iteration (list length) - N
    SELECT c*v v,F 
    FROM @L L 
        CROSS APPLY(
            SELECT TOP((SELECT COUNT(*)FROM @L)-@)ROW_NUMBER()OVER(ORDER BY(SELECT\))-1F FROM sys.all_views a,sys.all_views b)c 
        JOIN R ON N=F+@-G
    )
-- Sum the multiplied values
SELECT SUM(V)FROM o GROUP BY F ORDER BY F

Результат

-142
55
27
41
-269
397

2

Japt -h , 17 5 байт

12 байтов сохранено благодаря @Shaggy

VÆ=än

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



Или другая реализация дает 12 байтов
Shaggy

Вы можете заменить äÏ-Xс änв обоих из них , чтобы спасти больше 2 байта.
Лохматый

Получил до 5 байтов !
Лохматый

@ Шагги, черт возьми, ты слишком хорош в японском xD Ты должен опубликовать свой 5-
байтовый

0

SmileBASIC, 76 байт

Наконец, причина для использования ARYOP!

DEF F L,D
IF!D THEN@R
DIM B[0]COPY B,L
T=SHIFT(L)ARYOP 1,L,L,B
F L,D-1@R
END

0

Clojure, 47 байтов

#(if(= 0 %)%2(recur(dec %)(map -(rest %2)%2))))

Простая рекурсия по анонимной функции. Вы сохраняете 1 байт, если порядок аргументов поменялся местами, как сейчас %2происходит чаще, чем %.



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.