Ihre Basis zu 1-2-3-Tribonacci binär zurück zu Ihrer Basis

19

Hintergrund

Die 1-2-3-Tribonacci-Sequenz

Stellen Sie sich für eine Sekunde vor, Sie könnten eine Fibonacci-Sequenz erstellen, indem Sie die Standard-Iterationsformel durch Folgendes ersetzen:

Tribonacci

Anstatt die letzten beiden zu addieren, um die nächsten zu erhalten, summieren Sie die letzten drei. Dies ist die Basis für die 1-2-3-Tribonacci-Sequenz.

Browns Kriterium

Browns Kriterium besagt, dass Sie einen beliebigen ganzzahligen Wert als Summe der Mitglieder einer Sequenz darstellen können, vorausgesetzt, dass:

  1. x sub n ist gleich 1

  2. Für alle n größer als 1,x sub n kleiner als 2 x sub n - 1

Was dies für die Herausforderung bedeutet

Sie können jede positive ganze Zahl als eine Summe von Mitgliedern der 1-2-3-Tribonacci-Sequenz beschreiben, die sich aus den folgenden Anfangsbedingungen zusammensetzt:

Anfangsbedingungen

Dies ist bekannt, da für jeden Wert in dieser Sequenz das Verhältnis zwischen Termen niemals größer als 2 ist (das Verhältnis ergibt einen Durchschnitt von etwa 1,839).

Wie schreibe ich in diesem numerischen Darstellungssystem?

Angenommen, Sie verwenden eine Little-Endian-Darstellung. Richten Sie die Mitglieder der Sequenz wie folgt aus:

1  2  3  6 11 20 37 68

Dann nehmen Sie Ihre Zahl, um dargestellt zu werden (für unsere Tests sagen wir es ist 63) und finden die Werte der gegebenen 1-2-3-Tribonacci, die sich zu 63 summieren (unter Verwendung der größten Werte zuerst!) . Wenn die Zahl Teil der Summe ist, setzen Sie eine 1 darunter, andernfalls eine 0.

1  2  3  6 11 20 37 68
0  0  0  1  0  1  1  0

Sie können dies für eine beliebige Ganzzahl tun - stellen Sie einfach sicher, dass Sie zuerst die größten Werte unter Ihrer angegebenen Eingabe verwenden!

Definition (endlich)

Schreiben Sie ein Programm oder eine Funktion, die bei einer positiven Ganzzahleingabe n(in einer beliebigen Standardbasis) zwischen 1 und dem Maximalwert Ihrer Sprache Folgendes bewirkt:

  1. Konvertieren Sie den Wert in die definierte numerische Darstellung von 1-2-3-Tribonacci.
  2. Verwenden Sie diese binäre Darstellung und lesen Sie sie als wäre sie binär. Dies bedeutet, dass die Ziffern gleich bleiben, aber was sie bedeuten, ändert sich.
  3. Nehmen Sie diese Binärzahl und rechnen Sie sie in die Basis der ursprünglichen Zahl um.
  4. Diese neue Nummer ausgeben oder zurückgeben.

Solange die Ausgabe gültig ist, müssen Sie diese Schritte jedoch nicht ausführen. Wenn Sie auf magische Weise eine Formel finden, die kürzer (und mathematisch äquivalent) ist, können Sie sie gerne verwenden.

Beispiele

Sei die Funktion fdie durch die Definition beschriebene Funktion und []repräsentiere die durchgeführten Schritte (als Little-Endian, obwohl es keine Rolle spielen sollte) (Sie müssen diesen Prozess nicht befolgen, dies ist nur der beschriebene Prozess):

>>> f(1)
[1]
[1]
[1]
1

>>> f(5)
[5]
[0, 1, 1]
[6]
6

>>> f(63)
[63]
[0, 0, 0, 1, 0, 1, 1]
[104]
104
Addison Crump
quelle
Kann ich ein separates Programm einreichen, das die Frage schneller löst, obwohl es nicht so kurz ist? log (log (n)) + n Zeit im Gegensatz zu log (n) + n Zeit. Go go N-te Potenzmatrix.
7.
@LliwTelracs Ich kann Sie nicht davon abhalten, Ihre Lösungen zu veröffentlichen. Stellen Sie einfach sicher, dass diese Lösungsmethode so genau wie möglich auf Ihr Wissen zielt, um sicherzustellen, dass Sie immer noch auf dem richtigen Gebiet konkurrieren.
Addison Crump
Nun, ich werde es zumindest nicht tun. Schnelle Potenzierung dieser Matrix ist lächerlich wortreich
fəˈnəˈtɛk
2
@LliwTelracs Dann füge es vielleicht einfach als Nachtrag zu deinem bestehenden Beitrag hinzu.
Jonathan Allan
Ihre Herausforderung ist für diejenigen unleserlich, die keine Bilder zeigen können.
Mindwin

Antworten:

7

Javascript 117 111 Bytes

Vielen Dank an @theonlygusti für die Unterstützung beim Golfspielen mit 5 Bytes

x=>{r=0;a=[1,2,3];i=1;while(a[++i]<x)a[i+1]=a[i]+a[i-1]+a[i-2];for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}return r}

Wie es funktioniert

Zunächst generiert die Funktion alle Tribonacci-Zahlen, bis sie eine finden, die größer als die Eingabe ist

a=[1,2,3];i=1;for(;a[++i]<x;)a[i+1]=a[i]+a[i-1]+a[i-2];

Anschließend wird die Liste der Nummern in umgekehrter Reihenfolge durchsucht. Wenn eine Zahl kleiner als die Eingabe ist, addiert sie 2 ^ (Index dieser Zahl) zum Rückgabewert und reduziert die Eingabe um diese Zahl.

for(;x;i--)if(x>=a[i]){r+=1<<i;x-=a[i]}

Schließlich gibt es das Ergebnis zurück.

Probieren Sie es online

fəˈnəˈtɛk
quelle
1
Was a[++i]<xist mit der for-Bedingung, um ein Byte zu speichern?
theonlygusti
1
Außerdem können Sie ersetzen x>0mit x. Speichern Sie weitere 2 Bytes.
theonlygusti
Das ist ein ziemlich guter Algorithmus. oo
Addison Crump
7

Python 2 , 110 102 Bytes

-3 Bytes dank Rod (netter Trick für boolean Gießen imit in einen int +iso die repr `+i`works)

n=input()
x=[3,2,1]
r=''
while x[0]<n:x=[sum(x[:3])]+x
for v in x:i=n>=v;n-=v*i;r+=`+i`
print int(r,2)

Probieren Sie es online!

Jonathan Allan
quelle
1
Sie können '01'[i]mit`+i`
Rod
iist ein Boolescher Wert, kein Int. Bearbeiten - Ohhh +i, ordentlich.
Jonathan Allan
3
@ Rod Ist das ein Trick in den Tipps und Tricks von Python 2?
Addison Crump
@VoteToClose Ich glaube nicht
Rod
7

JavaScript (ES6), 97 Byte

Hier verwenden wir reduce()eine rekursive Funktion. Wir gehen davon aus, dass die Ausgabe 31-Bit ist (dies ist die größte vorzeichenlose Größe, mit der JS für bitweise Operationen ohnehin problemlos arbeiten kann).

n=>[...Array(x=31)].reduce(p=>(c=(F=k=>k<4?k:F(--k)+F(--k)+F(--k))(x--))>n?p:(n-=c,p|1<<x),0)

In Bezug auf die Leistung ist dies eindeutig nicht sehr effizient.

Für die Neugierigen:

  • Das Verhältnis zwischen der Anzahl der Anrufe zu F() für N + 1reduce() Iterationen und N-Iterationen konvergiert schnell gegen die Tribonacci-Konstante (39 1.83929). Daher kostet jedes zusätzliche Bit in der Ausgabe ungefähr doppelt so viel Zeit wie das vorherige.
  • Mit 31 Bit wird die F()Funktion gut 124 Millionen Mal aufgerufen.

Prüfung

NB: Dies kann 1 oder 2 Sekunden dauern.

Arnauld
quelle
Wow, das hängt meinem Browser hinterher, wenn ich ihn benutze. xD
Addison Crump
@VoteToClose In Bezug auf die Leistung ist dies schrecklich ineffizient. :-) Der Testcode sollte jedoch nicht zu lange zurückbleiben. Auf meiner Box erhalte ich ungefähr 600 ms in Firefox und 900 ms in Chrome. Ist es auf Ihrer Seite viel langsamer?
Arnauld
Wie 5 Sekunden. xD
Addison Crump
@VoteToClose Sollte jetzt etwas schneller sein. Die 32. Iteration war sinnlos, daher habe ich die Ausgabe auf eine vorzeichenlose 31-Bit-Ganzzahl beschränkt.
Arnauld
6

Mathematica, 78 74 Bytes

Fold[#+##&,#~NumberDecompose~Reverse@LinearRecurrence[{1,1,1},{1,2,3},#]]&

LinearRecurrence[{1,1,1},{1,2,3},#]generiert eine Liste mit der Länge der Eingabe der 1-2-3 Tribonacci-Zahlen. (Das {1,1,1}stellt die Summe der vorherigen drei Terme dar, wobei {1,2,3}es sich um die Anfangswerte handelt.) #~NumberDecompose~Findet dann den gierigsten Weg, um die Eingabe als Summe von Elementen der Liste zu schreiben (dies ist dieselbe Funktion, die einen Geldbetrag in Vielfache von zerlegen würde die verfügbaren Währungen, zum Beispiel). Endlich,Fold[#+##&,...] wandelt die sich ergebende binäre Liste in eine (Basis 10) integer.

Vorherige Einreichung:

Fold[#+##&,#~NumberDecompose~Reverse@Array[If[#<4,#,Tr[#0/@(#-Range@3)]]&,#]]&

Wie es häufig der Fall ist (wenn auch nicht oben), ist diese Golfversion bei Eingaben größer als 20 oder so sehr langsam, da sie (mit nicht optimierter Rekursion) eine Liste von Stämmen erzeugt, deren Länge die Eingabe ist; Das Ersetzen des Finales #durch eine vernünftigere Bindung Round[2Log@#+1]führt zu einer viel besseren Leistung.

Greg Martin
quelle
Was? Mathematica hat kein 123Tribonacci[]eingebautes?
Palsch
1
Nicht genau, obwohl sich herausstellt, dass die Verwendung eines eingebauten Tools ein wenig hilft.
Greg Martin
5

Haskell, 95 Bytes

(a!b)c=a:(b!c)(a+b+c)
e#(r,c)|c-e<0=(2*r,c)|1<2=(2*r+1,c-e)
f n=fst$foldr(#)(0,n)$take n$(1!2)3

Anwendungsbeispiel: f 63->104 . Probieren Sie es online! .

So funktioniert es: !Baut die 1-2-3-Tribonacci-Sequenz auf. Gegeben 1, 2und 3als Startparameter nehmen wir die ersten nElemente der Sequenz. Dann klappen wir von der rechten Funktion ab, #die das nächste Element evon subtrahiert nund das Bit in den Rückgabewert setzt, rwenn ees benötigt wird oder das Bit nicht gesetzt wird. Das Setzen des Bits verdoppelt sich rund das Hinzufügen 1, das Deaktivieren des Bits verdoppelt sich nur.

nimi
quelle
4

Jelly , 31 Bytes

S=³
3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ

Probieren Sie es online!

Ich bin mir fast sicher, dass es einen VIEL kürzeren Weg gibt, um dies in Jelly zu erreichen.

Wie?

S=³ - Link 1, compare sum to input: list
S   - sum
  ³ - 3rd command line argument which is 1st program argument.
 =  - equal?

3RUµḣ3S;µ<³Ạµ¿µŒPÇÐfṀe@ЀµḄ - Main link: n
3RU                         - range(3) upended -> [3,2,1]
   µ    µ   µ¿              - while
         <³                 - less than input (vectorises)
           Ạ                - all?
    ḣ3S;                    -     head(3), sum, and concatenate
                                  [3,2,1] -> [6,3,2,1] -> [11,6,3,2,1] -> ...
              µ             - monadic chain separation, call the result x
               ŒP           - power set of x - e.g. for [6,3,2,1] -> [[],[6],[3],[2],[1],[6,3],[6,2],[6,1],[3,2],[3,1],[2,1],[6,3,2],[6,3,1],[6,2,1],[3,2,1],[6,3,2,1]]
                  Ðf        - filter keep
                 Ç          -     last link (1) as a monad (those that sum to the input)
                    Ṁ       - maximum (e.g. an input of 63 would yield [[37,20,6],[37,20,3,2,1]], the maximum of which is [37,20,6], the one with the largest numbers used)
                         µ  - monadic chain separation (to have x as the right argument below)
                     e@Ѐ   - exists in with reversed arguments mapped over x (e.g. [37,20,6] with x = [68,37,20,11,6,3,2,1] yields [0,1,1,0,1,0,0,0])
                          Ḅ - convert from binary to integer.        
Jonathan Allan
quelle
4

Perl 6 , 93 91 Bytes

-2 Bytes dank b2gills

{my@f=1,2,3,*+*+*...*>$^n;sum @f».&{$_~~any first *.sum==$n,@f.combinations}Z*(2 X**^∞)}

Wie es funktioniert

  • Zunächst wird die 1-2-3-Tribonacci-Sequenz bis zum ersten Element generiert, das größer als die Eingabe ist:

    my @f = 1, 2, 3, *+*+* ... * > $^n;
  • Darauf aufbauend findet es die Teilmenge der Sequenz, die sich zur Eingabe addiert:

    first *.sum==$n, @f.combinations
  • Darauf aufbauend erstellt es eine Liste von Booleschen Werten, die angeben, ob jedes Element der Sequenz Teil der Summe ist:

    @f».&{$_~~any ...}
  • Und schließlich interpretiert es diese Liste der Werte True = 1, False = 0 als Basis 2 und gibt sie als Zahl (Basis 10) zurück:

    sum ... Z* (2 X** ^∞)
smls
quelle
1
Sie können es mit *>$^nund kürzen .sum==$n. Auch der Raum zwischen myund wird nicht benötigt@f
Brad Gilbert b2gills
3

JavaScript (ES6), 61 bis 60 Byte

n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)

Berechnet die 1-2-3-Tribonacci-Zahlen, bis sie die ursprüngliche Zahl erreicht haben. Wenn sich die Rekursion abwickelt, wird versucht, jede nacheinander zu subtrahieren, wobei das Ergebnis nach und nach verdoppelt wird.

Bearbeiten: 1 Byte dank @Arnauld gespeichert.

Neil
quelle
Wow! Sehr schön. Könnte n=>(g=(x,y,z)=>(n>x&&g(y,z,x+y+z)*2)+!(n<x||![n-=x]))(1,2,3)ein Byte speichern?
Arnauld
@Arnauld Ich hatte nach etwas gesucht, n<x||aber das ![]ist einfach genial.
Neil
2

Batch, 151 148 145 Bytes

@set/ar=0,n=%1
@call:c 3 2 1
@echo %r%
@exit/b
:c
@set/as=%1+%2+%3
@if %n% gtr %3 call:c %s% %*
@set/ar*=2
@if %n% geq %3 set/an-=%3,r+=1

Port meiner JavaScript-Antwort. Bearbeiten: 3 Bytes durch Übergeben meiner Unterprogrammargumente in umgekehrter Reihenfolge und weitere 3 Bytes durch Verwenden einzelner @s in jeder Zeile anstelle von gespeichert @echo off.

Neil
quelle
2

Jelly , 19 18 17 Bytes

Ḣx3+
BÇL¡2ị
²Ç€»ċ

Probieren Sie es online!

Hintergrund

Anstatt zu versuchen, eine Ganzzahl in eine 1,2,3-Tribonacci-Basis zu konvertieren, dann von binär in eine Ganzzahl, machen wir das Gegenteil: konvertieren Sie Ganzzahlen in binär, dann von einer 1,2,3-Trionacci-Basis in eine Ganzzahl und geben Sie zurück die höchste, die der Eingabe entspricht. Dies ist leicht zu bewerkstelligen.

Wir werden den Prozess für die Eingabe 63 veranschaulichen , insbesondere den Schritt, in dem 104 getestet wird. In der Binärzahl ist 104 von der höchstwertigen bis zur niedrigstwertigen Ziffer gleich

 1  1  0  1  0  0  0
37 20 11  6  3  2  1

wobei die zweite Zeile die Positionswerte dieser Ziffern darstellt.

Wir können die 1,2,3-Tribonacci-Sequenz nach rechts erweitern und dabei beobachten, dass die hinzugefügten Ziffern der gleichen rekursiven Formel entsprechen. Für drei Millionen Ziffern ergibt dies

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

Um nun den Wert der 1,2,3-Tribonacci-Basiszahl zu berechnen, können wir die rekursive Formel verwenden. Da jede Zahl die Summe der drei Zahlen rechts davon ist (in der obigen Tabelle), können wir die erste Ziffer entfernen und diese zu den ersten drei Ziffern des verbleibenden Arrays hinzufügen. Nach 7 Schritten, was der Anzahl der Binärziffern von 104 entspricht , sind nur noch drei Stellen übrig.

 1  1  0  1  0  0  0  0  0  0
37 20 11  6  3  2  1  0  1  0

    2  1  2  0  0  0  0  0  0
   20 11  6  3  2  1  0  1  0

       3  4  2  0  0  0  0  0
      11  6  3  2  1  0  1  0

          7  5  3  0  0  0  0
          6  3  2  1  0  1  0

            12 10  7  0  0  0
             3  2  1  0  1  0

               22 19 12  0  0
                2  1  0  1  0

                  41 34 22  0
                   1  0  1  0

                     75 63 41
                      0  1  0

Da nun die erste und die letzte verbleibende Ziffer beide den Positionswert 0 haben , ist das Ergebnis die mittlere Ziffer, dh 63 .

Wie es funktioniert

²Ç€»ċ   Main link. Argument: n

²       Yield n². Since 1.839² = 3.381921 > 2, the range [1, ..., n²] will contain
        the answer. Better bounds, at the cost of additional bytes are possible.
 Ç€     Map the the second helper link over [1, ..., n²].
   »    Take the maximum of n and each result.
    ċ   Count the occurrences of n.


BÇL¡2ị  Second helper link. Left argument: k. Right argument: n

B       Convert k to binary. Let's call the result A.
  L     Length; count the number of binary digits. Let's call the result l.
 Ç ¡    Apply the first helper link l times to A.
    2ị  Retrieve the second element.


Ḣ×3+    First helper link. Argument: A (array)

Ḣ       Head; pop and yield the first element of A.
 x3     Repeat it thrice.
   +    Add the result, component by component, to the beheaded A.
Dennis
quelle
2

Jelly ( Gabel ), 17 16 Bytes

ḣ3S;µ¡
3RṚdzæFṪḄ

1 Byte gespart dank @Dennis, der Golf gespielt hat, ohne es überhaupt laufen zu lassen.

Dies beruht auf einer Jelly-Gabel, bei der ich enttäuschenderweise immer noch an der Implementierung eines effizienten Frobenius-Lösungsatoms arbeite. Für diejenigen, die interessiert sind, möchte ich Mathematica Geschwindigkeit in FrobeniusSolveund zum Glück gibt es eine Erklärung für ihre entsprechen Methode in dem Artikel "Änderungen vornehmen und Umbauten finden: Balancing a Knapsack" von Daniel Lichtblau.

Erläuterung

ḣ3S;µ¡  Helper link. Input: a list
    µ   Create monadic chain
ḣ3        Take the first 3 items
  S       Sum
   ;      Prepend to the list
     ¡  Repeat it n (initial argument from main) times

3RṚdzæFṪḄ  Main link. Input: integer n
3          The constant 3
 R         Range. Makes [1, 2, 3]
  Ṛ        Reverse. Makes [3, 2, 1]
   Ç       Call the helper link on that list.
           Generates the first (n+3) 123-Tribonacci values in reverse
    ³      Get n
     æF    Frobenius solve for n using the first n 123-Tribonacci values in reverse
       Ṫ   Tail. Take the last value. The results of Frobenius solve are ordered
           where the last result uses the least
        Ḅ  Unbinary. Convert digits from base 2 to base 10
Meilen
quelle
3
Sie wissen, dass Sie tief in das Code-Golfen eintauchen, wenn Sie Gabeln mit Super-Esolangs verwenden.
Addison Crump
Würde ḣ3S;µ¡¶3RṚdzæFṪḄfunktionieren Ich habe Ihre Gabel nicht installiert und kann sie daher nicht testen.
Dennis
@Dennis Das ist die Eingabe von stdin nicht Argumenten, oder? Ich hatte Probleme mit der Verwendung von Argumenten und erkannte nur, dass es umgekehrt funktionierte.
Meilen
Nein, das sollten immer noch Argumente sein. ³verweist auf das erste Argument.
Dennis
@Dennis Nvm, es funktioniert mit Argumenten, ich jelly.pyhatte nach dem letzten Commit noch ein paar andere Dinge drin.
Meilen
1

Gleichstrom , 110 102 Bytes

?se1sa2sb3sc_1sf[laddSdlbdsalcdsb++sclf1+sfle>y]dsyx0sk[lk2lf^+skler-se]sr[Lddle!<rlf1-dsf0!>z]dszxlkp

Nun, scheint wie große Geister haben gleich denken. Anscheinend ist der Algorithmus, mit dem ich die Einschränkungen von dcumgehen wollte, zufällig genau der gleiche, der in der Antwort von @ LliwTelrac verwendet wurde. Interessant.

Probieren Sie es online!

R. Kap
quelle
1

Bash + BSD-Dienstprogramme (OS X usw.), 53 Byte

jot $[2#$1**4]|egrep -v '[2-9]|11(1|$)'|sed $[2#$1]!d

Bash + GNU-Dienstprogramme (funktioniert auch unter BSD), 59 Bytes

seq -f2o%.fp $[2#$1**2]|dc|egrep -v '11(1|$)'|sed $[2#$1]!d

Die Eingabe und Ausgabe in beiden oben genannten Fällen erfolgt binär.


Probieren Sie die GNU-Version bei TIO aus. (Das mit verknüpfte Beispiel zeigt die Eingabe von 111111 (63 in binär) und die Ausgabe von 1101000 (104 in binär).)

Ich glaube nicht, dass TIO eine BSD-Option anbietet, aber wenn Sie einen Mac zur Verfügung haben, können Sie beide ausprobieren. (Das 59-Byte-Programm ist viel schneller als das 53-Byte-Programm.)


Leider seqkann anstelle von nicht einfach in die BSD-Lösung geworfen werdenjot , da das Ausgabeformat fürseq für Ausgaben über 999999 unterschiedlich ist. (Dies beginnt ein Problem für Eingaben um 32, da 32 ^ 4> 1000000.)

Sie können jotoben mit ersetzen seq -f%.f, damit dies mit GNU-Dienstprogrammen funktioniert, aber für die gleichen 59 Bytes können Sie die oben genannte GNU-Lösung verwenden, die viel schneller ist.

Mitchell Spector
quelle