Caminho diferente para a frente


23

Dada uma lista de números inteiros, produza uma diferença direta em uma ordem / profundidade especificada.

Para a lista de números inteiros:

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

As diferenças diretas nas várias ordens / profundidades são:

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

Então, com a entrada de

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

Você retornaria a lista

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

Entrada

A entrada pode ser via STDIN ou parâmetros de função.

Um número inteiro especificando a profundidade a ser retornada. Será 0 no comprimento da lista menos 1

Uma lista de números inteiros para calcular a diferença direta para

Saída

A saída pode ser via STDOUT ou retornada pela função.

As diferenças avançadas para a profundidade especificada como uma lista de números inteiros

Regras

Funções internas e de terceiros que fazem isso diretamente não são permitidas.

Aplicam-se restrições de brecha padrão .

O código mais curto vence

Respostas:


19

J, 15 9 7 bytes

Muito fácil. Leva profundidade e lista como argumentos à esquerda e à direita.

-~/\~&2

Como uma definição explícita sem todos os truques adverbiais, isso se reduz a

4 : '(2 -~/\ ])^:x y'
  • -~/\~&2 y- A diferença para a frente de y.
  • x -~/\~&2 y- A x-ésima diferença de y.

Se eu fizesse uma definição séria (ou seja, não-golfe) dessa função, provavelmente faria algo assim:

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

O caso monádico calcula a diferença direta, enquanto o caso diádico calcula a x-ésima diferença direta.

Ainda mais simples, mas não exatamente igual:

+/\inv

+/\produz um vetor das somas dos prefixos do argumento. inv(definido como ^:_1) é uma conjunção que inverte um verbo. Isso funciona onde J sabe como inverter um verbo e, no caso de +/\, J sabe como.


3
Isso mostra o poder dos advérbios e conjunções, como -é o único verbo nessa função.
randomra

14

Python, 61 59 bytes

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

Aqui, realizamos a subtração fechando todos, exceto o último da lista, com todos, exceto o primeiro da lista. zip(L[1:],L)é equivalente a zip(L[1:],L[:-1]), devido à zipnatureza de assumir o comprimento mínimo das duas listas:

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

Uma alternativa tão longa (apenas Python 2):

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

Infelizmente, o Python 2 não corta o final da lista, então não posso map(int.__sub__,L,L[1:]). Irritantemente, Python 3 faz , mas mapnão retorna uma lista de modo que este acaba por ser um byte mais (60 bytes):

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

No entanto, se permitirmos que a entrada seja a profundidade seguida pela lista como f(3, 2, 5, 6, 7, 5, 10, 25)(por exemplo, profundidade 3 e lista [2, 5, 6, 7, 5, 10, 25]), então são 56 bytes :

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

Aqui está outra alternativa que realmente incomodaria qualquer um que visse isso no código de produção (este destrói a lista original):

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

Seu último código está incorreto. Você precisaria em seu L[1]-L.pop(0)lugar.
Mbomb007

@ mbomb007 Obrigado pela captura. Isso foi embaraçoso - eu tive argumentos em torno do caminho errado o tempo todo.
Sp3000 24/02

Estava perto, mas algo como qualquer outra profundidade teve os sinais invertidos.
mbomb007

9

Mathematica 23 57 23 bytes

Sugestão de Martin Büttner, explorando a capacidade de listar subtrações.

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

por exemplo

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

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


Rest@#-Most@# realiza a subtração que produz diferenças.

O Nest executa a operação no número especificado de vezes, sempre operando na lista mais recente.


7

Haskell, 40 34 bytes

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

Exemplo de uso: 4 # [10,18,-12,4,8,-3,-5,67,9,14]quais saídas [-142,55,27,41,-269,397].

Como funciona: calcule repetidamente a diferença entre elementos vizinhos e armazene os resultados intermediários em uma lista. Pegue o nth elemento desta lista.

Edit: @Zgarb encontrou 6 bytes para salvar. Impressionante!


Você pode usar a função monad e encurtar o lambda para (zipWith(-)=<<tail).
Zgarb

7

JavaScript (ES6), 52 49 bytes

Função recursiva simples, usada mappara varrer a matriz e slicesoltar o primeiro elemento em cada chamada recursiva.

Edite 3 bytes salvos, obrigado @DocMax, sugestão realmente inteligente

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

Teste no console 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
Fatia antes mapa para evitar eficientemente a necessidade de pe guardar 3 caracteres: H=(n,l)=>n?H(n-1,l.slice(1).map((a,k)=>a-l[k])):l.
DocMax 24/02

6

CJam, 15 bytes

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

Recebe a entrada como uma matriz no estilo CJam e depois a profundidade:

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

e imprime o resultado como uma matriz no estilo CJam.

Teste aqui.

Explicação

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 bytes

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

Exemplo de uso: http://ideone.com/ALgYez

3 bytes graças ao Geobits: v)>


Você deve se livrar do segundo int e apenas atribuir i=eaos outros.
Geobits

5

> <> 53 50 bytes

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

Uso: preencha previamente a pilha (-v no interpretador python) primeiro com profundidade, seguida pelos números inteiros.

Por exemplo:

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

Devoluções

2 -3 10 3

Obrigado ao Sp3000 pela ajuda.


1
É possível usar ?!e mover alguns componentes em vez de 0=??
Sp3000 24/02

Boa pegada! Isso ajuda muito
cirpis

5

Prelúdio , 95 92 79 78 bytes

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

O formato de entrada é

N
M
n_1
n_2
...
n_M

onde Né a profundidade das diferenças e Mé o número de números inteiros na entrada. A adição Mfoi necessária, porque não há como o Prelude distinguir a 0do final da entrada. A saída também é uma lista de números inteiros separados por nova linha. Eu tive que assumir a especificação do Prelude levemente ajustada que criamos para esse desafio , porque o Prelude padrão lê números inteiros como valores de bytes, o que torna impossível a inserção de números negativos. Essencialmente, esse é o intérprete Python com um NUMERIC_INPUTsinalizador adicional .

Para referência, existem apenas 48 38 37 caracteres não espaciais - o restante foi apenas necessário para alinhar o código corretamente.

Explicação

No Prelude, cada linha é uma "voz" separada que opera em sua própria pilha. O programa é executado coluna por coluna, onde as vozes separadas são tomadas para operar "em paralelo". Todos os comandos são caracteres únicos e os parênteses são loops do tipo Brainfuck (que são inseridos e repetidos sempre que a parte superior da pilha é diferente de zero). Observe que a posição vertical do parêntese de fechamento é irrelevante - colocá-lo em uma voz diferente ainda conta como correspondente ao parêntese de abertura mais recente, e a pilha que é verificada quanto à condição do loop é sempre a voz em que (apareceu. Agora, para este programa ...

O programa pode ser basicamente dividido em duas partes. As duas linhas inferiores são usadas apenas para a maioria dos loops do programa (exceto o loop principal N), passando 1s para frente e para trás. As duas linhas superiores contêm o loop principal e a diferença real. A anotação a seguir tem o código transposto, para que eu possa anotar as colunas individuais:

? ?   # 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 bytes

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

Versão sem golfe antes de eu ser recursivo:

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 bytes

Recursão!

function(x,y)if(x)Recall(x-1,diff(y)) else y
  • xé o número de iterações a serem executadas e yé um vetor de números inteiros.
  • if(x)é verdade enquanto x>0.
  • Recall chama a função atual, mas com novos argumentos.
  • Diff gera as diferenças entre os elementos consecutivos da lista / vetor.

Versões prévias:

#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

Existe uma maneira melhor de repetir a função diff x vezes? Usar um loop for parece excessivo.
Freekvd

Há Reduzir, mas custaria mais caracteres, eu acho.
MickyT

Há um pequeno problema. Quando chamado com 0 profundidade retorna profundidade 2
MickyT

Fui para uma abordagem diferente, problema resolvido, mas tive que adicionar 7 caracteres.
Freekvd

2
Bom uso de Recall().
Alex A.

3

Python, 92 87 86 bytes

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)

Este é o meu primeiro golfe em Python. Todas as sugestões serão apreciadas :)

5 6 bytes graças a Sp3000: D


Eu recomendaria uma compreensão da lista.
mbomb007

Você pode transformar o appendem d+=f-e,. Em geral, para o code-golf, você nunca precisará usar L.appendpor causa disso.
Sp3000 23/02

3

c, 68 55 bytes

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

Isso pode levar um pouco de liberdade às especificações de entrada. Uma matriz int é construída de modo que o elemento 0 seja a profundidade e os elementos 1 a (n + 1) sejam os elementos da lista de entrada 0 a n. Em seguida, o endereço do elemento 1 é passado para a função.

A matriz deve ter terminação zero. A matriz é editada no local.

Por exemplo:

#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


Por que você deixou um espaço int *l?
Jonathan Frech

2

Powershell 115 111 bytes

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

Execute como tal:

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

Saída:

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

Mover uma chave para um local diferente permite exibir todas as etapas da resposta.

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 bytes

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

Espera a entrada como um número inteiro que representa a profundidade, seguida por uma lista de números inteiros separados por espaço, ambos fornecidos pelo prompt padrão. Saída é uma lista separada por nova linha de números inteiros.

Primeiro, converte a lista de números inteiros (que vê como uma cadeia longa) em uma lista de variáveis ​​locais cujos nomes são 1,2,3, ... Em seguida, calcula as diferenças avançadas definindo o valor da y-ésima variável local a ser o valor da y + 1ª variável local menos o valor da y-variável local (ie 18-10 = 8), que substitui os valores existentes somente após o uso. Faz isso $ a (valor da variável global a) vezes. Em seguida, ele exibe o valor de cada variável local, 1 de cada vez.


+1 para explicação. Essa é uma maneira incrivelmente complicada de processar listas.
Zgarb

@ Zgarb, eu não sei como o STATA aceita entradas como uma matriz / lista, exceto via arquivo (que não funcionaria aqui por causa da outra entrada). É por isso que tem que funcionar assim.
bmarks

2

T-SQL, muitos :)

Quando vi esse problema pela primeira vez, imaginei se havia uma maneira de fazer isso em uma consulta. Embora trivial para a maioria dos idiomas, não é muito para consulta SQL.

A entrada entra nas variáveis ​​@ (para profundidade) e @L para a lista inteira. @L é um tipo de tabela definido pelo usuário

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

Configuração de entrada

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

A consulta com alguns comentários

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

Resultado

-142
55
27
41
-269
397


0

SmileBASIC, 76 bytes

Finalmente uma razão para usar 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 bytes

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

Uma recursão simples em função anônima. Você salva 1 byte se a ordem dos argumentos for trocada, como agora %2ocorre com mais frequência que %.



Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.