Zähle die Quadrate

18

Herausforderung

Origami (Faltpapier) ist eine kreative Kunstform. Soweit ich weiß, bevorzugt der Meister von Origami Karopapier. Beginnen wir von vorne - wandeln Sie ein rechteckiges Papier in ein quadratisches um.

Das Papier ist also in Quadrate unterteilt. Schritt für Schritt entfernen wir das größte Quadrat, das eine kürzere Kante mit der aktuellen Form teilt (siehe Bild unten). Wenn der verbleibende Teil nach einem Schritt kleiner oder gleich ist 0.001 * (area of the original paper), kann das Papier nicht weiter geteilt werden. Es ist möglich, dass endlich nichts mehr übrig bleibt.

Ihre Aufgabe ist es, zu berechnen, wie viele Quadrate während des Prozesses erstellt werden. Das Quadrat im letzten Schritt, durch das das Papier nicht mehr geteilt werden kann, wird in die Ausgabe einbezogen.

Beispiel (ein Papier mit 1.350Breite / Höhe), Ausgabe ist 10:

Slice-Beispiel

Ein- und Ausgang

Eingabe: Breiten- / Höhenverhältnis für das rechteckige Papier, eine Dezimalstelle (oder eine Ganzzahl ohne Punkt) von 1.002bis 1.999mit einem minimalen Schritt von 0.001. Sie können auch jedes andere vernünftige Format verwenden, das das Verhältnis beschreibt. Erwähne es einfach in deiner Antwort.

Ausgabe: Quadratzahl, eine ganze Zahl.

Beispiel I / O

Ein Zuordnungsformat wird verwendet, um die Seite aufgeräumt zu halten, während Ihr Code weder eine Listeneingabe unterstützen noch eine Zuordnungsfunktion sein muss.

1.002 => 251
1.003 => 223
1.004 => 189
1.005 => 161
1.006 => 140
1.007 => 124
1.008 => 111
1.009 => 100

Liste aller Antworten

Dank @LuisMendo sehen Sie hier die Antwortgrafik.

Graph

Bemerkungen

  • Dies ist ein Code-Golf, also gewinnt der kürzeste Code
  • Achten Sie auf Standardlücken
  • Sie können frei entscheiden, wie Sie mit Ein- und Ausgängen umgehen möchten, sie sollten jedoch den Standardbeschränkungen folgen.

Apropos...

  • Kommentar, wenn Sie etwas Unklares über die Herausforderung haben
  • Persönlich würde ich vorschlagen, dass Ihre Antwort eine Erklärung enthält, wenn Sie eine Golfsprache verwenden
  • Dank @ GregMartin, lesen Sie seine Antwort für eine gute mathematische Erklärung für die Herausforderung.

Beispielcode

Hier ist eine ungolfed Version von C ++ Code:

#include <iostream>
#include <utility>

int f (double m)
{
    double n = 1, k = 0.001;
    int cnt = 0;
    k *= m;                       // the target minimum size
    while(m*n >= k)
    {
        m -= n;                   // extract a square
        if(n > m)
            std::swap(n, m);      // keep m > n
        ++ cnt;
    }
    return cnt;
}

int main()
{
    double p;
    std::cin >> p;
    std::cout << f(p);
    return 0;
}

Alle im Beispielcode enthaltenen Berechnungen benötigen eine Genauigkeit von 6 Dezimalstellen, die in behandelt wird float.

Keyu Gan
quelle
Können zwei Zahlen, die das Verhältnis bilden, als Eingaben verwendet werden?
Luis Mendo
@ LuisMendo ja, wie du möchtest.
Keyu Gan
2
Ordentliche Herausforderung!
Fehler
5
Die Liste der Antworten erzeugt eine schöne Grafik
Luis Mendo
1
@KeyuGan Natürlich, mach weiter! Lassen Sie mich wissen, wenn Sie eine Version mit einem anderen Format benötigen
Luis Mendo

Antworten:

2

MATL , 19 Bytes

`SZ}y-htG/p1e-3>}x@

Die Eingabe ist ein Array, in dem die beiden Zahlen das ursprüngliche Verhältnis definieren, z [1, 1.009]. (Es ist nicht erforderlich, dass die Nummern sortiert sind oder dass eine davon 1 ist.)

Probieren Sie es online!

Erläuterung

`        % Do...while loop
  S      %   Sort array. Takes 1×2 array as input (implicit) the first time
  Z}     %   Split array into its 2 elements: first the minimum m, then the maximum M
  y      %   Duplicate m onto the top of the stack. The stack now contains m, M, m
  -      %   Subtract. The stack now contains m, M-m
  h      %   Concatenate into [m, M-m]. This is the remaining piece of paper
  t      %   Duplicate
  G/     %   Divide by input, element-wise
  p      %   Product of array. Gives ratio of current piece's area to initial area
  1e-3>  %   True if this ratio exceeds 1e-3. In that case the loop continues
}        % Finally (execute after last iteration, but still within the loop)
  x      %   Delete last piece of paper
  @      %   Push current loop counter. This is the result
         % End (implicit)
         % Display (implicit)
Luis Mendo
quelle
6

Haskell , 71 70 65 63 62 61 58 56 Bytes

Vielen Dank an @xnor für einige geniale Verbesserungen!

(n#m)e|e>n*m*1e3=0|n<m=m#n$e|d<-n-m=(d#m)e+1
n!m=n#m$n*m

Probieren Sie es online!

fehlerhaft
quelle
Ich denke, das kann m==nam Ende sein, 1>0weil es die einzige verbleibende Möglichkeit ist. Oder vielleicht könnten die Fälle neu angeordnet werden, um hier eine Bindung zu ermöglichen.
9.
Wird der Gleichstellungsfall tatsächlich benötigt? Wenn auf n>merweitert n>=mund der erste Scheck geschrieben e>m*n*1000wird, sollte dies 1für Gleichheit sorgen.
9.
@ xnor Gute Idee, danke!
Fehler
1
56:(n#m)e|e>n*m*1e3=0|n<m=m#n$e|d<-n-m=(d#m)e+1;n!m=n#m$n*m
xnor
Wow, mit dem d<-n-mwie es otherwiseist wirklich ordentlich !!!
Fehler
4

JavaScript (ES6), 59-58 Byte

f=(m,n=!(k=m/1e3,c=0))=>m*n<k?c:(c++,m-=n)<n?f(n,m):f(m,n)

Prüfung

Arnauld
quelle
4

Mathematica, nicht konkurrierend (21 Bytes)

Diese Antwort ist nicht konkurrierend, da sie die tatsächlich gestellte Frage nicht beantwortet! Aber es beantwortet eine Variante der Frage und liefert eine Entschuldigung, um einige interessante Mathematik aufzuzeigen.

Tr@*ContinuedFraction

Symbolische Funktion, die eine positive rationale Zahl als Eingabe verwendet (deren Zähler und Nenner die Abmessungen des Originalpapiers darstellen) und eine positive ganze Zahl zurückgibt. Zum Beispiel Tr@*ContinuedFraction[1350/1000]kehrt zurück 10. ( ContinuedFractionWirkt aufgrund von Genauigkeitsproblemen anders auf Gleitkommazahlen, weshalb in diesem Kontext eine rationale Zahl als Eingabe benötigt wird.)

Eine interessante Interpretation des in dem Problem beschriebenen geometrischen Verfahrens (wiederholtes Abschneiden von Quadraten von einem Rechteck) ist, dass es sich um eine Implementierung des euklidischen Algorithmus handelt, um die größten gemeinsamen Teiler zu finden! Betrachten Sie das Beispiel in der Frage selbst mit Verhältnis1.35, die durch ein Stück Papier mit den Maßen (1350, 1000) modelliert werden könnte. Jedes Mal, wenn ein Quadrat abgeschnitten wird, wird die kleinere Zahl von der größeren Zahl abgezogen. Die resultierenden Rechtecke in diesem Beispiel haben also die Dimensionen (350, 1000), dann (350, 650), dann (350, 300), dann (50, 300), dann (50, 250) und (50, 200) und (50, 150) und (50, 100) und (50, 650). 50) und auch (50,0), sobald wir das letzte Quadrat von sich wegnehmen. Genau so funktioniert der euklidische Algorithmus (Modulo der Differenz zwischen Division und wiederholter Subtraktion), und tatsächlich sehen wir, dass 50 tatsächlich die GCD von 1350 und 1000 ist.

Typischerweise verfolgt man im euklidischen Algorithmus diese Zwischendimensionen und verwirft die Anzahl der Subtraktionen. Man kann jedoch abwechselnd aufzeichnen, wie oft wir eine Zahl von der anderen subtrahiert haben, bevor die Differenz zu klein wird, und wir müssen umschalten, was wir subtrahieren. Diese Aufzeichnungsmethode ist genau der fortgesetzte Bruchteil einer rationalen Zahl. (Fortgesetzte Brüche von irrationalen Zahlen, die niemals enden, sind auch super cool, aber hier nicht relevant.) Zum Beispiel haben wir im Beispiel 1350/1000 1000- 1mal, dann 350- 2mal, dann 300- 1mal, dann 50- 6mal subtrahiert ; daher ist der fortgesetzte Bruchteil von 1350/1000 {1,2,1,6}. Mathematisch haben wir 1350/1000 umgeschrieben als 1+ 1 / ( 2+ 1 / ( 1+ 1 /6)), die Sie überprüfen können.

Wenn Sie für dieses Problem nicht anhalten, wenn die Quadrate kleiner als ein bestimmter Schwellenwert werden, sondern einfach alle endlich vielen Quadrate zählen, bevor sie anhalten, entspricht die Gesamtzahl der Quadrate der Gesamtzahl der Subtraktionen die Summe aller ganzen Zahlen im fortgesetzten Bruch - und genau das Tr@*ContinuedFractionberechnet die Zusammensetzung der Funktionen ! (Für das gegebene Beispiel 1.35 erhält es die Antwort, die das OP wünscht, weil das letzte Quadrat groß genug ist, dass alle Quadrate gezählt wurden. Aber Tr@*ContinuedFraction[1001/1000]zum Beispiel ergibt es 1001, weil es das eine große Quadrat und alle 1000 der kleinen 1x1000 Quadrate zählt .)

Greg Martin
quelle
1
Das ist zwar interessant, aber das nicht konkurrierende Label ist Sprachen vorbehalten, die neuer sind als die Herausforderung . Unabhängig davon müssen alle Antworten die Herausforderung lösen. Daher sollte diese Antwort wirklich gelöscht werden. Wären Sie in der Lage, aus der fortgesetzten Fraktionsliste zu rekonstruieren, wo sie abgeschnitten werden müssen, damit dies zu einer ebenso interessanten wie gültigen Lösung wird?
Martin Ender
1
Beim Schreiben dieser Antwort hatte ich ein starkes Kratzen, aber ich stimme zu, dass dies eine nach Community-Standards löschenswerte Antwort ist. (Vielen Dank für Ihr sanftes und dennoch genaues Feedback!) Wenn TPTB die Löschung um 24 Stunden verzögern möchte, kann ich den Ansatz möglicherweise vervollständigen, um die richtige Antwort zu erhalten. Wenn nicht, löschen Sie weg und ohne harte Gefühle.
Greg Martin
3

Mathematica, 64 53 Bytes

({t=1,#}//.{a_,b_}/;1000a*b>#:>Sort@{++t;a,b-a};t-1)&

Eine Imperativlösung (C-Stil) hat genau die gleiche Länge:

(For[t=a=1;b=#,1000a*b>#,If[a>b,a-=b,b-=a];++t];t-1)&
Martin Ender
quelle
2

C (GCC / Clang), 61 59 Bytes

c,k;f(m,n){for(k=m*n;m*n/k;m>n?(m-=n):(n-=m))++c;return c;}

Die Eingabe erfolgt über zwei Ganzzahlen (Breite und Höhe) ohne Punkt, z f(1999,1000).

Ich hoffe, jemand konnte ein Byte speichern, indem er C in den 58-Byte-Club drückte. ;)

Keyu Gan
quelle
Schlagen Sie vor, die runden Klammern zu entfernenm-=n
ceilingcat
1

C 59 Bytes

s,a,n=1e3;C(m){for(a=m;m*n>a;s++)m>n?m-=n:(n-=m);return s;}

Probieren Sie es online

Die Eingabe ist eine Ganzzahl, die das Verhältnis von Breite zu Höhe in Tausendstel angibt (z. B. 1002 für 1.002: 1).

Ungolfed-Version

int C(int m)
{
    int n = 1000;
    int a = m;
    int s = 0;

    while (m * n > a)
    {
        if (m > n)
            m -= n;
        else
            n -= m;

        s++;
    }

    return s;
}
bmann
quelle