Machen Sie eine Eins-Sequenz

12

Eine Folge von ganzen Zahlen ist eine Ein-Folge, wenn der Unterschied zwischen zwei aufeinanderfolgenden Zahlen in dieser Folge -1 oder 1 ist und das erste Element 0 ist.

Genauer gesagt: a1, a2, ..., an ist eine Eins-Sequenz, wenn:

For any k (1 ≤  k < n): |a[k] - a[k+1]|=1, 
a[1]=0

Eingang

  • n - Anzahl der Elemente in der Sequenz
  • s - Summe der Elemente in der Sequenz

Ausgabe

  • eine einreihige Menge / Liste / Array / etc von Länge nmit der Summe der Elemente s, wenn möglich
  • eine leere Menge / Liste / Array / etc, wenn nicht möglich

Beispiele

Als Eingabe 8 4könnte Ausgabe [0 1 2 1 0 -1 0 1]oder sein [0 -1 0 1 0 1 2 1]. Es kann andere Möglichkeiten geben.

Bei der Eingabe 3 5ist die Ausgabe leer [], da dies nicht möglich ist.

Regeln

Dies ist ein Code Golf, die kürzeste Antwort in Bytes gewinnt. Einsendungen sollten ein Programm oder eine Funktion sein. Die Eingabe / Ausgabe kann auf eine der Standardarten erfolgen .

typedef
quelle
Übrigens habe ich den Beweis, dass alle Zahlen, die als eine Folge der Länge I darstellbar sind, alle Zahlen dazwischen sind (l-1)*l/2und -(l-1)*l/2die gleiche Parität haben wie (l-1)*l/2.
stolzer Haskeller
Dies kann verwendet werden, um einen effizienten Algorithmus (O (n)) zu
erstellen

Antworten:

7

CJam, 56 47 44 34 Bytes

Hier gibt es viel Raum für Verbesserungen, aber hier ist der erste Versuch:

L0aa{{[~_(]_)2++}%}l~:N;(*{:+N=}=p

Dank an Dennis für die effiziente Ausführung des { ... }%Teils.

Gibt, falls möglich, die Array-Darstellung aus ""

Probieren Sie es hier online aus

Optimierer
quelle
Ich bin verwirrt: Der {}%Teil Ihres Codes sieht nicht nach meinem aus (das ist nur @ PeterTaylors Code, der Punkte durch Unterstriche ersetzt). Wenn ich etwas zu Ihrem Code beigetragen habe, ist es der {}=Operator ...
Dennis
Ich hatte anfangs _{_W=)+}%\{_W=(+}%+zwei Kopien, addiere 1 zu der ersten und subtrahiere 1 von der anderen. Ihr Beispiel hat mich dazu gebracht, in einem { ... }%Block herauszufinden, wie das geht . In Bezug auf das { ... }=hatte ich es bereits in meinen Experimenten so weit reduziert, obwohl es noch nicht veröffentlicht wurde.
Optimierer
Ich verstehe aus der Frage, dass bei einer Eingabe 3 5die Ausgabe sein sollte []und nicht""
Peter Taylor
1
@PeterTaylor "eine leere Menge / Liste / Array / etc wenn nicht möglich" - Also denke ich, dass ich es nur klarstellen muss ...
Optimierer
Plus, []pin CJam nur Ausgaben an "". Die Sprache repräsentiert also leere Arrays.
Optimierer
6

JavaScript (E6) 79 82

F=(n,t,
  d=n+n*~-n/4-t/2,
  l=1,
  q=[for(x of Array(n))d<n--?++l:(d+=~n,--l)]
)=>d?[]:q

Kein Bedarf an roher Gewalt oder Aufzählung aller Tupel.

Eine Folge der Länge n wird als n- 1-Schritte angesehen, wobei jeder Schritt inkrementiert oder dekrementiert wird.
Beachten Sie, dass Sie ein Inkrement nur gegen ein Dekrement tauschen können, die Summe variiert um 2, sodass die Summe für jede gegebene Länge immer gerade oder immer ungerade ist.
Mit allen Schritten ist die Sequenz 0, 1, 2, 3, ..., n-1 und wir wissen , ist die Summe (n-1) * n / 2
ändern Sie den letzten Schritt, die Summe Änderungen durch 2, so dass die Der letzte Schritt wiegt 2.
Wenn Sie den vorletzten Schritt ändern, ändert sich die Summe um 4, sodass der letzte Schritt 4 wiegt. Das liegt daran, dass der nachfolgende Schritt auf der bisherigen Teilsumme aufbaut.
Wenn Sie den vorherigen Schritt ändern, ändert sich die Summe um 6, sodass der letzte Schritt 6 wiegt (nicht 8, es sind keine Binärzahlen).
...
Ändern der ersten Stufe wiegt (n-1) * 2

Algorithmus

Find the max sum (all increments)  
Find the difference with the target sum (if it's not even, no solution)  
Seq[0] is 0  
For each step  
  Compare current difference with the step weight
  if is less 
     we have an increment here, seq[i] = seq[i-1]+1 
  else 
     we have a decrement here, seq[i] = seq[i-1]-1.  
     Subtract we current weight from the current diff.
If remaining diff == 0, solution is Seq[]. Else no solution

Ungolfed Code

F=(len,target)=>{
  max=(len-1)*len/2
  delta = max-target
  seq = [last=0]
  sum = 0
  weight=(len-1)*2
  while (--len > 0)
  {
    if (delta >= weight)
    {
      --last
      delta -= weight;
    }
    else
    {
      ++last
    }  
    sum += last
    seq.push(last);
    weight -= 2;
  }  
  if (delta) return [];
  console.log(sum) // to verify

  return seq
}

Test In der Firefox / FireBug-Konsole

F(8,4)

Ausgabe

[0, -1, 0, -1, 0, 1, 2, 3]
edc65
quelle
5

GolfScript ( 41 39 Bytes)

[][1,]@~:^;({{.-1=(+.)))+}%}*{{+}*^=}?`

Online-Demo

Danke an Dennis für 41-> 39.

Peter Taylor
quelle
Sie können verkürzen ,0=zu ?. Ein einfacher Port für CJam wäre 5 Bytes kürzer:L1,al~:S;({{_W=(+_)))+}%}*{:+S=}=p
Dennis
@Dennis oooh, das ist eine praktische Möglichkeit, zwei {}% -Blöcke zu fahren. Stört es mich, wenn ich es benutze?
Optimierer
@Optimizer: Ich nicht, aber es ist nicht wirklich meine Arbeit.
Dennis
Ich habe über den { ... }%Block gesprochen. In meinem Code hatte ich zwei und versuchte, ihn auf 1 zu reduzieren. Wie es sich für einen echten Algorithmus gehört, haben Peter und ich fast zur gleichen Zeit den gleichen Algorithmus veröffentlicht.
Optimierer
3

Mathematica, 73 Bytes

f=FirstCase[{0}~Join~Accumulate@#&/@Tuples[{-1,1},#-1],l_/;Tr@l==#2,{}]&;

Einfache Brute-Force-Lösung.

Ich generiere alle möglichen Schritte. Dann wandle ich diese in akkumulierte Listen um, um die One-Sequences zu erhalten. Und dann suche ich den ersten, dessen Summe gleich dem zweiten Parameter ist. Ist dies nicht der Fall, lautet der Standardwert {}.

Martin Ender
quelle
Mathematica ist nur ein Wegbereiter für mathematisch / kombinatorische Probleme, nicht wahr? ;)
Optimierer
@Optimizer Ich bin sicher, CJam wird es trotzdem schlagen. ;) Eigentlich sollte derselbe Algorithmus in CJam nicht schwer zu machen sein.
Martin Ender
1
Es wird es auf jeden Fall schlagen, aber nur wegen der kurzen Methodennamen. Der Algorithmus wird nicht so einfach sein.
Optimierer
@Optimizer, nicht wahr? Ich denke, es ist einfacher mit einer einfachen Schleife und einem Filter als mit dieser Funktionskomposition.
Peter Taylor
3

Haskell, 56 Bytes

n%s=[x|x<-scanl(+)0`map`mapM(\_->[1,-1])[2..n],s==sum x]

Erläuterung:

  • Erstellen Sie eine Liste mit den Permutationen 1,-1und der Länge n-1: replicateM n-1[-1,1]
    Beispiel: replicateM 2 [-1,1]==[[-1,-1],[-1,1],[1,-1],[1,1]]
  • Bauen Sie die One-Sequence daraus auf. scanlhat eine schlechte Leistung, aber es macht den richtigen Job hier.
  • Filtern Sie alle möglichen Einsequenzen mit der Länge, nin der sich die Summe befindets
Johannes Kuhn
quelle
1
Eine einfache Verbesserung besteht darin, eine in eine Infix-Funktion zu ändern. Hier ist ein Hinweis auf eine unintuitivere Verbesserung: Importieren Control.Monadnur für die Verwendung, replicateMdie bereits zu lang ist. Mit welcher anderen monadischen Funktion können Sie simulieren replicateM?
stolzer Haskeller
Übrigens sollten Sie nur eine Lösung zurückgeben, also sollten Sie head$Ihre Lösung ergänzen .
stolzer Haskeller
headnicht zurück []zu [] :: [[a]]- und ich Fehler hassen.
Johannes Kuhn
1
Da einige Zeit vergangen ist, werde ich Ihnen sagen, was ich meinte. Sie könnten mapM(\x->[1,-1])[2..n]anstelle von sequenceund verwenden replicate.
stolzer Haskeller
Interessant. Das ist noch kürzer: P
Johannes Kuhn
2

Python, 138

from itertools import*
def f(n,s):
 for i in[list(accumulate(x))for x in product([-1,1],repeat=n-1)]:
  if sum(i)==s:return[0]+i
 return[]
Monopol
quelle
0

CJam, 65 58 54 Bytes

Kaum kürzer als meine Mathematica-Lösung, aber das ist hauptsächlich meine Schuld, dass ich CJam immer noch nicht richtig nutze:

0]]l~:S;({{_1+\W+}%}*{0\{+_}%);}%_{:+S=}#_@\i=\0>\[]?p

Es ist buchstäblich der gleiche Algorithmus: n-1Holen Sie sich alle -tupel von {1, -1}. Suchen Sie den ersten, dessen Akkumulation der gleiche ist wie s, stellen Sie a voran 0. Drucken Sie ein leeres Array, wenn keines gefunden wird.

Martin Ender
quelle
0

CJam, 40

Ein weiterer Ansatz in CJam.

ri,W%)\_:+ri-\{2*:T1$>1{T-W}?2$+\}/])!*p
jimmy23013
quelle
0

Rubin (136)

def one_sequences(n)
  n.to_s.chars.map(&:to_i).each_cons(2).to_a.select{|x|x[0] == 0 && (x[1] == 1 || x[1]
  == -1)}.count
end
Johnson
quelle
0

J, 47 Zeichen

Überprüft jede Sequenz wie viele andere Antworten. Ich werde versuchen, eine kürzere O (n) -Lösung zu erstellen.

   f=.4 :'(<:@#}.])(|:#~y=+/)+/\0,|:<:2*#:i.2^<:x'

   8 f 4
0 1 2 1 0 1 0 _1

   3 f 5
[nothing]
randomra
quelle
0

APL 38

{⊃(↓a⌿⍨⍺=+/a←+\0,⍉1↓¯1*(⍵⍴2)⊤⍳2*⍵),⊂⍬}

Beispiel:

     4 {⊃(↓a⌿⍨⍺=+/a←+\0,⍉1↓¯1*(⍵⍴2)⊤⍳2*⍵),⊂⍬}8
0 1 2 1 0 1 0 ¯1

Dieses wie viele andere zwingt sich einfach durch jede Kombination, um ein passendes zu finden, wenn es nicht gefunden wird, gibt es nichts zurück. Tatsächlich werden einige Kombinationen mehrmals versucht, um den Code zu verkürzen.

Moris Zucca
quelle