Generalisierte Gray-Codes

13

Eingabe: Ein Array I von k positiven ganzen Zahlen. Die ganzen Zahlen sind nicht größer als 100 und k ≤ 100 .

Ausgabe: Ihr Code muss alle möglichen Arrays O nicht negativer Ganzzahlen der Länge k mit der Einschränkung ausgeben, dass 0 ≤ O i ≤ I i . Um von einem Array zum nächsten zu gelangen, können Sie 1 zu einem Wert im Array addieren oder subtrahieren. Ihr Code darf nicht dasselbe Array zweimal ausgeben. Wenn die Anzahl der auszugebenden Arrays sehr groß ist, sollte Ihr Code nur für immer weiter ausgegeben werden, bis er getötet wird.

Beispiele

  • Wenn ich ein Array von k Einsen bin , dann ist dies genau das Problem des Iterierens über alle Gray-Codes der Bitbreite k , mit der Ausnahme, dass das erste und das letzte Element nicht in einem Schritt erreichbar sein müssen.

  • Wenn I = [2,1]ja, ist eine mögliche Reihenfolge der Ausgabearrays(0,0),(0,1),(1,1),(1,0),(2,0),(2,1)

  • Wenn I = [2,1,3]ja, ist eine mögliche Reihenfolge der Ausgabearrays (0,0,0),(0,0,1),(0,0,2),(0,0,3),(0,1,3),(0,1,2),(0,1,1),(0,1,0),(1,1,0),(1,1,1),(1,1,2),(1,1,3),(2,1,3),(2,1,2),(2,1,1),(2,1,0),....

Dies ist eine Code-Golf-Herausforderung, die Einreichung mit dem Quellcode mit der kürzesten Länge gewinnt. Lassen Sie sich durch die kurzen Antworten in Golfsprachen nicht davon abhalten, eine Antwort in anderen Sprachen zu verfassen. Versuchen Sie, die kürzeste Antwort in einer beliebigen Sprache zu finden.

Dies ist auch eine Herausforderung mit eingeschränkter Komplexität. Jedes neue Array sollte mit einer O (k) -Zeit ausgegeben werden, die seit dem vorherigen ausgegebenen Array (oder dem Start des Programms für das erste ausgegebene Array ) verstrichen ist. Dies bedeutet, dass die Laufzeit pro neuem Ausgangsarray (sie haben jeweils die Länge k ) nicht größer als O (k) sein sollte . Das heißt, es sollte zeitproportional zu k sein und nicht beispielsweise k 2 oder 2 k . Beachten Sie, dass dies nicht die durchschnittliche Zeit pro Ausgang ist, sondern die Zeit im ungünstigsten Fall für jedes ausgegebene Array.

Sie können davon ausgehen, dass alle Arithmetikoperationen mit 64-Bit-Ganzzahlen in konstanter Zeit ausgeführt werden können, ebenso wie das Lesen und Ausgeben sowie das Zuweisen und Nachschlagen und Ändern von Werten in Arrays.

Eine Folge der eingeschränkten Komplexität ist, dass Lösungen, die nur beim Beenden des Programms ausgegeben werden, nicht akzeptabel sind.

Anush
quelle
1
(sollte "addiere oder subtrahiere 1" modulo durchgeführt werden I_i+1? Kannst du 0 von erreichen I_i?)
user202729
@ user202720 Nein, das habe ich nicht beabsichtigt.
Anush
Wie funktioniert die Komplexität, wenn nund ksind sie begrenzt? vorausgesetzt, sie gehen mit der Bitbreite ins Unendliche
l4m2
@ l4m2 Für die Komplexitätsanalyse wird angenommen, dass k gegen unendlich geht.
Anush
@Anush also wie geht die Bitbreite?
14 m²,

Antworten:

4

Python 3 , 116 Bytes

def f(a):
 l=len(a);t=[0]*l;d=[1]*l
 while 1:
  i=0;yield t
  while not-1<t[i]+d[i]<=a[i]:d[i]*=-1;i+=1
  t[i]+=d[i]

Probieren Sie es online!

Danke Mnemonic für -1 Byte.

Generatorfunktion. (danke Dennis für die Erinnerung, ich habe vergessen, dass es die Funktion gibt) Wenn die Ausgabe auf stdout gedruckt werden soll, verwenden Sie print(t,flush=1)9 zusätzliche Bytes, oder wenn Python mit aufgerufen wird -u, print(t)reicht dies für +1 Bytes.

Stoppt mit einem Fehler ( IndexError). Wenn Sie diese Funktion aufrufen und dann das Programm fortsetzen möchten, müssen Sie sie abfangen.

user202729
quelle
Wie lange läuft die innere while-Schleife?
Anush
@Anush Bei den meisten kSchritten, da bei jedem Schritt ium 1und nach kSchritten erhöht i==kund d[i]ein Fehler verursacht wird.
user202729
Dies ist eine sehr schöne Lösung.
Anush
Sie können durch Ersetzen eines Byte speichern not 0<=mit not-1<.
1
Könnten Sie yield tanstelle von verwenden print(t,flush=1)?
Dennis
2

Stax , 22 Bytes

▒)∙ñ╚▀NK♀F☺S(A#P`░]╪Db

Führen Sie es aus, und debuggen Sie es

Hier ist ein großes Beispiel für das asymptotische Verhalten .

Ausgepackt, ungolfed und kommentiert sieht es so aus.

,           pop from input to main stack
W           run the rest of the program repeatedly until explicitly cancelled
  cJP       copy top of stack and print, delimited by spaces
            get the index to mutate
  i^            iteration index + 1
  x{^|%}I       repeatedly apply divmod using l[k]+1 from input
                get the index of the first value that returns modulus >0
  cU=C      if the result is -1 (no match), then terminate the program
            get the direction to mutate
  s             get the "div" part of the last div operation called "d"
  ^|1           -1 ^ (d+1)
  ~{+}&     increment element in array at the index by the calculated amount

Führen Sie dieses aus

rekursiv
quelle
1
Gemessen an der Bitkomplexität ist der Iterationsindex O(k)Bits, daher können Teilungszeiten kO(k²)
einige
1

JavaScript (Node.js) , 114 Byte

a=>{b=a.map(_=>0);c=a.map(_=>1);for(i=0;a[i];b[i]+=c[i]||-1){console.log(b);for(i=0;b[i]==a[i]*c[i];i++)c[i]^=1;}}

Probieren Sie es online! Ungolfed:

function ggray(maxima) {
    var current = Array(maxima.length).fill(0);
    var flag = Array(maxima.length).fill(1);
    for (;;) {
        console.log(current);
        for (var i = 0; ; i++) {
            if (i == maxima.length) return;
            if (current[i] != maxima[i] * flag[i]) break;
            flag[i] = 1 - flag[i];
        }
        if (flag[i]) current[i]++;
        else current[i]--;
    }
}
Neil
quelle
1

Kotlin , 181 178 Bytes

Dank an: Anush wies darauf hin, dass ich die Herausforderung, 2 Bytes zu sparen, falsch verstanden habe. ovs wies auf eine Einsparung von 1 Byte hin.

val p={a:List<Int>->var l=a.size
val v=Array(l,{0})
val i=Array(l,{1})
l-=1
o@while(0<1){println(v)
var p=l
while(v[p]+i[p]!in 0..a[p]){i[p]*=-1
p-=1
if(p<0)break@o}
v[p]+=i[p]}}

Probieren Sie es online!

JohnWells
quelle
1
Für das Beispiel in der Frage mit 2 1 3 benötigt Ihr Code anscheinend 3 2 4 als Eingabe.
Anush
1
while(true)kann seinwhile(1<2)
ovs