Ordina un elenco di differenze


22

L'elenco delle differenze di un elenco di numeri interi è rappresentato dalle differenze di elenco dei membri consecutivi.

Ad esempio l'elenco delle differenze di

1, 3, 2 ,4

è

2, -1, 2

Il tuo compito è quello di prendere come input un elenco di differenze e produrre come sarebbe l'elenco di differenze se l'elenco originale fosse ordinato.

Ad esempio l'elenco delle differenze

2, 1, -2, -1

Potrebbe rappresentare un elenco

2 4 5 3 2

Che quando ordinato è

2 2 3 4 5

Che ha un elenco di differenze di

0 1 1 1

Questo è quindi le risposte verranno classificate in byte con meno byte migliori.


Le soluzioni sono garantite come uniche?
H.Piz,

@ H.PWiz Sì, lo sono.
Wheat Wizard


1
@ H.PWiz Quick proof: un elenco è perfettamente ricostruibile da un elenco di differenze (DL) combinato con un valore del primo elemento, quindi c'è una conversione uno a uno da L a (FV, DL). Aumentare l'FV di qualsiasi importo equivale ad aggiungere quell'ammontare a ogni elemento di L e quindi non può cambiare l'ordinamento di L se tale confronto è opportunamente monotonico. (In altre parole, non influisce sull'ordinamento a meno che il numero che si aggiunge non provochi un overflow di numeri interi).
CR Drost,

1
Potresti aggiungere qualche altro test case? Noto alcune soluzioni che danno risultati diversi [-2, 100, -2, -1], per esempio.
Shaggy,

Risposte:


16

05AB1E , 4 byte

.¥{¥

Provalo online!

Spiegazione

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

Undelta05AB1E ha i built-in più di nicchia. o0
totalmente umano

2
Ah, merda, picchiami. Ho sempre desiderato usare undelta.
Magic Octopus Urn l'

16
Undeltaಠ ___ ಠ
Business Cat

1
"Undelta" è semplicemente una somma cumulativa, giusto?
Zgarb,

2
@Zgarb Undelta sta aggiungendo uno 0 come primo elemento dell'elenco, quindi esattamente come hai detto, somma cumulativa o delta inverso.
Magic Octopus Urn l'

9

Python 3 con Numpy , 56 54 53 byte

2 byte di sconto grazie a @Artyer (Numpy's sortanziché standard sorted). 1 byte spento grazie a @notjagan (spostandosi 0in cumsum)

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

Il codice definisce una funzione anonima che immette un elenco o un array Numpy e genera un array Numpy.

Provalo online!


1
Woah, mi hai insegnato qualcosa di nuovo oggi. Il mio approccio con è numpystato molto più lungo. Tornerò domani per votare questo, perché ti vedo già limitato. Molto bella!
Mr. Xcoder, l'

@ Mr.Xcoder Grazie! Non sono un esperto di Numpy, ho appena seguito quello che avrei fatto in Matlab: diff(sort([0 cumsum(x)]))(in Matlab, [ ]è concatenazione)
Luis Mendo,

Dovere adempiuto!
Mr. Xcoder,

-1 byte spostando il 0in cumsum.
notjagan,



4

Buccia , 4 byte

Ẋ-O∫

Provalo online!

spiegazione

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

Un'altra lingua che ha undelta? O qualche appassionato incorporato?
Mr. Xcoder, l'

@Sig. Xcoder Succede che cumsum è lo stesso di undelta
H.Pwiz

@ H.PWiz In realtà non è quello che chiamiamo cumsum ... a meno che tu non prenda in considerazione il prefisso vuoto.
Erik the Outgolfer,

@EriktheOutgolfer Sì, questo è ciò che fa la buccia, come scanl(+)0in Haskell.
H.Piz,

4

Pyth , 9 byte

-1 byte grazie a @EriktheOutgolfer .

.+S+0sM._

Test Suite.

Pyth , 10 byte

.+S.u+YNQ0

Provalo online! oppure prova altri casi di test .


Come nella mia risposta (eliminata), puoi usare +0sM._invece di .u+YNQ0-1.
Erik the Outgolfer,

@EriktheOutgolfer Perché l'hai eliminato?
Mr. Xcoder, l'

Pensavo che l'idea centrale fosse troppo simile alla tua.
Erik the Outgolfer,

@EriktheOutgolfer Ok, grazie allora
Mr. Xcoder, l'

m=+Zè una variante della stessa lunghezza sM._, ma purtroppo non sembra essere più breve.
FryAmTheEggman,

4

JavaScript (ES6), 57 56 byte

Salvato 1 byte grazie a @ETHproductions

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

dimostrazione


.sort((a,b)=>a-b)Questo è il modo di ottenere delta? Ordinando con sottrazione? : P
totalmente umano

@totallyhuman Il primo map()dà i delta. Questo codice li ordina. La seconda mappa ricostruisce i nuovi delta. Il sort()metodo JS utilizza l'ordine lessicografico per impostazione predefinita. Quindi, abbiamo bisogno di questo callback specializzato per numeri> 9 (purtroppo).
Arnauld,

Questo -p+(p=n)mi frantuma, ma purtroppo non c'è modo migliore ... a meno che ...
ETHproductions

che diamine, non ho premuto il pulsante di invio> _ <Ma comunque, penso che puoi salvare un byte con quella modifica ...
ETHproductions

@ETHproductions Grazie :-)
Arnauld l'

3

Java 8, 123 byte

La soluzione standard: input somma cumulativa, ordinamento, quindi diff. Neanche trucchi di implementazione sostanziale.

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

Cast to Consumer<int[]>. L'output è input mutato.

Provalo online

Lambda ungolfed

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

Ringraziamenti

  • -3 byte grazie a Olivier Grégoire, master of unholy autoincrementation
  • -1 byte grazie a 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

k, 16 bytes

1_-':{x@<x}@+\0,

Try it online!

              0, /prepend a 0
            +\   /cumulative sum
     {x@<x}@     /sort
1_-':            /differences list


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!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.