Unterteilen des Gitters in Dreiecke


18

Tor

Ziel dieser Herausforderung ist es, eine Funktion zu erstellen, mit nder die Anzahl der Möglichkeiten berechnet wird, das n X 1Gitter in Dreiecke zu unterteilen, bei denen sich alle Eckpunkte der Dreiecke auf Gitterpunkten befinden.

Beispiel

Zum Beispiel gibt es 14 Möglichkeiten, das 2 x 1-Gitter zu unterteilen, also f(2) = 14über die folgenden Partitionen, bei Partitionen von 2 x 1 denen die Partitionen 2, 2, 2, 2, 4 bzw. 2 unterschiedliche Ausrichtungen haben.

Wertung

Das ist , also gewinnt der kürzeste Code.


10
Einige zusätzliche Testfälle wären von Vorteil, damit wir überprüfen können, ob unsere Eingaben korrekt sind.
AdmBorkBork

8
Möglicherweise möchten Sie nicht degenerierte Dreiecke angeben .
Arnauld

1
Ich habe die OEIS-Sequenz A051708 bearbeitet , um diese Interpretation widerzuspiegeln.
Peter Kagey

Antworten:


2

05AB1E , 13 Bytes

·LÉœÙεÅγo;P}O

Port of @Bubbler 's Jelly Antwort .

Sehr langsam aufgrund der eingebauten Permutationen.

Probieren Sie es online aus oder überprüfen Sie die ersten vier Eingaben .

Erläuterung:

·                # Double the (implicit) input
 L               # Create a list in the range [1, doubled_input]
  É              # Check for each if they're odd (1 if truthy, 0 is falsey)
                 # We now have a list of n 0s and n 1s (n being the input)
   œ             # Get all permutations of that list
    Ù            # Only leave the unique permutations
     ε     }     # Map each permutation to:
      Åγ         #  Run-length encode the current value (short for `γ€g`)
        o        #  Take 2 to the power for each
         ;       #  Halve each
          P      #  Take the product of the mapped permutation
            O    # Sum all mapped values together (and output implicitly)

19

Haskell , 60 55 54 52 Bytes

Nach dem Zeichnen und Programmieren vieler Beispiele ist mir aufgefallen, dass dies dasselbe ist wie das Problem der Türme:

Auf einem (n+1)×(n+1) Schachbrett, wie viele Möglichkeiten gibt es für eine Saatkrähe aus zu gehen (0,0) bis (n,n) nur durch Bewegen rechts +(1,0) oder bis +(0,1) ?

Grundsätzlich haben Sie die obere und die untere Linie des 1×n Gitters. Jetzt müssen Sie die nicht horizontale Linie ausfüllen. Jedes Dreieck muss zwei nicht horizontale Linien haben. Ob eine seiner Seiten Teil der oberen oder unteren Linie ist, hängt von der Richtung und Länge ab, in die Sie beim Turmproblem gehen würden. Dies ist OEIS A051708 . Betrachten Sie zur Veranschaulichung dieser Entsprechung die folgenden Beispiele. Hier entspricht die obere Zeile Aufwärtsbewegungen, während die untere Zeile Rechtsbewegungen entspricht.

Vielen Dank an @PeterTaylor für -6 Bytes und @PostLeftGarfHunter für -2 Bytes!

b 0=1
b 1=2
b n=div((10*n-6)*b(n-1)-9*(n-2)*b(n-2))n

Probieren Sie es online!


Ich habe die OEIS-Sequenz gefunden, indem ich mit den ersten Werten gesucht habe. Gute Erklärung, warum es passt. Möchten Sie es bearbeiten, um einen Kommentar zu dieser alternativen kombinatorischen Interpretation hinzuzufügen? Wenn nicht, könnte ich.
Peter Taylor

Übrigens müssen Sie die Indizierung anpassen, da die richtige Antwort hier ist A051708(n+1). Also habe ich die erste richtige Antwort gepostet :-P
Peter Taylor

Ich nehme an, der Turm bewegt die Karte in Dreiecke, indem er Dreiecke mit oberen und unteren Rändern entsprechend nach oben oder rechts bewegt.
Neil

@PeterTaylor Verdammt, danke für den Hinweis auf meinen Fehler :)
Fehler

5
@Neil Ich habe eine grafische Erklärung hinzugefügt.
Fehler

8

Haskell , 42 Bytes

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

Probieren Sie es online!

Eine ziemlich direkte Implementierung, die über 2 Variablen rekursiv ist.

So können wir diese Lösung erhalten. Beginnen Sie mit dem Code, der eine direkte rekursive Formel implementiert:

54 Bytes

0%0=1
a%b=sum$map(a%)[0..b-1]++map(b%)[0..a-1]
f n=n%n

Probieren Sie es online!

Mit flawr der Saatkrähe bewegen Interpretation , a%bist die Anzahl der Pfade, die die Saatkrähe bekommen von (a,b)zu (0,0)verwenden nur die Abnahme bewegt sich eine Koordinate. Der erste Zug nimmt entweder ab aoder ab b, der andere bleibt gleich, daher die rekursive Formel.

49 Bytes

a?b=sum$map(a%)[0..b-1]
0%0=1
a%b=a?b+b?a
f n=n%n

Probieren Sie es online!

Wir können die Wiederholung vermeiden, map(a%)[0..b-1]++map(b%)[0..a-1]indem wir feststellen, dass die beiden Hälften gleich aund bvertauscht sind. Der Hilfsaufruf a?bzählt die Pfade, auf denen der erste Zug abnimmt a, und somit auch die Pfade, auf b?adenen der erste Zug abnimmt b. Diese sind im Allgemeinen unterschiedlich und tragen dazu bei a%b.

Die Summation in a?bkann auch als Listenverständnis geschrieben werden a?b=sum[a%i|i<-[0..b-1]].

42 Bytes

0?0=1
a?b=sum[a?i+i?a|i<-[0..b-1]]
f n=n?n

Probieren Sie es online!

Zum Schluss werden wir %die Rekursion los und schreiben sie einfach ?durch Ersetzen a%idurch a?i+i?ain den rekursiven Aufruf.

Der neue Basisfall führt dazu ?, dass die Ausgaben doppelt so hoch sind wie ?in der 49-Byte-Version, da dies bei 0?0=1hätte sein müssen 0%0=0?0+0?0=2. Auf diese Weise können Sie define verwenden, f n=n?nohne die Halbierung, die wir sonst benötigen würden.


Ihre 49-Byte-Lösung verwendet dieselbe Rekursion wie meine Antwort, aber ich habe die 42-Byte-Lösung noch nicht herausgefunden. Eine Erklärung wäre nett.
Peter Taylor

Ich glaube, ich habe in einem meiner früheren Programme den gleichen Ansatz gewählt: Die Idee ist, alle Partitionen zu generieren (oder zu zählen), indem die nicht horizontalen Linien von rechts nach links generiert werden. Sie beginnen mit der vertikalen Linie. Dann können Sie wiederkehren: Nehmen Sie einen der Endknoten der vorherigen Linie und verbinden Sie ihn mit einem Knoten in der gegenüberliegenden horizontalen Linie, der weiter links von allen vorherigen Knoten in dieser Linie liegt.
Fehler

Der Operator a%bzählt die Anzahl der Partitionen anhand der Knoten 0,1,...,ain der oberen Zeile und der Knoten 0,1,..,bin der unteren Zeile. Der Operator a?bzählt die Anzahl der Möglichkeiten, wie Sie vom oberen Knoten aus eine neue Zeile hinzufügen können, awenn der untere Knoten bbereits verwendet wird. (Sie können eine Verbindung azu allen Knoten herstellen [0,1,...,b-1], müssen dann jedoch für jeden Knoten eine neue Verbindung herstellen.)
Fehler

@flawr, das ist die 49-Byte-Datei, die ich verstehe. Es ist das ?von dem 42-Byte, das ich nicht habe, und was besonders merkwürdig ist, dass es nicht symmetrisch ist.
Peter Taylor

@ PeterTaylor Sorry für die Verwirrung, ich habe die beiden Lösungen irgendwie vertauscht. Ich denke, wir können die beiden Lösungen recht einfach ineinander überführen: Im ersten Schritt können wir sie durch map...ein Listenverständnis ersetzen , im zweiten Schritt fügen wir einfach die Definition von %:a?b=sum$map(a%)[0..b-1], a%b=a?b+b?a a?b=sum[a%i|i<-[0..b-1]], a%b=a?b+b?a a?b=sum[a?i+i?a|i<-[0..b-1]]
Fehler

7

CJam (24 Bytes)

{2,*e!{e`0f=:(1b2\#}%1b}

Online-Demo

Dies verwendet den Bubbler-Ansatz der Summierung über Permutationen von n0s und n1s.

Präparation

{         e# Define a block
  2,*     e#   Given input n, create an array of n 0s and n 1s
  e!      e#   Generate all permutations of that array
  {       e#   Map:
    e`    e#     Run-length encode
    0f=:( e#     Extract just the lengths and decrement them
    1b    e#     Sum
    2\#   e#     Raise 2 to the power of that sum
  }%
  1b      e#  Sum the mapped values
}

Alternativer Ansatz (28 Byte)

{_1aa{_2$,f{j}@@,f{j}+1b}2j}

Online-Demo

Präparation

Die Dreiecke haben alle eine horizontale Kante und zwei Kanten, die die horizontalen Linien verbinden. Beschriften Sie die nicht horizontalen Kanten mit einem Tupel der beiden x-Koordinaten und sortieren Sie sie lexikografisch. Dann ist die erste Kante (0,0)die letzte Kante (n,n)und zwei aufeinanderfolgende Kanten unterscheiden sich in genau einer der beiden Positionen. Dies führt zu einer einfachen Rekursion, die ich mit dem memoised-Rekursionsoperator implementiert habe j:

{            e# Define a block
  _          e#   Duplicate the argument to get n n
  1aa        e#   Base case for recursion: 0 0 => 1
  {          e#   Recursive body taking args a b
    _2$,f{j} e#     Recurse on 0 b up to a-1 b
    @@,f{j}  e#     Recurse on a 0 up to a b-1
    +1b      e#     Combine and sum
  }2j        e#   Memoised recursion with 2 args
}

Hinweis

Dies ist nicht das erste Mal, dass ich fjin CJam unterstützt werden möchte. Hier würde es auch die Punktzahl auf 24 Bytes senken. Vielleicht sollte ich versuchen, einen Patch zu schreiben ...


Yay, ich habe dich um 10 Sekunden geschlagen, ich glaube nicht, dass ich jemals so nah dran war :)
Fehler

@flawr, ich habe darüber nachgedacht, etwas zu posten, bevor ich eine Sektion geschrieben habe, aber ich dachte, ich hätte Zeit, sie schnell auszuschalten. Dann sah ich "Neue Antwort", so dass ich meine teilweise geschriebene Zerlegung löschte, veröffentlichte und bearbeitete.
Peter Taylor

1
Danke für -5 Bytes übrigens: D
Fehler

4

Jelly , 15 bis 14 Bytes

Ø.xŒ!QŒɠ€’§2*S

Probieren Sie es online!

-1 Byte basierend auf Peter Taylors Kommentar.

Verwendet die Abbildung von flawr direkt anstelle der resultierenden Formel.

Wie es funktioniert

Ø.xŒ!QŒɠ€’§2*S    Main link (monad). Input: positive integer N.
Ø.x               Make an array containing N zeros and ones
   Œ!Q            All unique permutations
      Œɠ€         Run-length encode on each permutation
         ’§       Decrement and sum each
           2*S    Raise to power of 2 and sum

Nehmen Sie jede mögliche Route in einem quadratischen Raster. Die Anzahl der Möglichkeiten, L-Einheiten als Turm in eine Richtung zu bewegen, ist 2**(L-1). Wenden Sie dies auf jede Route an und addieren Sie die Anzahl der Wege, um jede Route zu durchlaufen.


Netter Ansatz. Als ich es nach CJam portierte, war es kürzer, um die Längen zu dekrementieren, zu summieren und dann 2 auf die Summe zu erhöhen. anstatt 2 auf die Länge zu erhöhen, zu halbieren und dann zu multiplizieren. Ich weiß nicht, ob es Ihnen ein Byte ersparen könnte.
Peter Taylor

3

Holzkohle , 44 31 Bytes

durchgestrichen 44 ist immer noch regulär 44

F⊕θ«≔⟦⟧ηF⊕θ⊞ηΣ∨⁺ηEυ§λκ¹⊞υη»I⊟⊟υ

Probieren Sie es online! Erläuterung: Berechnet die Anzahl der Möglichkeiten, ein Trapez mit entgegengesetzten Seitenlängen m,nin Dreiecke zu unterteilen, die alle auf ganzzahligen Offsets liegen. Dies ist einfach ein allgemeiner Fall des nin der Frage genannten Größenrechtecks . Die Anzahl der Partitionen wird rekursiv als Summe der Anzahl der Partitionen für alle Seiten m,0..n-1und angegeben n,0..m-1. Dies entspricht dem verallgemeinerten Problem der Türme , OEIS A035002 . Der Code berechnet einfach die Anzahl der Partitionen, die von 0,0bis zu n,nden zuvor berechneten Werten arbeiten.

F⊕θ«

Schleife über die Reihen 0..n.

≔⟦⟧η

Beginnen Sie mit einer leeren Zeile.

F⊕θ

Schleife über die Spalten in der Reihe 0..n.

⊞ηΣ∨⁺ηEυ§λκ¹

Nehmen Sie die bisherige Zeile und die Werte in den vorherigen Zeilen in der aktuellen Spalte und addieren Sie die Gesamtsumme zur aktuellen Zeile. Wenn es jedoch überhaupt keine Werte gibt, ersetzen Sie sie1 die Summe durch.

⊞υη»

Fügen Sie die fertige Zeile zur Liste der bisherigen Zeilen hinzu.

I⊟⊟υ

Den berechneten Endwert ausgeben.




Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.