Inna droga naprzód


23

Podana lista liczb całkowitych daje różnicę w przód przy określonej kolejności / głębokości.

Aby uzyskać listę liczb całkowitych:

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

Różnice w przód dla różnych zleceń / głębokości są następujące:

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

Więc z wejściem

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

Zwróciłbyś listę

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

Wkład

Wejście może odbywać się za pośrednictwem STDIN lub parametrów funkcji.

Liczba całkowita określająca głębokość do zwrócenia. Będzie to 0 do długości listy minus 1

Lista liczb całkowitych, dla których należy obliczyć różnicę w przód

Wydajność

Dane wyjściowe mogą być przesyłane przez STDOUT lub zwracane przez funkcję.

Różnice w przód dla określonej głębokości jako lista liczb całkowitych

Zasady

Wbudowane i zewnętrzne funkcje, które robią to bezpośrednio, są niedozwolone.

Obowiązują standardowe ograniczenia luk .

Najkrótszy kod wygrywa

Odpowiedzi:


19

J, 15 9 7 bajtów

Bardzo łatwe. Pobiera głębię i listę jako argumenty lewy i prawy.

-~/\~&2

Jako wyraźna definicja bez wszystkich przysłówkowych podstępów, ogranicza się to do

4 : '(2 -~/\ ])^:x y'
  • -~/\~&2 y- Różnica w przód o y.
  • x -~/\~&2 y- xTrzecia różnica w przód o y.

Gdybym zrobił poważną (tj. Nie golfową) definicję tej funkcji, prawdopodobnie zrobiłbym coś takiego:

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

Przypadek monadyczny oblicza różnicę do przodu, podczas gdy przypadek dyadyczny oblicza x-tą różnicę do przodu.

Jeszcze prostsze, ale nie do końca równe:

+/\inv

+/\zwraca wektor sum przedrostków argumentu. inv(zdefiniowany jako ^:_1) to koniunkcja, która odwraca czasownik. Działa to wszędzie tam, gdzie J wie, jak odwrócić czasownik, aw przypadku +/\J wie, jak to zrobić.


3
To pokazuje moc przysłówków i spójników, ponieważ -jest to jedyny czasownik w tej funkcji.
randomra

14

Python, 61 59 bajtów

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

Tutaj wykonujemy odejmowanie poprzez skompresowanie wszystkich oprócz ostatniej listy ze wszystkimi oprócz pierwszej listy. zip(L[1:],L)jest równoważny zip(L[1:],L[:-1]), ze względu na zipcharakter przyjęcia minimalnej długości dwóch list:

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

Alternatywa, która jest równie długa (tylko Python 2):

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

Niestety, Python 2 nie odcina końca listy, więc nie mogę tego zrobić map(int.__sub__,L,L[1:]). Irytująco, Python 3 robi , ale mapnie zwraca listę więc ten kończy się bajt więcej (60 bajtów):

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

Jeśli jednak zezwolimy, aby dane wejściowe były głębokością, po której następowała lista typu f(3, 2, 5, 6, 7, 5, 10, 25)(tj. Głębokość 3 i lista [2, 5, 6, 7, 5, 10, 25]), to jest to 56 bajtów :

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

Oto kolejna alternatywa, która naprawdę zirytowałaby każdego, kto zobaczył to w kodzie produkcyjnym (ten niszczy oryginalną listę):

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

Twój ostatni kod jest nieprawidłowy. Zamiast tego będziesz potrzebować L[1]-L.pop(0).
mbomb007

@ mbomb007 Dzięki za złapanie. To było niezręczne - cały czas miałem sprzeczne argumenty.
Sp3000,

Było blisko, ale coś jak każda inna głębokość zamieniła znaki.
mbomb007

9

Mathematica 23 57 23 bajty

Sugestia Martina Büttnera, wykorzystująca możliwości odejmowania odejmowania.

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

na przykład

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

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


Rest@#-Most@# wykonuje odejmowanie, które daje różnice.

Nest wykonuje tę operację określoną liczbę razy, działając zawsze na najnowszej liście.


7

Haskell, 40 34 bajtów

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

Przykład użycia: 4 # [10,18,-12,4,8,-3,-5,67,9,14]które wyjścia [-142,55,27,41,-269,397].

Jak to działa: wielokrotnie oblicz różnicę między elementami sąsiednimi i zapisz wyniki pośrednie na liście. Weź nelement th z tej listy.

Edycja: @Zgarb znalazł 6 bajtów do zapisania. Niesamowite!


Możesz użyć funkcji monad i skrócić lambda do (zipWith(-)=<<tail).
Zgarb

7

JavaScript (ES6), 52 49 bajtów

Prosta funkcja rekurencyjna, używana mapdo skanowania tablicy islice upuszczania pierwszego elementu przy każdym wywołaniu rekurencyjnym.

Edytuj 3 bajty zapisane, dzięki @DocMax, naprawdę inteligentna sugestia

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

Przetestuj w konsoli 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
Kawałek przed mapie, aby skutecznie uniknąć konieczności pi zapisać 3 znaki: H=(n,l)=>n?H(n-1,l.slice(1).map((a,k)=>a-l[k])):l.
DocMax,

6

CJam, 15 bajtów

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

Pobiera dane wejściowe jako tablicę w stylu CJam, a następnie głębokość:

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

i wypisuje wynik jako tablicę w stylu CJam.

Sprawdź to tutaj.

Wyjaśnienie

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

Jawa, 122 119 bajtów

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

Przykład użycia: http://ideone.com/ALgYez

3 bajty dzięki Geobits: v)>


Powinieneś pozbyć się drugiego int i po prostu przypisać i=ego innym.
Geobity

5

> <> 53 50 bajtów

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

Sposób użycia: Najpierw wypełnij stos (-v w interpreterie Pythona) z głębią, a następnie liczbami całkowitymi.

Na przykład:

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

Zwroty

2 -3 10 3

Dzięki Sp3000 za pomoc.


1
Czy można używać ?!i przenosić niektóre komponenty zamiast 0=??
Sp3000,

Dobry chwyt! To pomaga grupie
około

5

Preludium , 95 92 79 78 bajtów

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

Format wejściowy to

N
M
n_1
n_2
...
n_M

gdzie Njest głębokość różnic i Mliczba liczb całkowitych na wejściu. Dodawanie Mbyło konieczne, ponieważ w Preludium nie ma możliwości odróżnienia znaku 0od końca danych wejściowych. Dane wyjściowe mają również postać liczb całkowitych oddzielonych znakiem nowej linii. Musiałem założyć nieco dostosowaną specyfikację Preludium, którą opracowaliśmy dla tego wyzwania , ponieważ standardowe Preludium odczytuje liczby całkowite jako wartości bajtów, co uniemożliwia wprowadzenie liczb ujemnych. Zasadniczo jest to interpreter języka Python z dodatkową NUMERIC_INPUTflagą.

Dla odniesienia jest tylko 48 38 37 znaków spacji - reszta była potrzebna tylko do poprawnego wyrównania kodu.

Wyjaśnienie

W Preludium każda linia jest osobnym „głosem”, który działa na swoim własnym stosie. Program jest wykonywany kolumna po kolumnie, gdzie oddzielne głosy są uruchamiane „równolegle”. Wszystkie polecenia są pojedynczymi znakami, a nawiasy są pętlami typu Brainfuck (które są wprowadzane i powtarzane, gdy górna część stosu jest różna od zera). Zauważ, że pionowe położenie nawiasu zamykającego nie ma znaczenia - umieszczenie go innym głosem nadal liczy się jako dopasowanie do ostatniego nawiasu otwierającego, a stos sprawdzany pod kątem stanu pętli jest zawsze głosem, w którym się (pojawił. Teraz przejdź do tego programu ...

Program można zasadniczo podzielić na dwie części. Dwie dolne linie są używane tylko dla większości pętli w programie (z wyjątkiem pętli głównej N), przekazując 1s tam iz powrotem. Dwie górne linie zawierają główną pętlę i rzeczywiste różnicowanie. Poniższa adnotacja zawiera transponowany kod, dzięki czemu mogę dodawać adnotacje do poszczególnych kolumn:

? ?   # 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 bajtów

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

Wersja bez gry w golfa, zanim zaczęłam rekursywnie:

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 bajtów

Rekurencja!

function(x,y)if(x)Recall(x-1,diff(y)) else y
  • xjest liczbą iteracji do wykonania i yjest wektorem liczb całkowitych.
  • if(x)jest prawdą, dopóki x>0.
  • Recall wywołuje bieżącą funkcję, ale z nowymi argumentami.
  • Diff wyprowadza różnice między kolejnymi elementami listy / wektora.

Poprzednie wersje:

#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

Czy istnieje lepszy sposób na powtórzenie funkcji dif x razy? Korzystanie z pętli for wydaje się nadmierne.
freekvd

Istnieje Reduce, ale myślę, że kosztowałoby więcej postaci.
MickyT,

Jest jeden mały problem. Po wywołaniu z 0 głębokością zwraca głębokość 2
MickyT

Poszedł do innego podejścia, problem rozwiązany, ale musiał dodać 7 znaków.
freekvd

2
Niezłe wykorzystanie Recall().
Alex A.

3

Python, 92 87 86 bajtów

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)

To jest mój pierwszy golf w Python. Wszelkie sugestie będą mile widziane :)

5 6 bajtów dzięki Sp3000: D


Poleciłbym zrozumienie listy.
mbomb007

Możesz zmienić appendw d+=f-e,. Ogólnie rzecz biorąc, do gry w golfa kodowego nigdy nie będziesz musiał używać L.appendz tego powodu.
Sp3000,

3

c, 68 55 bajtów

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

Może to wymagać nieco wolności ze specyfikacją wejściową. Tablica int jest konstruowana tak, że element 0 jest głębokością, a elementy 1 do (n + 1) są elementami listy wejściowej 0 do n. Następnie adres elementu 1 jest przekazywany do funkcji.

Tablica musi być zakończona zerem. Tablica jest edytowana na miejscu.

Na przykład:

#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


Dlaczego zostawiłeś miejsce int *l?
Jonathan Frech,

2

PowerShell 115 111 bajtów

$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','}

Wykonaj jako taki:

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

Wydajność:

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

Przeniesienie nawiasów klamrowych w inne miejsce pozwala wyświetlić każdy krok do odpowiedzi.

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 bajtów

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

Oczekuje wprowadzenia jako liczba całkowita reprezentująca głębokość, a po nim lista liczb całkowitych oddzielonych spacjami, obie podane za pomocą standardowego monitu. Wyjściem jest oddzielona nowa linia lista liczb całkowitych.

Najpierw konwertuje listę liczb całkowitych (które wyświetla jako 1 długi ciąg) na listę zmiennych lokalnych, których nazwy to 1,2,3, ... Następnie oblicza różnice naprzód, ustawiając wartość y-tej zmiennej lokalnej na wartość y + 1-sza zmienna lokalna minus wartość y-tej zmiennej lokalnej (tj. 18-10 = 8), która zastępuje istniejące wartości dopiero po użyciu. Robi to $ a (wartość zmiennej globalnej a) razy. Następnie wyświetla wartość każdej zmiennej lokalnej, po jednym na raz.


+1 za wyjaśnienie. Jest to niezwykle skomplikowany sposób przetwarzania list.
Zgarb

@Zgarb, nie znam sposobu, aby STATA pobierała dane wejściowe jako tablicę / listę, z wyjątkiem plików (które nie działałyby tutaj z powodu innych danych wejściowych). Dlatego musi tak działać.
zaznacza

2

T-SQL, Too Many :)

Kiedy po raz pierwszy zobaczyłem ten problem, zastanawiałem się, czy istnieje sposób, aby to zrobić w zapytaniu. Choć w większości języków jest banalny, nie dotyczy to w dużej mierze zapytań SQL.

Dane wejściowe przechodzą w zmienne @ (dla głębokości) i @L dla listy liczb całkowitych. @L jest zdefiniowanym przez użytkownika typem tabeli

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

Konfiguracja wejścia

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

Zapytanie z kilkoma komentarzami

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

Wynik

-142
55
27
41
-269
397


0

SmileBASIC, 76 bajtów

Wreszcie powód do użycia 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 bajtów

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

Prosta rekurencja funkcji anonimowej. Zapisujesz 1 bajt, jeśli kolejność argumentów jest zamieniana, ponieważ teraz %2występuje częściej niż %.



Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.