Nummer Dreieck Flip

30

Angenommen, Sie listen die positiven Ganzzahlen in einem Dreieck auf und drehen sie dann von links nach rechts. Geben Sie bei einer gegebenen Nummer die Nummer aus, an die sie gesendet wurde. Dies ist eine selbstinverse Abbildung.

         1                      1         
       2   3                  3   2       
     4   5   6    <--->     6   5   4     
   7   8   9  10         10   9   8   7   
11  12  13  14  15     15  14  13  12  11

Dies ist das n-te Element von A038722 mit einem Index:

1, 3, 2, 6, 5, 4, 10, 9, 8, 7, 15, 14, 13, 12, 11, ...

Diese Sequenz kehrt zusammenhängende Teile der positiven ganzen Zahlen mit zunehmender Länge um:

 1, 3, 2, 6, 5, 4, 10, 9, 8, 7, 15, 14, 13, 12, 11, ...
<-><----><-------><-----------><------------------>

Testfälle:

1 -> 1
2 -> 3
3 -> 2
4 -> 6
14 -> 12
990 -> 947
991 -> 1035
1000 -> 1026
1035 -> 991
1036 -> 1081
12345 -> 12305

Bestenliste:

xnor
quelle

Antworten:

15

JavaScript (ES7), 26 Byte

n=>((2*n)**.5+.5|0)**2-n+1

Eine Implementierung der folgenden Formel aus OEIS :

Formel

Demo

Arnauld
quelle
Ich mag die ODER-Operation, um es in eine ganze Zahl zu teilen! gute Arbeit!
CraigR8806
7

Gelee , 8 7 Bytes

RṁR€UFi

Vielen Dank an @ErikTheOutgolfer für das Speichern von 1 Byte!

Probieren Sie es online!

Wie es funktioniert

RṁR€UFi  Main link. Argument: n

R        Range; yield [1, ..., n].
  R€     Range each; yield [[1], [1, 2], [1, 2, 3], ..., [1, ..., n]].
 ṁ       Mold the left argument like the right one, yielding
         [[1], [2, 3], [4, 5, 6], ...]. The elements of the left argument are 
         repeated cyclically to fill all n(n+1)/2 positions in the right argument.
    U    Upend; reverse each flat array, yielding [[1], [3, 2], [6, 5, 4], ...].
     F   Flatten, yielding [1, 3, 2, 6, 5, 4, ...].
      i  Index; find the first index of n in the result.
Dennis
quelle
6

Alice , 27 Bytes

Danke an Sp3000 für die .CIdee.

/o
\i@/.2:e2,tE*Y~Z.H2*~.C+

Probieren Sie es online!

Erläuterung

Ich denke, es gibt einen kürzeren Weg, dies mit Dreieckszahlen zu berechnen, aber ich dachte, dies ist ein interessanter Missbrauch einer eingebauten, also hier ist eine andere Lösung.

Die Grundidee besteht darin, die integrierten Funktionen "packen" und "entpacken" von Alice zu verwenden. "Pack" oder "take Ztwo integers" ordnet sie bijektiv einer einzelnen Ganzzahl zu. "Unpack" oder Yinvertiert diese Bijektion und wandelt eine Ganzzahl in zwei um. Normalerweise kann dies verwendet werden, um eine Liste oder einen Baum von Ganzzahlen in einer einzelnen (großen) Ganzzahl zu speichern und die einzelnen Werte später wiederherzustellen. In diesem Fall können wir jedoch die Funktionen in umgekehrter Reihenfolge verwenden, damit die Art der Bijektion für uns funktioniert.

Das Entpacken einer Ganzzahl in zwei Ganzzahlen besteht im Wesentlichen aus drei Schritten:

  1. Map ℤ → ℕ (einschließlich Null) mit einer einfachen "Faltung". Dies bedeutet, dass negative Ganzzahlen ungeraden Naturwerten und nicht negative Ganzzahlen geraden Naturwerten zugeordnet werden.
  2. Ordnen Sie ℕ → ℕ 2 mithilfe der Cantor-Pairing-Funktion zu . Das heißt, die Naturalien sind entlang der Diagonalen eines unendlichen Gitters geschrieben und wir geben die Indizes zurück:

       ...
    3  9 ...
    2  5 8 ...
    1  2 4 7 ...
    0  0 1 3 6 ...
    
       0 1 2 3
    

    ZB 8würde das Paar zugeordnet werden (1, 2).

  3. Ordnen Sie 2 → ℤ 2 zu , indem Sie die Umkehrung von Schritt 1 für jede ganze Zahl einzeln verwenden. Das heißt, ungerade natürliche Werte werden negativen ganzen Zahlen zugeordnet, und gerade natürliche Werte werden nicht negativen ganzen Zahlen zugeordnet.

Um zwei ganze Zahlen in eine zu packen, invertieren wir einfach jeden dieser Schritte.

Jetzt können wir sehen, dass die Struktur der Cantor-Pairing-Funktion das benötigte Dreieck bequem codiert (obwohl die Werte nicht eins sind). Um diese Diagonalen umzukehren, müssen wir nur die x- und y- Koordinaten in das Gitter tauschen .

Leider müssen wir die Zuordnungen into → ℕ oder ℕ → ℤ selbst rückgängig machen , da alle drei oben genannten Schritte in einem integrierten Y(oder Z) zusammengefasst sind . Währenddessen können wir jedoch einige Bytes durch direktes Verwenden der Zuordnungen + → ℤ oder ℤ → ℕ + speichern, um den Fehler in der Tabelle zu beheben, bei dem nur ein Byte vorkommt . Also hier ist der gesamte Algorithmus:

  1. Ordnen Sie + → ℤ mit (n / 2) * (-1) n-1 zu . Diese Zuordnung wird so gewählt, dass sie die implizite Zuordnung ℤ → ℕ während des Entpackens aufhebt , mit der Ausnahme, dass sie den Wert um 1 nach unten verschiebt.
  2. Entpacke das Ergebnis in zwei ganze Zahlen.
  3. Tausche sie aus.
  4. Packen Sie die ausgetauschten Werte erneut in eine einzelne Ganzzahl.
  5. Ordnen Sie ℤ → ℕ + mit | 2n | zu + (n≥0) . Auch dieses Mapping wird so gewählt, dass es das implizite ℕ → ℤ- Mapping während des Packens aufhebt , außer dass es den Wert um 1 nach oben verschiebt.

Damit können wir uns das Programm ansehen:

/o
\i@/...

Dies ist lediglich ein Framework für lineare arithmetische Programme mit ganzzahliger Eingabe und Ausgabe.

.    Duplicate the input.
2:   Halve it.
e    Push -1.
2,   Pull up the other copy of the input.
t    Decrement.
E    Raise -1 to this power.
*    Multiply. We've now computed (n/2) * (-1)^(n-1).
Y    Unpack.
~    Swap.
Z    Pack.
.H   Duplicate the result and take its absolute value.
2*   Double.
~    Swap with other copy.
.C   Compute k-choose-k. That's 1 for k ≥ 0 and 0 for k < 0.
+    Add. We've now computed |2n| + (n≥0).
Martin Ender
quelle
4

Oktave , 71 68 Bytes

Dank Conor O'Brien konnten 3 Bytes eingespart werden .

x=triu(ones(n=input('')));x(~~x)=1:nnz(x);disp(nonzeros(flip(x))(n))

Dies funktioniert bei großen Eingaben aufgrund von Speicherbeschränkungen nicht.

Probieren Sie es online!

Erläuterung

Betrachten Sie die Eingabe n = 4. Der Code erstellt zuerst die Matrix

 1     1     1     1
 0     1     1     1
 0     0     1     1
 0     0     0     1

Dann ersetzt es von Null verschiedenen Einträge in der Spalte-Großauftrag (nach unten, dann quer) durch 1, 2, 3...:

 1     2     4     7
 0     3     5     8
 0     0     6     9
 0     0     0    10

Dann wird die Matrix vertikal gespiegelt:

 0     0     0    10
 0     0     6     9
 0     3     5     8
 1     2     4     7

Schließlich nimmt es den n-ten Wert ungleich Null in der Hauptreihenfolge der Spalten an, was in diesem Fall der Fall ist 6.

Luis Mendo
quelle
1
@ rahnema1 Das eist Genie! Sie sollten es auf jeden Fall als Antwort zusammen mit Ihren anderen sehr guten Vorschlägen posten. Was ans =, bin ich es nie ist es sicher gültig ist oder nicht
Luis Mendo
4

Haskell , 31 Bytes

r=round
f n=r(sqrt$2*n)^2-r n+1

Probieren Sie es online!

Diese Antwort verwendet nur die Formel. Es ist die am wenigsten interessante Antwort, aber es ist auch die golferischste.

Haskell , 38 36 34 Bytes

x!y|x<=y=1-x|v<-y+1=v+(x-y)!v
(!0)

Probieren Sie es online!

(!0) ist die punktfreie Funktion, um die es uns geht.

Erläuterung

Lassen Sie mich zunächst sagen, dass ich mit dieser Antwort sehr zufrieden bin.

Die Grundidee hier ist, dass wenn wir die größte dreieckige Zahl entfernen, die kleiner als unsere Eingabe ist, wir sie umkehren und die dreieckige Zahl wieder hinzufügen können. Also definieren wir einen Operator !, !nehmen unsere regulären Eingaben x, aber es wird auch eine zusätzliche Nummer benötigt y. yVerfolgt die Größe der wachsenden Dreieckszahl. Wenn x>ywir Rekursion wollen, verringern wir xdurch yund erhöhen ynach dem anderen. Also berechnen wir (x-y)!(y+1)und ergänzen y+1es. Wenn x<=ywir unseren Basisfall erreicht haben, kehren xwir zurück , um die Platzierung in der Reihe des Dreiecks umzukehren 1-x.

Haskell , 54 Bytes

f x|u<-div(x^2-x)2=[u+x,u+x-1..u+1]
(!!)$0:(>>=)[1..]f

Probieren Sie es online!

(!!)$0:(>>=)[1..]f ist eine punktfreie Funktion

Erläuterung

Das erste, worum es uns geht f, fist eine Funktion, die xdie xdritte Zeile des Dreiecks in umgekehrter Reihenfolge aufnimmt und zurückgibt . Dazu wird zunächst die x-1nd-Dreieckszahl berechnet und dieser zugewiesen u. u<-div(x^2-x)2. Wir geben dann die Liste zurück [u+x,u+x-1..u+1]. u+xist die xdritte dreieckige Zahl und die erste Zahl in der Reihe, u+x-1ist eins weniger als diese und die zweite Zahl in der Reiheu+1 ist eins mehr als die letzte dreieckige Zahl und damit die letzte Zahl in der Reihe.

Sobald wir haben f, bilden wir eine Liste (>>=)[1..]f, die eine Abflachung des Dreiecks ist. Wir fügen der Vorderseite Null hinzu, 0:damit unsere Antworten nicht um eins versetzt werden, und geben sie an unsere Indexierungsfunktion weiter (!!).

Haskell , 56 Bytes

f 0=[0]
f x|u<-f(x-1)!!0=[u+x,u+x-1..u+1]
(!!)$[0..]>>=f

Probieren Sie es online!

Dieser ist 2 Bytes länger, aber meiner Meinung nach etwas eleganter.

Weizen-Assistent
quelle
3

C (gcc) , 48 Bytes

k,j,l;f(n){for(k=j=0;k<n;)l=k,k+=++j;n=1+k-n+l;}

Probieren Sie es online!

Wahrscheinlich suboptimal, aber ich bin ziemlich zufrieden damit. Nutzt die Tatsache, dass

NTF N = T N + A057944 ( N ) - N + 1

(Wenn ich die Formel richtig aufgeschrieben habe, ist das.)

Conor O'Brien
quelle
Sie rufen nicht return auf, sondern es wird der Rückgabewert a verwendet. Das ist undefiniertes Verhalten.
2501
@ 2501 Solange das Programm funktioniert, ist es zulässig. Das Schreiben in das erste Argument einer Funktion entspricht dem Zurückgeben eines Werts.
Conor O'Brien
Das Schreiben in das erste Argument einer Funktion entspricht dem Zurückgeben eines Werts. In der C-Sprache gibt es so etwas nicht. Der Standard sagt sogar explizit, dass die Verwendung des zurückgegebenen Werts einer Funktion, die nicht zurückgibt, undefiniertes Verhalten ist.
2501
1
@ 2501 Sie scheinen die C-Umgebung (gcc) für die C-Spezifikation zu verwirren. Ja, die C-Sprache / -Spezifikation nennt es undefiniert, aber es ist als solches implementiert. Wenn ich also "Äquivalent" sage, beziehe ich mich definitiv auf die Implementierung von C durch gcc und die meisten anderen Compiler. Bei PPCG schreiben wir keinen "perfekten" Code - viel Code widerspricht der Spezifikation, um Golf zu spielen. Wie gesagt, solange es funktioniert, ist es eine gültige Antwort.
Conor O'Brien
@ 2501 Ich empfehle Ihnen, einige Artikel auf der Meta-Site zu lesen, insbesondere diesen .
Conor O'Brien
2

05AB1E , 30 Bytes

U1V[YLO>X›iYLOX-UY<LO>X+,q}Y>V

Probieren Sie es online!

Eduardo Hoefel
quelle
Ich wollte gerade sagen: "Was? Eine 05AB1E-Antwort ohne Unicode?" aber dann ruiniert das eine Nicht-ASCII-Zeichen es ...: P Schöne erste Antwort, willkommen bei Programming Puzzles and Code Golf!
Clismique
@ Qwerp-Derp Vielen Dank! Ich habe gerade angefangen, diese Sprache zu lernen, daher wundere ich mich nicht, dass meine Antwort so schlecht war.
Eduardo Hoefel
2

Schale , 6 Bytes

!ṁ↔´CN

Probieren Sie es online!

Erläuterung

!ṁ↔´CN  -- implicit input N, for example: 4
   ´ N  -- duplicate the natural numbers:
           [1,2,3,…] [1,2,3,…]
    C   -- cut the second argument into sizes of the first:
           [[1],[2,3],[4,5,6],[7,8,9,10],…]
 ṁ↔     -- map reverse and flatten:
           [1,3,2,6,5,4,10,9,8,7,15,…
!       -- index into that list:
           6
ბიმო
quelle
2

tinylisp , 78 bytes

(d _(q((R N T)(i(l T N)(_(a R 1)N(a T R))(a 2(a T(s T(a N R
(d f(q((N)(_ 2 N 1

Definiert eine Funktion f, die das Mapping ausführt. Probieren Sie es online!

Ungolfed

Wir finden die kleinste Dreieckszahl, die größer oder gleich der eingegebenen Zahl ist, sowie die Zeile des Dreiecks, in der sich unsere Zahl befindet. Daraus können wir die gespiegelte Version der Zahl berechnen.

  • Wenn die aktuelle Dreieckszahl kleiner als N ist, fahren Sie mit der nächsten Zeile des Dreiecks fort. (Wir behandeln die oberste Zeile als Zeile 2, um die Mathematik zu vereinfachen.)
  • Ansonsten ist die gespiegelte Version von N (TN) + (TR) +2.

Die Hauptfunktion flipruft einfach die Hilfsfunktion _flipab der obersten Zeile auf.

(load library)

(def _flip
 (lambda (Num Row Triangular)
  (if (less? Triangular Num)
   (_flip Num (inc Row) (+ Triangular Row))
   (+ 2
    (- Triangular Num)
    (- Triangular Row))))))

(def flip
 (lambda (Num) (_flip Num 2 1)))
DLosc
quelle
1

05AB1E , 9 Bytes

·LD£í˜¹<è

Probieren Sie es online!

Erläuterung

·L          # push range [1 ... 2n]
  D         # duplicate
   £        # split the first list into pieces with size dependent on the second list
    í       # reverse each sublist
     ˜      # flatten
      ¹<è   # get the element at index <input>-1

Das Reduzieren von Arrays kann mit größeren Listen leider nicht sehr gut umgehen.
Auf Kosten von 1 Byte könnten wir · t2z + ïn¹-> unter Verwendung der floor(sqrt(2*n)+1/2)^2 - n + 1in OEIS gefundenen mathematischen Formel ausführen .

Emigna
quelle
1

Batch, 70 Bytes

@set/ai=%2+1,j=%3+i
@if %j% lss %1 %0 %1 %i% %j%
@cmd/cset/ai*i+1-%1

Verwendet eine Schleife, um den Index der Dreieckszahl zu finden, der mindestens so groß ist wie n.

Neil
quelle
0

PHP, 35 Bytes

<?=((2*$argn)**.5+.5^0)**2-$argn+1;

Dieselbe Formel wie im Arnaulds Approach

Jörg Hülsermann
quelle
0

C #, 46 44 Bytes

n=>Math.Pow((int)(Math.Sqrt(2*n)+.5),2)-n+1;

Ich portiere @ Arnauld's Lösung . Vielen Dank!

  • Pow von 0,5 ist Sqrt. 2 Bytes gespeichert!
aloisdg sagt Reinstate Monica
quelle
0

APL (Dyalog), 27 Bytes

Ich habe zwei Lösungen gleichzeitig bytecount.

Ein Zug:

⊢⊃⊃∘(,/{⌽(+/⍳⍵-1)+⍳⍵}¨∘⍳)

Probieren Sie es online!

Und ein DFN:

{⍵⊃⊃((⍳⍵),.{1+⍵-⍳⍺}+\⍳⍵)}

Probieren Sie es online!

Beide Lösungen erstellen zuerst das gespiegelte Dreieck und extrahieren dann das Element an dem Index, der durch das Argument ( 1-basiert) angegeben wird.

Kritixi Lithos
quelle
0

J, 25 Bytes

3 :'>:y-~*:>.-:<:%:>:8*y'

Als Erklärung betrachten f(n) = n(n+1)/2. f(r), angesichts der Reiher die am weitesten links stehende Zahl der rth Zeile des gespiegelten Dreiecks zurück. Nun überlegen Sie g(n) = ceiling[f⁻¹(n)]. g(i)Gibt bei gegebenem Index idie Zeile zurück, in der sich der Index i befindet. Dann f(g(n))gibt die am weitesten links stehende Nummer der Zeile , auf dem Index n gefunden wird. Also, h(n) = f(g(n)) - (n - f(g(n)-1)) + 1ist die Antwort auf das obige Problem.

Vereinfachend bekommen wir h(n) = [g(n)]² - n + 1 = ceiling[(-1 + sqrt(1 + 8n))/2]² - n + 1.

Aus der Formel von @ Arnauld geht Folgendes hervor:

ceiling[(-1 + sqrt(1 + 8n))/2] = floor[1/2 + sqrt(2n)].

ljeabmreosn
quelle