Reparieren Sie die Bereiche

30

Wenn Sie eine Liste mit positiven ganzen Zahlen eingegeben haben, wobei einige durch ersetzt wurden 0, geben Sie die Liste mit den fehlenden Zahlen aus, die in " 0Ersetzt" geändert wurden.

Merkmale der Eingabeliste:

  • Die Liste hat immer eine Länge von mindestens 2.

  • Definieren wir die Eingabeliste als aund die "Originalliste" (dh die Liste vor dem Ersetzen von Zahlen durch 0s) als b. Für alle n, a[n]entweder b[n]oder 0.

  • Für alle n, b[n]entweder b[n-1] + 1oder b[n-1] - 1. Das heißt, die Zahlen in bändern sich 1bei jedem Index gegenüber dem vorherigen immer um. Das erste Element ist natürlich von dieser Regel ausgenommen.

  • Für jeden Lauf von Nullen in a( , die mit aufeinander folgenden Elemente ersetzt sind 0), wobei xdie den Index des Beginns des Laufes und y das den Zweck a[x-1]zu a[y+1]immer entweder allein zuzunehmen oder ausschließlich abnimmt. Daher gibt es nur eine Möglichkeit, die Nullen auszufüllen.

    • Dies bedeutet auch, dass weder das erste noch das letzte Element des Arrays Nullen sein dürfen.

Einfacher ausgedrückt: Um eine Reihe von Nullen auszufüllen, ersetzen Sie sie einfach durch einen Bereich von der vorherigen bis zur darauf folgenden Zahl. Zum Beispiel eine Eingabe von

1 2 0 0 0 6 7

muss ausgeben

1 2 3 4 5 6 7

Da es sich um , wird der kürzeste Code in Bytes gewinnen.

Testfälle:

In                      Out
-----------------------------------------------------
1 0 0 0 5 6 0 4 0 0 1 | 1 2 3 4 5 6 5 4 3 2 1
7 6 0 0 3 0 0 0 7 0 5 | 7 6 5 4 3 4 5 6 7 6 5
1 0 3 0 5 0 3 0 5 0 7 | 1 2 3 4 5 4 3 4 5 6 7
14 0 0 0 0 0 0 0 0 23 | 14 15 16 17 18 19 20 21 22 23
Türknauf
quelle
Anstelle von 0kann unser Programm einen anderen Wert annehmen wie null?
Downgoat
@Downgoat Nein, fehlende Nummern müssen als angegeben werden 0.
Türknauf

Antworten:

15

JavaScript (ES6), 72 66 64 54 53 Byte

12 Bytes gespart dank @Neil!

1 Byte dank @IsmaelMiguel gespeichert

a=>a.map((l,i)=>l?b=l:b+=a.find((q,r)=>r>i&&q)>b||-1)

Ziemlich gut für JavaScript.


Probieren Sie es online aus (alle Browser funktionieren)

Erläuterung

a=>  // Function with arg `a`
  a.map((l,i)=>  // Loop through input
    l?             // If nonzero
      b=l          // Set `b` to current number
    :a.find((q,r)=>r>i&q) // Otherwise look for the next nonzero number
     >b?           // If it's increased since nonzero last number   
       ++b:--b)    // Increasing? increase `b` (the previous nonzero number)
                   // otherwise decrease `b`
Downgoat
quelle
1
Ich denke, das a.find((q,r)=>r>i&&q)>b?++b:--bist dasselbe wieb+=a.find((q,r)=>r>i&&q)>b||-1
Ismael Miguel
@IsmaelMiguel das ist schlau, danke!
Downgoat
Bitte. Ich bin froh, dass es für dich geklappt hat.
Ismael Miguel
Ich denke, Sie können && mit nur & ersetzen (nur bemerkt, dass Sie eine & in der Erklärung und zwei in der Antwort haben)
Charlie Wynn
7

MATL , 11 12 Bytes

fGXzGn:3$Yn

Funktioniert mit der aktuellen Version (13.0.0) der Sprache / des Compilers.

Probieren Sie es online!

f        % implicitly input array. Indices of nonzero elements (*)
GXz      % push input and get its nonzero elements (**)
Gn:      % vector [1,2,...,n], where n is input length (***)
3$Yn     % interpolate at positions (***) from data (**) defined at positions (*)
Luis Mendo
quelle
7

Haskell, 68 61 58 Bytes

g(a:b:r)=[a..b-1]++[a,a-1..b+1]++g(b:r)
g x=x
g.filter(>0)

Anwendungsbeispiel: g.filter(>0) $ [7,6,0,0,3,0,0,0,7,0,5]-> [7,6,5,4,3,4,5,6,7,6,5].

So funktioniert es: Nullen aus der Eingabe entfernen und dann aufrufen g. Sei adas erste und bdann das zweite Element der verbleibenden Liste. Verketten die Listen von anach oben b-1und von aunten zu b+1(einer von ihnen wird leer sein) und einen rekursiven Aufruf mit agesunken.

Edit: @Zgarb hat 3 Bytes gespeichert. Vielen Dank!

nimi
quelle
6

Mathematica, 59 Bytes

#//.{a___,x_,0..,y_,b___}:>{a,##&@@Range[x,y,Sign[y-x]],b}&

Testfall

%[{1,0,3,0,5,0,3,0,5,0,7}]
(* {1,2,3,4,5,4,3,4,5,6,7} *)
njpipeorgan
quelle
4

Perl, 47 45 44 39 37 Bytes

Beinhaltet +1 für -p

s%\S+%$p+=/\G(0 )+/?$'<=>$p:$&-$p%eg

Erwartet die Liste auf stdin. Beispiel: echo 1 0 3 0 1 | perl -p file.pl

Tonne Hospel
quelle
Ich sehe hier ein paar Kopien einfügen .. ;-) Schön gemacht übrigens.
Kenney
3

Jelly, 12 11 Bytes

ḢWW;ḟ0Ṫr¥\F

Probieren Sie es online!

Alternative Version, 8 Bytes (nicht konkurrierend)

Leider wurde Jelly's popin der neuesten Version vor dieser Herausforderung nicht als iterabel bezeichnet. Dies wurde behoben und das Folgende funktioniert in der aktuellen Version.

ḟ0Ṫr¥\FḊ

Probieren Sie es online!

Wie es funktioniert

ḢWW;ḟ0Ṫr¥\F  Main link. Input: A (list)

Ḣ            Pop the first element of A. Let's call it a.
 WW          Yield [[a]].
   ;         Concatenate with the popped A.
             This wraps the first element of A in an array.
    ḟ0       Filter; remove all zeroes.
        ¥    Create a dyadic chain:
      Ṫ        Pop the last element of the left argument.
       r       Call range on the popped element and the right argument.
         \   Reduce the modified A by this chain.
          F  Flatten the resulting list of ranges.

In der alternativen Version ḢWW;wird unnötig. Da das erste Element jedoch vor dem Poppen in iterierbar umgewandelt wird, wird es tatsächlich nicht geändert. Das Finale entfernt das Duplikat des ersten Elements.

Dennis
quelle
3

Retina, 39 34 31 Bytes

3 Bytes gespart dank @Martin.

+`1(1*) (?= +((1)\1)?)
$0$1$3$3

Übernimmt die Eingabe und gibt die Ausgabe in unary.

Der Code füllt iterativ jede leere Stelle (0) mit previous_number - 1 + 2 * if_next_nonzero_number_bigger. previous_number - 1ist $1und if_next_nonzero_number_biggerist $3.

Bei dezimaler E / A ist der Code 51 Byte lang, wie Sie im Online-Interpreter mit allen Testfällen sehen können .

randomra
quelle
Sie können ein weiteres Byte speichern, indem Sie das erste 1im Lookahead weglassen .
Martin Ender
@ MartinBüttner Richtig, bearbeitet.
Randomra
2

GNU Sed (mit execErweiterung durch bash), 61

Die Punktzahl enthält +1 für die -rOption zum Beruhigen.

:
s/( 0)+ /../
s/\w+..\w+/{&}/
s/.*/bash -c 'echo &'/e
/ 0/b
  • Finde Läufe von 0s und ersetze sie..
  • Platzieren Sie geschweifte Klammern um die Endpunktnummern, um eine Bash-Klammer-Erweiterung wie {1..4}für die lokalen Endpunkte zu erstellen . Das Schöne an den Bash-Klammer-Erweiterungen ist, dass die generierte Sequenz immer in die richtige Richtung verläuft, unabhängig davon, ob der Anfang oder das Ende größer ist.
  • Verwenden Sie die eOption für den sBefehl, um bash aufzurufen und diese Klammererweiterung auszuwerten
  • Wenn weitere 0s gefunden werden, springen Sie zum Anfang zurück.

Ideone.

Digitales Trauma
quelle
2

Python 2, 195 111 Bytes (danke Alex !)

t=input()
z=0
for i,e in enumerate(t):
 if e:
  while z:t[i-z]=e+z if l>e else e-z;z-=1
  l=e
 else:z+=1
print t

Eingabe: muss ein [list]von Ints sein
Ausgabe: [list]von Ints

vageli
quelle
Das tut mir leid! Fest. Vielen Dank für die Köpfe hoch.
Vageli
Keine Bange. Gute Lösung. :) Sie können es auf 112 Bytes herunterkommen mit dieser , die Ihre gleichen Ansatz ist, nur ein bisschen mehr golfed. Wir haben auch eine Sammlung von Tipps zum Golfen in Python hier .
Alex A.
1

Perl, 85 82 Bytes

beinhaltet +1 für -p

s/(\d+)(( 0)+) (\d+)/$s=$1;$e=$4;$_=$2;$c=$s;s!0!$c+=$e<=>$s!eg;"$s$_ $e"/e&&redo

Erwartet die Liste auf stdin. Beispiel: echo 1 0 3 0 1 | perl -p file.pl.

Dies verwendet einen verschachtelten regulären Ausdruck. Etwas lesbar:

s/(\d+)(( 0)+) (\d+)                  # match number, sequence of 0, number
 /
    $s=$1;                            # start number
    $e=$4;                            # end number
    $_=$2;                            # sequence of ' 0'
    $c=$s;                            # initialize counter with start number
    s!0! $c += $s <=> $e !eg          # replace all 0 with (in|de)cremented counter
    "$s$_ $e"                         # return replacement
 /e
&& redo                               # repeat until no more changes.
Kenney
quelle
1

Python 2, 92 88 Bytes

(Zwischenvariable entfernt)

t=filter(bool,input())
print sum([range(o,p,cmp(p,o))for o,p in zip(t,t[1:])],[])+t[-1:]
Orez
quelle
1

Pyth, 17 Bytes

u+G+treGHHfTtQ[hQ

So funktioniert es:

u                 reduce
              [hQ     seed: the first element of input, in a list
                      iterable:
          tQ              all except the first element of input
        fT                remove if 0
                      lambda: G is the list to be returned, H is the current item
 +G                       append to return list
    reGH                  a range from the last element of the return list and the current item
   +                      concatenated with
        H                 the last item (this step forms a bidirectional inclusive list)

Mit anderen Worten: Alle Nullen werden aus der Eingabe entfernt, und zwischen jedem Element wird ein exklusiver Bereich eingefügt. Dieser Bereich ist für Elemente mit nur einem Abstand Null.

Cameron McCluskie
quelle
1

Vim: 231 Schlüsselbefehle

Beachten Sie, dass jedes ^ vor einem Zeichen bedeutet, dass Sie die Kontrolle behalten sollten, während Sie dieses Zeichen eingeben

mbomayiwo^V^R"^V^V^V^X ^V^["sy0dd`a@f ^["bc0yiwo^V^V^V^X^V^R"^V^[0l@sa^V^V^V^A-^V^[0f-"ayhdd`a@i ^["dc0mbyiwo^V^R"Exe@b^V^[0fel"ty2ldd`b@t ^["ec0wmbyiwo@f @d^V^[@z ^["fc0"xyiwwmbyiwocw^V^V^V^Rx^V^V^V^[@a@i @e^V^[@z ^["ic0IB0 B^V^R" ^V^OWB0 ^V^OA B0^V^[0*w"tyiWdd`b@t ^["zd0dd`bAe^[0@e 

Schritte, damit Sie dies auch ausführen können!

  1. Kopieren Sie die Zeile in Vim
  2. Tippen Sie ein :s/\^V/<Ctrl-V><Ctrl-V>/gund drücken Sie die Eingabetaste (die beiden s sollten ein blaues ^ V ergeben)
  3. Tippen Sie ein :s/\^R/<Ctrl-V><Ctrl-R>/gund drücken Sie die Eingabetaste (Sie sollten jetzt blau ^ Rs sehen)
  4. Tippen Sie ein :s/\^X/<Ctrl-V><Ctrl-X>/gund drücken Sie die Eingabetaste (Sie sollten jetzt ein blaues ^ X sehen)
  5. Geben Sie ein :s/\^O/<Ctrl-V><Ctrl-O>/gund drücken Sie die Eingabetaste
  6. Geben Sie ein :s/\^A/<Ctrl-V><Ctrl-A>/gund drücken Sie die Eingabetaste
  7. Geben Sie ein :s/\^\[/<Ctrl-V><Ctrl-[>/gund drücken Sie die Eingabetaste (dieser Befehl ist etwas anders, weil ich das [entkommen musste)
  8. Typ 0"yy$. Der Befehl ist jetzt im y-Register gespeichert
  9. Richten Sie die Eingabe in einer Zeile ein und führen Sie sie mit aus @y

Wenn jemand eine bessere Möglichkeit zum Teilen des Befehls kennt, lassen Sie es mich bitte wissen. Ich weiß, das ist langwierig, aber es ist das Beste, was ich mir vorstellen kann.

Input-Output

Die Eingabezeichenfolge sollte in jeder Zeile der Datei einzeln stehen. 1 0 0 4 3 0 0 0 7

Die Ausgabe überschreibt einfach die Eingabezeichenfolge 1 2 3 4 3 4 5 6 7

Erläuterung

Algorithmus

  1. Beginnen Sie mit einer Zahl ungleich Null und vergewissern Sie sich, dass es nicht die letzte Zahl ist
  2. Suchen Sie die nächste Zahl ungleich Null
  3. Nimm ihren Unterschied. Wenn die Antwort negativ ist, sollten Sie die Anzahl verringern, um den Bereich zu reparieren. Andernfalls erhöhen Sie die Anzahl, um den Bereich zu reparieren.
  4. Gehen Sie zurück zum ersten Zeichen und ersetzen Sie jede Null durch Erhöhen / Verringern der vorherigen Zahl.
  5. Wiederholen Sie diesen Vorgang, bis Sie das letzte Zeichen erreicht haben

Verwendete Makros

@e - Auf Ende prüfen. An die letzte Nummer wird ein e angehängt. Wenn die Zahl unter dem Cursor ein e am Ende hat, löschen Sie das e und stoppen Sie die Ausführung. Andernfalls starten Sie einen Interpolationszyklus mit @b.

mbyiwo^R"Exe@b^[0fel"ty2ldd`b@t

@b - Interpolationszyklus starten. Speichern Sie die Zahl unter dem Cursor für eine Subtraktionsoperation (@s) und suchen Sie dann den nächsten Ausdruck ungleich Null (@f)

mayiwo^R"^V^X ^["sy0dd`a@f

@s - Speichert den in @d zu verwendenden Subtraktionsbefehl. Es ist einfach, (val)^Xwo (val)die Nummer zu Beginn des Interpolationsschritts ist. Dies wird mit dem Befehl @b festgelegt.

@f - Finde den nächsten Ausdruck ungleich Null. Schreiben Sie den aktuellen Wert in das unbenannte Register, schreiben Sie @f @din die nächste Zeile und führen Sie dann @z aus. Dies wiederholt diesen Befehl, wenn die Zahl Null ist, und führt @d aus, wenn dies nicht der Fall ist.

wmbyiwo@f @d^[@z

@z - Bedingte Ausführung, wenn das unbenannte Register 0 ist. Dieser Befehl erwartet zwei Befehle in einer neuen Zeile im Format command1 command2. Wenn das unbenannte Register 0 ist, command1wird ausgeführt, ansonsten command2wird ausgeführt. Beachten Sie, dass keiner der Befehle Leerzeichen enthalten kann.

 IB0 B^R" ^OWB0 ^OA B0^[0*w"tyiWdd`b@t`

@t - Temporäres Befehlsregister. Speichert verschiedene Befehle für kurze Zeit, bevor sie ausgeführt werden. Wird hauptsächlich in if-Anweisungen verwendet.

@d - Interpolationsrichtung bestimmen. Subtrahiert die erste Zahl in der Sequenz von der Zahl unter dem Cursor (mit @s). Wenn das Ergebnis negativ ist, muss die Interpolation dekrementiert werden, damit ^ X in @a gespeichert wird. Andernfalls sollten wir erhöhen, damit ^ A in @a gespeichert wird. Sobald dies gespeichert ist, gehen Sie zurück zum Anfang dieses Interpolationszyklus und führen Sie @i aus, um tatsächlich zu interpolieren

yiwo^V^X^R"^[0l@sa^V^A-^[0f-"ayhdd`a@i

@a - Speichert entweder ^Aoder ^Xzum Inkrementieren oder Dekrementieren während des Interpolationsschritts. Dies wird mit dem Befehl @d festgelegt.

@i - Interpolieren. Kopieren Sie die Nummer an der aktuellen Position nach @x und wechseln Sie zur nächsten Nummer. Wenn diese Zahl Null ist, ersetzen Sie sie durch @x und führen Sie @a aus, um sie ordnungsgemäß nach oben oder unten zu ändern. Wiederholen Sie dann diesen Befehl. Wenn die Zahl keine Null ist, haben wir das Ende dieses Interpolationszyklus erreicht. Ein neues sollte mit dieser Nummer als Anfang gestartet werden. Führen Sie also @e aus, um nach dem Ende zu suchen, und führen Sie es erneut aus.

"xyiwwmbyiwocw^V^Rx^V^[@a@i @e^[@z

@x - Temporäres Speicherregister. Wird im Interpolationsbefehl verwendet (@i)

Tastenanschläge aufteilen

mbo :Set b mark to current position and open a new line below to write macros
mayiwo^V^R"^V^V^V^X ^V^["sy0dd`a@f ^["bc0 :Write to @b and reset line

yiwo^V^V^V^X^V^R"^V^[0l@sa^V^V^V^A-^V^[0f-"ayhdd`a@i ^["dc0 :Write to @d and reset line

mbyiwo^V^R"Exe@b^V^[0fel"ty2ldd`b@t ^["ec0 :Write to @e and reset line

wmbyiwo@f @d^V^[@z ^["fc0 :Write to @f and reset line

"xyiwwmbyiwocw^V^V^V^Rx^V^V^V^[@a@i @e^V^[@z ^["ic0 :Write to @i and reset line

IB0 B^V^R" ^V^OWB0 ^V^OA B0^V^[0*w"tyiWdd`b@t ^["zd0 :Write to @z and reset line

dd`b :Delete this line and move cursor back to original line

Ae^[ :Append an e to the last number

0@e  :Move to the beginning of the line and run
Dominic A.
quelle
0

Python 3.5, 159 Bytes

eine rekursive Lösung

def f(s):
 h=s[0]
 g=lambda s,h,v:h*(h[-1]==s[0])if len(s)==1else(g(s[1:],h+[h[-1]-v],-v)+g(s[1:],h+[h[-1]+v],+v))*(s[0]==0 or h[-1]==s[0])
 return g(s,[h],1)

Ungolfed

def f(s):
    h=s[0]
    def g(s,h,v):
        if len(s)==1:
            if h[-1]!=s[0]:
                r=[]
            else:
                r=h
        else:
            if s[0]==0:
                r=g(s[1:],h+[h[-1]+v],v)
            elif h[-1]!=s[0]:
                r=[]
            else:
                r=g(s[1:],h+[h[-1]-v],-v)+g(s[1:],h+[h[-1]+v],+v)
        return r
return g(s,[h],1)

In der Golf-Lösung ersetze ich Bedingungen, indem ich die Tatsache nutze, dass h*True=hundh*False=[]

Ergebnis

>>> f([7, 6, 0, 0, 3, 0, 0, 0, 7, 0, 5])
[7, 6, 5, 4, 3, 4, 5, 6, 7, 6, 5]
Erwan
quelle
0

Perl 6 , 54 Bytes

{$_=$^a;1 while s/:s(\d+) 0 + (\d+)/{+~$0...+~$1}/;$_}
smls
quelle
0

MATLAB, 39 38 37 Bytes

@(a)interp1(find(a),a(a>0),find(a/0))

Anonyme Funktion, die linear zwischen den Punkten in interpoliert a. find(a)ist ein Array von Indizes von Nicht-Null-Elementen in aund a(a>0)sind die positiven Werte. 1 Byte gespart dank des Vorschlags eines Freundes von >anstatt ~=.

MattWH
quelle