Adição de cabeça para baixo na pirâmide ... REVERSO!


22

A adição de cabeça para baixo da pirâmide é o processo de pegar uma lista de números e adicioná-los consecutivamente até chegar a um número.

Quando dados os números 2, 1, 1, ocorre o seguinte processo:

 2   1   1
   3   2 
     5

Isso termina no número 5.


SUA TAREFA

Dado o lado direito de uma pirâmide de cabeça para baixo (crescente), escreva um programa ou função que retorne a lista original.

Novo desafio extra : tente fazer isso em menos de O (n ^ 2)

EXEMPLO

f([5, 2, 1]) => [2, 1, 1]
f([84,42,21,10,2]) => [4,7,3,8,2]

NOTA: A pirâmide de cabeça para baixo nunca estará vazia e sempre consistirá SOMENTE em números inteiros positivos.


6
Bem-vindo ao PP&CG! Esse desafio é decente, embora possa ser melhorado. Eu recomendo postar seus desafios na Sandbox primeiro para melhorar a postagem antes que ela seja publicada.
Tau

13
Percepção livre de que não consigo encontrar um idioma mais curto:
f([a,b,c,d,e])=[1464101331001210001100001][abcde]
Lynn

4
Apenas para sua informação, é o mesmo que o kata CodeWars .
ggorlen 30/04

6
@ggorlen eu sei. Eu sou o único que fez o kata :)
Whimpers

8
Try doing this in less than O(n)certamente é impossível alocar uma matriz de tamanho n ou alterar itens de O (n) mais rapidamente que a complexidade de O (n)?
meu pronome é monicareinstate

Respostas:


17

JavaScript (ES6),  62 58 49  46 bytes

Guardado 3 bytes graças a @Oliver

Retorna a lista como uma sequência separada por vírgula.

f=a=>+a||f(a.map(n=>a-(a=n),a=a.shift()))+[,a]

Experimente online!

Comentado

f = a =>              // f = recursive function taking the input list a[]
  +a                  // if a[] consists of a single positive integer:
                      //   stop recursion and return this integer
  ||                  // else:
    f(                //   do a recursive call to f:
      a.map(n =>      //     for each value n in a[]:
        a - (a = n),  //       yield the difference between the previous value and n
                      //       and update a to n
        a = a.shift() //       start by removing the first element and saving it in a
                      //       (because of the recursion, it's important here to reuse
                      //       a variable which is defined in the scope of f)
      )               //     end of map()
    )                 //   end of recursive call
    + [, a]           //   append the last entry from a[]

@ Oliver, sim
Shaggy



6

TI-BASIC, 54 bytes

Ans→L₁:dim(L₁→dim(L₂:While 1-Ans:L₁(Ans→L₂(Ans:-ΔList(L₁→L₁:dim(Ans:End:L₁(Ans→L₂(Ans:L₂

Entrada é a lista do lado direito do triângulo Ans, conforme descrito no desafio.
Saída é a linha superior do referido triângulo.

Exemplos:

{5,2,1
         {5 2 1}
prgmCDGF19
         {2 1 1}
{84,42,21,10,2
 {84 42 21 10 2}
prgmCDGF19
     {4 7 3 8 2}

Explicação:
Esta solução abusa do fato de que o triângulo se formou usando o lado direito do triângulo quando o início acaba sendo a alteração em cada elemento.

Em outras palavras,

2 1 1
 3 2
  5

torna-se:

5 2 1
 3 1
  2

Portanto, a lista resultante é o lado direito desse novo triângulo, que pode ser formado definindo o último elemento no índice do comprimento da lista pai na lista resultante.

Ans→L₁          ;store the input list in L₁
dim(L₁→dim(L₂   ;set the length of L₂ to the length of L₁
While 1-Ans     ;while the L₁'s length is not 1
L₁(Ans→L₂(Ans   ;set the last element of L₁ to the corresponding index in L₂
-ΔList(L₁→L₁    ;get the change in each element, then negate
                ; (elements are in descending order so the change in each
                ;  element will be negative)
                ; and store the resulting list in L₁
dim(Ans         ;leave the length of L₁ in "Ans"
End
L₁(Ans→L₂(Ans   ;set the element again
                ; (needed for final step)
L₂              ;leave L₂ in "Ans"
                ;implicit print of "Ans"

Nota: TI-BASIC é um idioma tokenizado. Contagem de caracteres não é igual à contagem de bytes.


4

Gelatina , 6 bytes

ṚIƬZḢṚ

Um link monádico que aceita uma lista de números inteiros que produz uma lista de números inteiros.

Experimente online!

Quão?

Constrói o triângulo inteiro e extrai os elementos necessários.

ṚIƬZḢṚ - Link: list of integers          e.g.  [84,42,21,10,2]
Ṛ      - reverse                               [2,10,21,42,84]
  Ƭ    - collect & apply until a fixed point:
 I     -   incremental differences            [[2,10,21,42,84],[8,11,21,42],[3,10,21],[7,11],[4],[]]
   Z   - transpose                            [[2,8,3,7,4],[10,11,10,11],[21,21,21],[42,42],[84]]
    Ḣ  - head                                  [2,8,3,7,4]
     Ṛ - reverse                               [4,7,3,8,2]

Teve uma solução quase idêntica, mas com Us em vez de !
Nick Kennedy

IƬUZḢAtambém trabalharia com a pergunta dada; Gostaria de saber se existe um byte salvar em algum lugar ...
Jonathan Allan

ạƝƬZṪ€funciona também, mas é novamente um seis.
Nick Kennedy

Sim, notei essa variante; Estou menos esperançoso agora.
Jonathan Allan

Acabei de publicar um artigo de 5 bytes, mas é um pouco diferente da sua abordagem em relação à peça após a construção da pirâmide.
Erik the Outgolfer

4

MathGolf , 14 11 bytes

xÆ‼├│?;∟;]x

Experimente online!

Explicação

x             reverse int/array/string
 Æ     ∟      do while true without popping using 5 operators
  ‼           apply next 2 operators to TOS
   ├          pop from left of list
    │         get differences of list
     ?        rot3
      ;       discard TOS (removes rest from ├ command)
              loop ends here
        ;     discard TOS (removes empty array from stack)
         ]    wrap stack in array
          x   reverse array

3

Python 2 , 56 bytes

f=lambda a:a and f([l-r for l,r in zip(a,a[1:])])+a[-1:]

Uma função recursiva que aceita uma lista de números inteiros positivos que retorna uma lista de números inteiros não negativos.

Experimente online!



3

Pari / GP , 36 bytes

Com base no comentário de @Lynn :

Insights gratuitos em que não consigo encontrar um idioma mais curto:

f([uma,b,c,d,e])=[1-46-410 01-33-10 00 01-210 00 00 01-10 00 00 00 01][umabcde]

O Pari / GP possui um built-in para a matriz Pascal, e seu inverso é exatamente a matriz que precisamos:

[10 00 00 00 0110 00 00 01210 00 013310 014641]-1=[10 00 00 00 0-110 00 00 01-210 00 0-13-310 01-46-41]

a->r=Vecrev;r(r(a)/matpascal(#a-1)~)

Experimente online!


3

R, 69 67 bytes

function(n,x=sum(n|1):1-1,`[`=outer)(x[x,choose]*(-1)^x[x,"+"])%*%n

Try it online!

Returns a column vector.

-2 bytes thanks to Kirill L.

Also based on Lynn's comment:

Free insight that I can't find a language it's shorter in:

f([a,b,c,d,e])=[1464101331001210001100001][abcde]

It's longer than the other R answer, but it was an interesting approach to take and try to golf.


2

Javascript (ES6), 127 bytes

f=a=>{for(e=[a],a=[a[l=a.length-1]],i=0;i<l;i++){for(e.push(g=[]),j=-1;j<l;)g.push(e[i][j]-e[i][++j]);r.unshift(g[j])}return r}

Original code

function f(a){
  var e=[a];
  var r=[a[a.length-1]];
  for (var i=1;i<a.length;i++){
    var g=[];
    for (var j=0;j<a.length;j++){
      g.push(e[i-1][j-1]-e[i-1][j]);
    }
    e.push(g);
    r.unshift(g[j-1]);
  }
  return r;
}

Oh, I lost like... a lot... to the previous answer...



2

05AB1E, 12 11 bytes

R.¥.Γ¥}¨ζнR

Port of @JonathanAllan's Jelly answer, although I'm jelly about Jelly's more convenient builtins in this case. ;)
-1 byte thanks to @Emigna.

Try it online or verify all test cases.

Explanation:

R            # Reverse the (implicit) input-list
             #  i.e. [16,7,4,3] → [3,4,7,16]
           # Undelta it (with leading 0)
             #  → [0,3,7,14,30]
    }      # Continue until the result no longer changes, and collect all steps:
     ¥       #  Get the deltas / forward differences of the current list
             #  → [[3,4,7,16],[1,3,9],[2,6],[4],[]]
       ¨     # Remove the trailing empty list
             #  → [[3,4,7,16],[1,3,9],[2,6],[4]]
        ζ    # Zip/transpose; swapping rows/column (with space as default filler)
             #  → [[3,1,2,4],[4,3,6," "],[7,9," "," "],[16," "," "," "]]
         н   # Only leave the first inner list
             #  → [3,1,2,4]
          R  # Revert it back
             #  → [4,2,1,3]
             # (after which it's output implicitly as result)

2
You can save a byte with R.¥.Γ¥}¨ by starting from the list whose delta is the input.
Emigna

@Emigna Ah, undelta into a loop with deltas to save a byte on the prepend. :) Thanks!
Kevin Cruijssen


2

Perl 6, 37 bytes

{[R,]($_,{@(.[]Z-.skip)}...1)[*;*-1]}

Try it online!

Repeatedly reduces by elementwise subtraction, and then returns the last number of each list in reverse.

Explanation:

{                                  }  # Anonymous code block
      $_,               ...   # Create a sequence starting from the input
         {             }      # Where each element is
            .[]Z-.skip          # Each element minus the next element
          @(          )         # Arrayified
                           1  # Until the list has one element left
 [R,]                                # Reverse the sequence
     (                     )[*;   ]  # For every list
                               *-1   # Take the last element



1

Charcoal, 19 bytes

Fθ«PI§θ±¹↑UMθ⁻§θ⊖λκ

Try it online! Link is to verbose version of code. Explanation:

Fθ«

Loop once for each term in the original list.

PI§θ±¹↑

Print the last term in the list, but move the cursor to the beginning of the previous line, so that the terms are output in reverse order.

UMθ⁻§θ⊖λκ

Compute the deltas, inserting a dummy value at the beginning so that we can use an operation that doesn't change the length of the list.




1

C, 76 bytes

i=0;int*f(int*a,int n){for(;i<n;a[i++]=a[i]-a[i+1]);if(!n)return a;f(a,n-1);}  

input : (*a = pointer to array, n = last element's index of that array)
output : return int* = output

Explanation
going from right side to up, as the last elements are same in both input and output the loop inside function simply finds next higher numbers in the triangle gradually reaching to the top leaving the answer intact in the end.

ungolfed(from C++)

#include <iostream>
#define SIZE_F 5

int*recFind(int*a, int n) {
    int i = 0;
    while (i < n)
        a[i++] = a[i] - a[i+1];
    if (!n) return a;
        recFind(a, n - 1);
}
int main()
{
    int first[SIZE_F],*n;
    for (int i = 0; i < SIZE_F; i++)
        std::cin >> first[i];

    n = recFind(first, SIZE_F - 1);//size - 1
    for (int i = 0; i < SIZE_F; i++)
        std::cout << n[i];
}

1

Japt, 11 9 bytes

Nc¡=äa
yÌ

Try it

2 bytes saved thanks to Oliver.

12 11 bytes

_äa}hUÊN yÌ

Try it

1 byte saved thanks to Oliver.



@Oliver, not thinking to use y(f) is bad enough, but completely forgetting the newline is unforgivable! Will update shortly. Thanks :)
Shaggy

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.