Flavour-Text
Die stapelbasierte esolang- Unterlast weist einige interessante Bindungen zur funktionalen Programmierung auf. Eine davon ist die Behandlung des numerischen Datentyps - wie beim Lambda-Kalkül stellen Sie die natürliche Zahl N durch eine Funktion dar, die eine Aktion N-mal ausführt.
Zur Vereinfachung betrachten wir nur die folgende Untermenge von Unterlastbefehlen:
:
- Dieser Befehl dupliziert das oberste Element auf dem Stapel.*
- Dieser Befehl verknüpft die beiden obersten Elemente auf dem Stapel zu einem einzelnen Element.
Wir definieren eine Unterlastungszahl N als eine Zeichenfolge von :
und *
die, wenn sie ausgeführt wird, das oberste Element auf dem Stapel verbraucht und N Kopien dieses Elements erzeugt, die miteinander verkettet sind. Einige Beispiele:
- Es gibt keine Unterlastnummern 0, -1, 1/2, π.
- Die leere Zeichenfolge
hat die Unterlastnummer 1, da der Stapel unberührt bleibt.
:*
ist die Unterlastzahl 2, da sie das oberste Element dupliziert und diese beiden Kopien dann zu einem einzigen Element zusammenfügt:(A):*
=(A)(A)*
=(AA)
.::**
ist die Unterlastzahl 3:(A)::**
=(A)(A):**
=(A)(AA)*
=(AAA)
.:::***
ist die Unterlastzahl 4.:*:*
ist auch die Unterlastzahl 4:(A):*:*
=(AA):*
=(AA)(AA)*
=(AAAA)
.
Im Allgemeinen werden Sie feststellen, dass, wenn M
und N
die Unterlastzahlen M und N sind, dann :N*
die Zahl N + 1 ist und MN
die Zahl M × N ist.
Die Herausforderung
Ihre Aufgabe ist es, das kürzeste Programm (Eingabe über STDIN) oder die kürzeste Funktion (Eingabe über Argument) zu schreiben, die die kürzeste Darstellung der Unterlastzahl für ihre Eingabe als Zeichenfolge erzeugt. Das heißt, wenn die Eingabe eine positive natürliche Zahl N> 1 ist, müssen Sie eine Unterlastzahl N erzeugen, deren Länge in Zeichen kleiner oder gleich der jeder anderen Unterlastzahl N ist.
Beispiele für Ein- und Ausgänge: ("Input - OUTPUT
.")
- 1 -
.
- 2 -
:*
. - 5 -
::*:**
(2 × 2 + 1). - 7 -
::*::***
(2 × 3 + 1) oder:::**:**
(3 × 2 + 1). - 33 -
::*:*:*:*:**
(2 × 2 × 2 × 2 × 2 + 1). - 49 -
::*:*:*:*::***
(16 × 3 + 1, Länge 14), aber nicht::*::***::*::***
(7 × 7, Länge 16).
Wenn es sich bei der Eingabe nicht um eine positive natürliche Zahl handelt, können Sie einen Fehler zurückgeben, undefiniertes Verhalten erzeugen oder die Eingabe sogar nicht beenden. Wir freuen uns über eine Erläuterung der Methode, mit der Sie die Antwort gefunden haben.
Es gelten die üblichen Lückenbeschränkungen: Keine zusätzlichen Eingaben, keine Webanfragen, Ausgabe- / Rückgabewerte müssen genau die Antwort sein und kein unendlicher Zufallsstrom von :
und *
usw.
x
dort,2*A117498(x)
wo A117498 die optimale Kombination von Binär- und Faktormethoden zum Auffinden einer Additionskette ergibt.Antworten:
GolfScript (
61 60 55 5453 Zeichen)Dies ist weniger knifflig als meine frühere Version und verfolgt einen etwas anderen Ansatz, aber es ist immer noch rohe Gewalt. Wir wissen, dass dies
':'X*'*'X*+
eine in Frage kommende Lösung ist. Wenn wir also alle bis zu dieser Länge gut ausbalancierten Zeichenfolgen erzeugen und die kürzeste auswählen, die zum richtigen Ergebnis führt, können wir sicher sein, eine zu finden.Vielen Dank an Howard, von dessen Lösung ich ein paar 1-Zeichen-Tweaks gestohlen habe.
quelle
.&
direkt nach der inneren Schleife (dh zwischen~}%
und}*
.GolfScript (
5453 Zeichen)Dies ist ein Ansatz, der im Geiste von Howard (Erstellen von Zeichenfolgen, die den richtigen Wert ergeben, und Auswählen der kürzesten statt der rohen Kraft durch Kandidatenzeichenfolgen, um diejenigen zu finden, die den richtigen Wert ergeben), der sich jedoch meiner Meinung nach ausreichend unterscheidet es gehört in eine separate antwort.
Online-Demo nicht verfügbar, da eine fehlerhafte Version des Interpreters ausgeführt wird.
quelle
3+
mit)
(Ausnutzung der Tatsache , dass[]0=
Blätter nichts auf dem Stapel) , wenn es nicht so ist ,[]2>
führt zu einem Fehler.[]2>
ergibt sich[]
ohne Fehler.'1'
.((=
stattdessen reparieren können-1=
.Python 2.7 -
878492Erläuterung:
Dies ist eine ziemlich einfache Lösung. Es testet rekursiv alle möglichen Darstellungen von n als Produkt aus zwei Zahlen oder als
:(n-1)*
und findet dann die Lösung mit der minimalen Länge. range (2, n) ist notwendig, damit die Rekursion eine begrenzte Tiefe hat und n <2 den Basisfall ergibt.Anmerkungen:
i und n / i sind die beiden Faktoren von n. Der ... und ... oder ... Ersatz für ... wenn ... sonst ... nicht funktioniert, weil '' als falsch ausgewertet wird. min von Saiten ergibt eine der kürzesten Saiten. Python 2.7 speichert 1 Zeichen mit / anstelle von //.
Bearbeiten: Der Basisfall wurde in den hinteren Bereich des Ausdrucks verschoben, sodass ich ... und ... oder ... verwenden und ein paar Leerzeichen rasieren kann.
Testfälle:
quelle
key=len
. Es gibt die lexikographisch früheste Zeichenfolge. ( Beispiel ). Da'*' < ':'
dies bedeutet, dass Sie eine Tendenz zu Lösungen mit Zweierpotenzen haben, aber sind sie immer die kürzesten?u(33)
, bei dem eine lexikografische Sortierung die 14-::**::*::*:***
::*:*:*:*:**
GolfScript,
635856 ZeichenDer Code wird in STDIN eingegeben und gibt das Ergebnis aus.
Beispiele:
Sie können Ihre eigenen Fälle online testen .
quelle
:x(=
Stück weitermachen. +1 für die Ausführung von 49 in angemessener Zeit.x,2>{x\%!},
alle wahren Teiler von anx
und{.v=x@/v=+}/
verkettet dann die Lösungen fürd
undx/d
für alle Teilerd
.{,}$
sortiert sie nach Länge und0=
nimmt die kürzeste davon (plus den Anfangsfall:(x-1)*
).Brachylog 2 , 30 (möglicherweise 26) Bytes, Herausforderung nach den Sprachdaten
Hier ist eine Funktion, die mit der aktuellen Brachylog 2-Implementierung funktioniert (und eine Liste von Zeichencodes zurückgibt, da die aktuelle Implementierung einige Probleme mit der Zeichenfolgenbehandlung hat):
Probieren Sie es online!
Die Sprache ist noch sehr neu. Hier ist eine 26-Byte- Version des Programms, die gemäß der Spezifikation funktionieren sollte, jedoch einige nicht implementierte Funktionen verwendet und daher noch nicht gültig ist, aber möglicherweise in Zukunft verfügbar sein wird (es ist auch noch weniger effizient):
Erläuterung
Die Grundidee ist ziemlich einfach: Wir wechseln zwischen der Zerlegung der Zahl in (1 oder mehr) Faktoren (nicht unbedingt Primfaktoren, aber Faktoren von 1 sind nicht zulässig) und dem Ausdrücken jeder dieser Faktoren als 1 + (eine Darstellung, die aus einem Rekursiv erhalten wird) Anruf). Dies ist garantiert, um alle möglichen Unterlastdarstellungen der Zahl zu durchsuchen (wir können eine Multiplikationsstufe "zweimal in Folge" anwenden, indem wir mehr als 2 Zahlen miteinander multiplizieren, und eine Inkrementierungsstufe zweimal in Folge, indem wir sie durch eine Multiplikationsstufe trennen, die multipliziert zusammen nur eine Nummer). Wir brauchen keinen expliziten Basisfall, da die Zerlegung von 1 in Primfaktoren eine leere Liste ergibt und wir sie daher mit einer Multiplikationsstufe konstruieren, die Nullzahlen miteinander multipliziert.
Das Programm ist ziemlich ineffizient, vor allem, weil der von mir gegebene Hinweis auf die Bewertungsreihenfolge (Generieren der kürzesten bis längsten Antworten in Bezug auf die Größe der endgültigen Ausgabe), während der "kürzeste" Teil der Frage gelöst wird, in Bezug auf nicht so großartig ist das Programm tatsächlich schnell fertig zu stellen (ein viel nützlicherer Hinweis wäre, "in jeder rekursiven Phase nur die kürzeste Antwort zu generieren", aber das braucht mehr Bytes ...). Darüber hinaus
ḋp~c×ᵐ
können mehrere multiplikative Partitionen generiert werden, wodurch das Programm eine Menge redundanter Arbeit leistet.quelle
J - 81 Zeichen
Für die Nachwelt war dies das Beste, was ich in J tun konnte.
Wir erstellen eine Liste der Ergebnisse, beginnend mit zwei leeren Zeichenfolgen (das ist das
,~
unda:
), die 0 (nie verwendet) und 1 darstellen, und iterieren dann ein Verb darüber (schleichende Verwendung von Hooks, Zügen und&
), das an die kürzeste Darstellung der nächsten Zahl angehängt wird.Das tatsächliche Verb, das wir iterieren, verwendet die Länge der Liste als Indikator für die Anzahl, mit der wir arbeiten. Zuerst zerlegen wir diese Zahl in Faktorenpaare (
#(#~]-:"1<.)@(],.%)2}.i.@#
) und rufen jedes Paar durch Ziehen aus dem Array ({~
) ab. Wir wandeln jedes dieser Paare (es könnte 0 von ihnen geben, wenn die Zahl eine Primzahl ist) in einzelne Strings (<@;"1
) um.Dann hängen wir an diese Liste den Eintrag für das vorherige Ergebnis in Klammern von
:
und*
an und sortieren diese Liste nach Länge ((/:#&>)
). Schließlich nehmen wir das erste Ergebnis aus dieser Liste (0{
) und hängen es an das Ende des Basisarrays ([,
) an. Wenn die Schleife iteriert ist, haben wir eine Liste mit einer Länge von 2 mehr als die Eingabe, beginnend mit 0. Wir müssen also den vorletzten String (_2{::
) zurückgeben.quelle
Jelly , 33 Bytes, Sprachnachstellung
Probieren Sie es online!
Eine einfache Brute-Force-Lösung.
Erläuterung
Hauptprogramm
Das Hauptprogramm verwendet die Hilfsfunktion, um alle möglichen Arten der Werterzeugung durch Multiplikation aufzulisten. Anschließend versucht es, den Wert durch Addition zu erzeugen, und gibt die kürzeste Möglichkeit zurück. Es behandelt auch den Basisfall (eine Eingabe von
1
).Hilfsfunktion
Die Hilfsfunktion versucht alle möglichen Methoden, um die Eingabe als Multiplikation von zwei Zahlen auszudrücken, und ruft das Hauptprogramm gegenseitig rekursiv auf, um die kürzesten Darstellungen zu erhalten.
quelle
GNU Prolog, 96 Bytes
Die erste Zeile ist eine Grammatik, die die Unterlastauswertung implementiert und in umgekehrter Richtung funktioniert (tatsächlich funktioniert sie aufgrund der
A#<B
Einschränkung nicht ganz in Vorwärtsrichtung ; ändern Sie dies inA#<N
für ein langsameres Programm, das in beide Richtungen funktioniert). Die zweite Zeile definiert das funktionsähnliche Prädikats
(das ist die Funktion, die als Lösung für dieses Programm implementiert wurde), das die kürzestmögliche Zeichenfolge findet, die als Eingabe ausgewertet wird (dies ist frustrierend wortreich für eine relativ einfache Aufgabe, aber das ist Prolog für dich…).Das Programm sollte ziemlich selbsterklärend sein, da es sich mehr oder weniger um eine direkte Übersetzung der Spezifikation in eine Grammatik und dann in die Prolog-Syntax handelt. die Definition
v
sagt , dassN
1 in eine leere Zeichenfolge ist, oderN
ist ,A
xB
(mitA
weniger alsB
weniger alsN
) , und die Schnur ist die Verkettung vonv(A)
undv(B)
oderN
ist ,M
+ 1 und die Saite wird:
konkateniert mitv(M)
konkateniert mit*
. Die zweite Zeile ist etwas subtiler.length(S,_)
bedeutet "S hat eine gewisse Länge", aber wenn Sie dies als erstes in der Zeile angeben, wird dies als Hinweis für die Prolog-Implementierung angesehen, dass zuerst die kürzesten Längen überprüft werden sollen (was bedeutet, dass wir die kürzestmögliche Länge für einen Rückgabewert erhalten). .quelle