排序差异列表


22

整数列表的差异列表是连续成员的列表差异。

例如,差异列表

1, 3, 2 ,4

2, -1, 2

您的任务是将差异列表作为输入,并输出对原始列表进行排序后的差异列表的外观。

例如差异列表

2, 1, -2, -1

可能代表清单

2 4 5 3 2

排序时是

2 2 3 4 5

其中有一个差异列表

0 1 1 1

这是因此答案将以字节计分,而字节数越少越好。


解决方案是否保证是唯一的?
H.PWiz

@ H.PWiz是的。
小麦巫师


1
@ H.PWiz快速证明:列表可以完美地从差异列表(DL)与第一个元素值组合而重建,因此存在从L到(FV,DL)的一对一转换。将FV增加任何数量都等于将该金额添加到L的每个元素中,因此,如果该比较适当地是单调的,则它不能更改L的排序。(换句话说,除非您添加的数字引起整数溢出,否则它不会影响排序)。
CR Drost

1
您能否再添加一些测试用例?例如,我注意到一些解决方案给出了不同的输出[-2, 100, -2, -1]
毛茸茸的

Answers:


16

05AB1E,4个字节

.¥{¥

在线尝试!

说明

.¥{¥
.¥   # Undelta the input list
  {  # Sort it
   ¥ # And get the deltas

Undelta05AB1E具有最多的内置细分市场。o0
完全人类的,

2
啊,胡扯,击败我。我一直想使用undelta。
魔术八达通缸

16
Undeltaಠ___ಠ
商务猫

1
“ Undelta”仅仅是累计金额,对不对?
Zgarb

2
@Zgarb Undelta会将0作为列表的第一个元素,然后按照您所说的完全相加或反向增量。
Magic Octopus Urn

9

带有Numpy的Python 356个 54 53字节

多亏@Artyer(用Numpy sort代替standard sorted),可节省 2个字节。@notjagan节省了 1个字节(移动0cumsum

lambda x:diff(sort(cumsum([0]+x)))
from numpy import*

该代码定义了一个匿名函数,该匿名函数输入一个列表或一个Numpy数组并输出一个Numpy数组。

在线尝试!


1
哇,您今天教我一些新知识。我的方法numpy要长得多。我明天会回来支持这个,因为我看到你已经被封顶了。非常好!
Xcoder先生17年

@ Mr.Xcoder谢谢!我不是Numpy的专家,我只是遵循我在Matlab中所做的事情:(diff(sort([0 cumsum(x)]))在Matlab中[ ]是串联的)
Luis Mendo

履行职责!
Xcoder先生17年

通过将-1字节0移入cumsum
notjagan



4

外壳,4个字节

Ẋ-O∫

在线尝试!

讲解

      -- implicit input, e.g                               [2,1,-2,-1]
   ∫  -- cumulative sum                                    [0,2,3,1,0]
  O   -- sort                                              [0,0,1,2,3]
Ẋ     -- apply function to all adjacent pairs in the list  [(0,0),(0,1),(1,2),(2,3)]
 -    --   subtract                                        [0,1,1,1]

另一种语言有错位?还是一些内置的更高级的?
Xcoder先生17年

@先生。Xcoder发生的总和与非
增量

@ H.PWiz实际上这不是我们所说的cumsum ...除非您将空前缀考虑在内。
暴民埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer是的,这就是果壳所做的,就像scanl(+)0在Haskell中一样。
H.PWiz

4

Pyth,9个字节

-1个字节感谢@EriktheOutgolfer

.+S+0sM._

测试套件。

Pyth,10个字节

.+S.u+YNQ0

在线尝试!尝试更多的测试用例


就像我(已删除)的答案一样,您可以使用+0sM._代替.u+YNQ0-1。
暴民埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer为什么删除它?
Xcoder先生17年

认为核心想法与您的想法太相似。
暴民埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer好,然后谢谢
Xcoder先生17年

m=+Z是的相同长度变体sM._,但可悲的是它似乎不能更短。
FryAmTheEggman

4

JavaScript(ES6),57 56字节

@ETHproductions节省了1个字节

a=>a.map(n=>t-=n,p=t=0).sort((a,b)=>b-a).map(n=>p-(p=n))

演示版


.sort((a,b)=>a-b)那就是获得增量的方式吗?通过减法排序?:P
totallyhuman

@totallyhuman第一个map()给出增量。此代码对它们进行排序。第二张地图重建新的三角洲。JS sort()方法默认情况下使用字典顺序。因此,我们需要针对数字> 9(严重)的此专用回调。
Arnauld

那使-p+(p=n)
难以接受

怎么了,我没有按下提交按钮> _ <但是无论如何,我认为您可以使用该编辑来保存一个字节...
ETHproductions

@ETHproductions谢谢:-)
Arnauld

3

Java 8,123字节

标准解决方案:累加总和输入,排序然后比较。也没有实质性的实现技巧。

l->{int s=l.length,d[]=new int[s+1],i=0;while(i<s)d[i+1]=d[i]+l[i++];for(java.util.Arrays.sort(d);i-->0;)l[i]=d[i+1]-d[i];}

投放到Consumer<int[]>。输出是变异输入。

在线试用

非高尔夫λ

l -> {
    int
        s = l.length,
        d[] = new int[s + 1],
        i = 0
    ;
    while (i < s)
        d[i + 1] = d[i] + l[i++];
    for (java.util.Arrays.sort(d); i-- > 0; )
        l[i] = d[i + 1] - d[i];
}

致谢

  • -3 bytes thanks to Olivier Grégoire, master of unholy autoincrementation
  • -1 byte thanks to Nevay

1
You can golf 3 bytes by rearranging the positions where you do your increments and your overall computations: l->{int s=l.length,d[]=new int[s+1],i=0;for(;i<s;)d[i+1]=d[i]+l[i++];java.util.Arrays.sort(d);for(i=0;i<s;)l[i]=-d[i]+d[++i];} (beware SE's invisible characters when copy/pasting)
Olivier Grégoire

1
Thanks for my new title ;) Here's more decrement unholiness to celebrate for(;i>0;)l[i-1]=d[i]-d[--i]; (last loop)
Olivier Grégoire

I had just reworked that loop myself, arriving at for(;i-->0;)l[i]=d[i+1]-d[i]; of the same length. Update to come.
Jakob

2
You can save 1 byte by using l->{int s=l.length,d[]=new int[s+1],i=0;while(i<s)d[i+1]=d[i]+l[i++];for(java.util.Arrays.sort(d);i-->0;l[i]=d[i+1]-d[i]);}.
Nevay

Ah yes, of course. Thanks!
Jakob


2

R, 31 32 bytes

-4 bytes thanks to @user2390246 for diffinv

+5 bytes from Jarko for cat

cat(diff(sort(diffinv(scan()))))

Reads from stdin, writes to stdout. diffinv is an inverse of diff for a given starting value (0 by default). Since it's diffed again, it doesn't matter what that value is.

As pointed out by Jarko Dubbeldam, I needed to properly output the result, at the cost of five bytes. Alas.

Try it online!


That's what I had in mind as well. Does need to handle printing though, as running this as a full program (through source) this doesn't output anything.
JAD

1
If you use diffinv rather than cumsum you don't need to prepend zero.
user2390246

@user2390246 wow, very nice! TIL about diffinv.
Giuseppe

Me too! I was just having a quick search to see if there were any previous answers I could have applied it to.
user2390246

1

Python 2, 83 bytes

l,r=input(),[1]
for i in l:r+=[r[-1]+i]
r.sort()
print[b-a for a,b in zip(r,r[1:])]

Try it online!

Horrible solution.


It's not that terrible, in fact
Mr. Xcoder

Python's += operator on lists works with any iterable, so you can use r+=r[-1]+i, instead of r+=[r[-1]+i] and save one byte.
Jonathan Frech

1

Perl 6, 46 bytes

{[\+](0,|@_).sort.rotor(2=>-1).flat.map(*R-*)}

Try it

Expanded:

{  # bare block lambda with implicit signature :(*@_)

  [\+](         # triangle reduce using &infix:«+»
    0,          # start with 0
    |@_         # Slip in the arguments from the outer block
  )             #                  (0, 2, 3, 1, 0)

  .sort         # sort the results (0,0,1,2,3)
  .rotor(2=>-1) # group in twos    ((0,0),(0,1),(1,2),(2,3))
  .flat         # flatten          (0,0,0,1,1,2,2,3)
  .map(*R-*)    # grab 2 values at a time, and subtract first from second
                # (0, 1, 1, 1)
}

1

Haskell, 74 bytes

import Data.List
g=sort.scanl(+)0
h l|k<-g l=map(\(x,y)->x-y)$zip(tail$k)k

Try it online!

Straightforward.


3
=<< from the function monad comes in handy: (zipWith(-)=<<tail).sort.scanl(+)0
nimi

@nimi Very nice. I'm not expert in monads, but I should have thought of zipWith.
jferard

1

TI-Basic (TI-84 Plus CE), 23 bytes

Prompt X
augment({0},cumSum(LX→X
SortA(LX
ΔList(LX

Prompts for user input. The list must be input with a leading {, with numbers separated by ,, and with an optional trailing }.

TI-Basic is a tokenized language; ΔList( and cumSum( are two-byte tokens, all other tokens used are one byte each.

Example run (with NAME as the program name and {4,-2,7,-4,0} as the input):

prgmNAME
X=?{4,-2,7,-4,0}
               {2 2 1 0 4}

Explanation:

Prompt X                  # 3 bytes, get list input, store in LX
augment({0},cumSum(LX→X   # 12 bytes, 
          # store the list ({0} prepended to the cumulative sum of LX) to LX
SortA(LX                  # 4 bytes, sort LX ascending
ΔList(LX                  # 4 bytes, implicitly print the difference list of LX

Do you need the L's?
Zacharý

@Zacharý you can omit them when storing a list, but omitting them when referencing would refer to the numerical variable X instead of the list
pizzapants184

1

C++ (gcc), 136 bytes

As unnamed generic lambda, assuming input to be like std::list and returning via reference parameter.

[](auto&L){auto r=L.begin(),l=L.insert(r,0);while(r!=L.end())*r+++=*l++;for(L.sort(),l=r=--L.end();--l!=L.begin();*r---=*l);L.erase(l);}

Try it online!

Ungolfed:

[](auto&L){
 auto r=L.begin(),
      l=L.insert(r,0); //adds a zero right in front
 while(r!=L.end())
   *r++ += *l++;       //sum left to right
 for(
  L.sort(),            //sorting invalidates the iterators
  l=r=--L.end();       //so, reinit
  --l!=L.begin();      //decrement l beforehand 
  *r-- -= *l           //diff right to left
 );
 L.erase(l);           //l==L.begin(), so this removes the temporary 0
}

1

Pyth, 8 bytes

.+S+M.uP

Demonstration

.+S+M.uP
.+S+M.uPNQ    Implicit variables
     .u  Q    Apply the following function to the input repeatedly until it
              stops changing, then output the list of values, including the
              starting value.
       PN     Remove the last element. No-op if the list is empty.
   +M         Sum each list. This gives the cumulative sums in reverse order,
              including a 0 at the end for the empty list.
  S           Sort
.+            Deltas

+1 This is a neat workaround with cumulative fixed point. I personally didn't even think of this.
Mr. Xcoder

1

TI-Basic, 20 bytes

cumSum(augment({0},Ans->L1
SortA(L1
ΔList(L1


1

VB.NET (.NET 4.5), 109 bytes

Sub A(n)
Dim c=n.count-1
For i=1To c
n(i)+=n(i-1)
Next
n.Sort()
For i=c To 1 Step-1
n(i)-=n(i-1)
Next
End Sub

A function that expects a list as input and modifies it directly. The original parameter can then be used for output

  1. Recreates an original list by adding forwards through the list (assumes an implicit 0 as the first element)
  2. Sorts the original list
  3. Gets the differences by going backwards (so I don't need to keep track of a different list) (the implicit first element of 0 means the first difference is the same as the smallest element)

Try it online!


Would you mind updating the TIO link?
Taylor Scott

@TaylorScott Update in what way?
Brian J

Your TIO link shows completely different code than in your answer
Taylor Scott

1
@TaylorScott Ahh....I see. I had to make some adjustments because TIO uses Mono, but I was using the .NET 4.5 compiler
Brian J

1

APL (Dyalog), 15 14 bytes

-1 byte thanks to ngn.

2-/⍋⊃¨⊂)0,+\

+\ cumulative sum

0, prepend a zero

() apply the following tacit function on that:

 enclose (so we can pick multiple items)

⍋⊃¨ let each of the indices that would sort the argument pick from that

¯2-/ reversed pairwise difference

Try it online!


Original solution found by the Code Golf Hackathon participants at the Dyalog '17 User Meeting:

¯2-/l[⍋l←+\0,⎕]

Try it online!

 prompt for input

0, prepend a zero

+\ cumulative sum

l← store as l

 find the indices that will sort l

l[] use that to index into l

¯2-/ reversed pairwise difference


1
I don't know if this was allowed at the hackathon but if you rewrite it in point-free style you could save a char: (¯2-/⍋⊃¨⊂)0,+\
ngn

@ngn This part of the workshop was attempting to get the participants started with PPCG, so the rules here were those of PPCG. Thanks.
Adám

1

MATL, 6 bytes

0hYsSd

Try it online!

0       # push 0
 h      # horizontal concatenate with implicit input
  Ys    # cumulative sum
    S   # sort
     d  # diff (implicit output)




0

Röda, 42 bytes

{i=0{[0];[i]if i+=_}|sort|slide 2|[_2-_1]}

Try it online!

This is similar to the Perl 6 answer. .sort is |sort, .rotor(2=>-1).flat is |slide 2 and .map(*R-*) is |[_2-_1].

Explanation:

{
  i=0 /* initialize variable i */
  /* the following block recreates the original list from differences: */
  {
    [0];       /* push 0 to the stream */
    [i]if i+=_ /* add every number in the stream to i and push i back */
  }|
  sort|    /* sort the numbers */
  slide 2| /* for values i1, i2, i3, ... in the stream
              push pairs i1, i2, i2, i3, ... */
  [_2-_1]  /* calculate difference of numbers in each pair in the stream */
}

The statement [i]if i+=_ is equivalent to

for sfv do
  if i += sfv do
    push(i)
  done
done

The += operator does not push values to the stream, so it is truthy. I could also have used some kind of block (eg. {|j|i+=j;[i]}_) to tie the addition and pushing statements together, but if is shorter.


0

Julia 0.6.0 (34 bytes)

Pretty much a copy of what has been done in R and Python 3

x->diff(sort(cumsum(vcat([0],x))))


0

J, 10 bytes

/:~&.(+/\)

explanation

"sort under scan sum": In J, the Under conjunction &. applies the transformation to its right to the input, then applies the verb to its left (in this case sort /:~) and then does the reverse transformation. That is, J understands how to invert a scan sum, which is exactly what's needed here: the successive differences are the input that, when scan-summed, will produce that scan-sum.

Try it online!

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.