倒置的金字塔加法…反转!


22

倒置金字塔加法是获取一个数字列表并将其连续加在一起直到达到一个数字的过程。

给出数字后,2, 1, 1将发生以下过​​程:

 2   1   1
   3   2 
     5

这以数字结尾5


你的任务

给定“颠倒金字塔”(升序)的右侧,编写将返回原始列表的程序或函数。

新的额外挑战:尝试在小于O(n ^ 2)的范围内进行操作

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

注意:倒置金字塔永远不会为空,并且将始终仅由正整数组成。


6
欢迎来到PP&CG!尽管可以改进,但这一挑战是体面的。我建议您先在“ 沙箱”中发布您的挑战,以改进该帖子,然后再发布到主要站点。

13
我无法找到一种较短的语言的自由见解:
F[一种bCdË]=[1个-46-41个01个-33-1个001个-21个0001个-1个00001个][一种bCdË]
Lynn

4
仅供参考,这与CodeWars kata相同。
ggorlen

6
@ggorlen我知道。我是制作
制片

8
Try doing this in less than O(n)当然,不可能分配一个n大小的数组或更改其中的O(n)个项目快于O(n)的复杂性?
我的代词是monicareinstate,

Answers:


17

JavaScript(ES6), 62 58 49  46字节

@Oliver节省了3个字节

以逗号分隔的字符串形式返回列表。

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

在线尝试!

已评论

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,是的
毛茸茸的



6

TI-BASIC,54个字节

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

输入是中的三角形右侧的列表Ans,如挑战中所述。
输出是所述三角形的第一行。

例子:

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

说明:
此解决方案滥用了以下事实:使用三角形的右侧作为起点形成的三角形最终是每个元素中的变化。

换一种说法,

2 1 1
 3 2
  5

变成:

5 2 1
 3 1
  2

因此,结果列表位于此新三角形的右侧,可以通过将最后一个元素设置为其结果列表中其父列表长度的索引来形成该列表。

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"

注意: TI-BASIC是一种标记化语言。字符数不等于字节数。


4

果冻,6 个字节

ṚIƬZḢṚ

一个接受整数列表的单子链接,该整数列表产生一个整数列表。

在线尝试!

怎么样?

建立整个三角形,然后提取所需的元素。

Ṛ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]

具有几乎相同的解决方案,但用Us代替
尼克·肯尼迪

IƬUZḢA也可以处理给定的问题;我想知道是否在某个地方保存了一个字节……
乔纳森·艾伦

ạƝƬZṪ€也可以,但是又是六。
尼克·肯尼迪

是的,我注意到了这种变体。我现在没有希望了。
乔纳森·艾伦

我刚刚发布了一个5乘法,但是与您在金字塔构造之后的方法有所不同。
暴民埃里克

4

MathGolf14 11字节

xÆ‼├│?;∟;]x

在线尝试!

说明

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

Pari / GP,36字节

基于@Lynn的评论:

F[一种bCdË]=[1个-46-41个01个-33-1个001个-21个0001个-1个00001个][一种bCdË]

Pari / GP具有Pascal矩阵的内置函数,它的逆矩阵正是我们需要的矩阵:

[1个00001个1个0001个21个001个331个01个4641个]-1个=[1个0000-1个1个0001个-21个00-1个3-31个01个-46-41个]

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

在线尝试!


3

R69 67字节

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

在线尝试!

返回列向量。

-2个字节,感谢KirillL。

同样基于Lynn的评论:

F[一种bCdË]=[1个-46-41个01个-33-1个001个-21个0001个-1个00001个][一种bCdË]

它比其他R答案更长,但这是一种尝试高尔夫的有趣方法。


2

Javascript(ES6),127个字节

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}

原始码

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

噢,我迷失了……很多……以前的答案……



2

05AB1E12 11 字节

R.¥.Γ¥}¨ζнR

@JonathanAllan的果冻答案,虽然我的果冻约在这种情况下果冻的更方便的内置命令。;)-
1个字节,感谢@Emigna

在线尝试验证所有测试用例

说明:

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
您可以R.¥.Γ¥}¨通过从输入增量的列表开始保存字节。
Emigna

@Emigna啊,用delta进入一个循环,以在前缀上保存一个字节。:) 谢谢!
Kevin Cruijssen


2

Perl 6、37个字节

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

在线尝试!

通过逐元素减法反复减少,然后反向返回每个列表的最后一个数字。

说明:

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

木炭,19字节

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

在线尝试!链接是详细版本的代码。说明:

Fθ«

为原始列表中的每个术语循环一次。

PI§θ±¹↑

打印列表中的最后一项,但将光标移至上一行的开头,以便以相反的顺序输出这些条款。

UMθ⁻§θ⊖λκ

计算增量,在开头插入一个虚拟值,以便我们可以使用不更改列表长度的操作。




1

C,76字节

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

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


从右至上的解释是,由于输入和输出中的最后一个元素相同,因此循环内部函数仅查找三角形中的下一个较高数字,并逐渐到达顶部,而最终答案保持不变。

取消高尔夫(来自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];
}


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.