Haskell , 1080 1033 Bytes
;
f=
g
ij=f
a =hi
hi = g
hij= ij
g ' ' =0
g '"' =0;
g '$' =0;
g '&' =0-0
g '(' =0-0-0
g '*' =0-0-0;
g ',' =0-0-0;
g '.' =0-0-0-0
g '0' =0-0-0-0-0
g '2' =0-0-0-0-0;
g '4' =0-0-0-0-0;
g '6' =0; g '8' =0
g ':' =0; g '<' =0-0
g '>' =0; g '@' =0-0;
g 'B' =0; g 'D' =0-0;
g 'F' =0; g 'H' =0-0-0
g 'J' =0; g 'L' =0-0-0-0
g 'N' =0; g 'P' =0-0-0-0;
g 'R' =0; g 'T' =0-0-0-0;
g 'V' =0; g 'X' =0-0-0-0-0
g 'Z' =0; g '^' =0; g '`' =0
g 'b' =0; g 'd' =0; g 'f' =0;
g 'h' =0; g 'j' =0; g 'l' =0;
g 'n' =0; g 'p' =0; g 'r' =0-0
g 't' =0; g 'v' =0; g 'x' =0-0-0
g 'z' =0; g '\92' =0-0; g '|' =0;
g '~' =0; g y = 1 ;z=0; i(-0)z=z;
i m('\10':y ) ="y"; ; ; ; ; ; ; ;
i m(mnmnmnmnm:y ) = i(m - 1 ) y ; ;
i k m ="y"; ; k i [ ] =01<1010101010;
k m('\10':y ) = k(m + 1 )(i m y ) ; ;
k m y =01>10; m o = k 1$'\10':o ; ; ;
o i('\10':y ) = o i y ; ; ; ; ; ; ; ; ;
o i(k:y )|g k<i = o(1 - i ) y ; ; ; ; ; ;
o i(k:y )|g k>i = o(1 - i ) y ; ; ; ; ; ;
o i [ ] =01<10; o i y =01>10;v=01>10101010
s y|o 1 y = m y|o(-0) y = m y ; s y =v; ; ;
Probieren Sie es online aus!
Erläuterung
Dies war für Haskell eine interessante Aufgabe.
Parität
Zu Beginn müssen wir feststellen, ob ein Zeichen einen geraden oder einen ungeraden Codepunkt hat. Der normale Weg, dies zu tun, besteht darin, den Codepunkt abzurufen und um 2 zu modifizieren. Wie man jedoch wissen könnte, erfordert das Abrufen des Codepunkts eines Zeichens einen Import, was aufgrund der Quellenbeschränkung bedeutet, dass dies nicht möglich ist gebraucht. Ein erfahrener Haskeller würde denken, Rekursion zu verwenden. Char
sind Teil der Enum
Typklasse, damit wir ihre Vorgänger und Nachfolger bekommen können. Allerdings pred
und succ
ist auch beide unbrauchbar , weil sie keine alternative Byteparität tun.
Das lässt uns ziemlich stecken, wir können so gut wie keine Manipulationen mit Zeichen durchführen. Die Lösung hierfür besteht darin, alles fest zu codieren. Wir können (die meisten) geraden Zeichen als Literale darstellen, Chancen, mit denen wir Probleme haben, weil sie '
ungerade sind, so dass sie nicht neben dem Zeichen selbst stehen können, was es dem Literal unmöglich macht, die meisten ungeraden Zeichen auszudrücken. Also codieren wir alle geraden Bytes hart und fügen am Ende einen Catch für alle ungeraden Bytes hinzu.
Das Problem Bytes
Möglicherweise stellen Sie fest, dass es einige gerade Bytes gibt, für die Literale nicht in einfache Anführungszeichen gesetzt werden können. Sie sind die Unprintables, Newlines und \
. Wir müssen uns keine Gedanken über nicht druckbare Dateien machen, da wir keine überprüfen müssen, solange wir keine verwenden. Tatsächlich können wir immer noch ungerade nicht druckbare Dateien wie Tabs verwenden, die ich am Ende einfach nicht brauche. Newline kann natürlich ignoriert werden, da es sowieso aus dem Programm entfernt wird. (Wir könnten Newline einfügen, da der Code-Punkt ziemlich praktisch ist, aber wir müssen nicht). Damit bleibt \
nun \
der Codepunkt 92, der zweckmäßigerweise eine ungerade Zahl gefolgt von einer geraden Zahl ist, also \92
zwischen Evens und Odds wechselt, also das Literal'\92'
ist vollkommen gültig. Wenn wir später Newline darstellen müssen, werden wir feststellen, dass es zum Glück dieselbe Eigenschaft hat '\10'
.
Abstandsprobleme
Um mit dem Schreiben des eigentlichen Codes beginnen zu können, müssen wir in der Lage sein, eine beträchtliche Anzahl von Zeichen in eine einzelne Zeile zu setzen. Um dies zu tun, schrieb ich die Kappe:
;
f=
g
ij=f
a =hi
hi = g
hij= ij
Die Kappe macht nichts anderes als gültige Haskell. Ich hatte ursprünglich gehofft, Definitionen zu erstellen, die uns später im Code helfen würden, aber das tat es nicht. Es gibt auch einfachere Möglichkeiten, die Obergrenze festzulegen, z. B. Leerzeichen und Semikolons, aber sie speichern auf diese Weise keine Bytes, sodass ich mich nicht darum gekümmert habe, sie zu ändern.
Hardcoder
Jetzt, da ich genug Platz in einer Zeile habe, beginne ich mit der Hardcodierung von Werten. Das ist meistens ziemlich langweilig, aber es gibt ein paar interessante Dinge. Zum einen können wir, sobald die Zeilen noch länger werden ;
, mehrere Deklarationen in eine Zeile einfügen, wodurch wir eine Menge Bytes sparen.
Das zweite ist, dass wir g
die Zeilen ein wenig einrücken müssen , da wir nicht immer eine Zeile mit a beginnen können . Jetzt kümmert sich Haskell wirklich um die Einrückung, also wird es sich darüber beschweren. Wenn jedoch die letzte Zeile vor der eingerückten Zeile mit einem Semikolon endet, wird dies zugelassen. Warum? Ich habe nicht die geringste, aber es funktioniert. Wir müssen uns also nur daran erinnern, die Semikolons am Ende der Zeilen zu platzieren.
Funktionsbausteine
Sobald der Hardcoder fertig ist, läuft es reibungslos bis zum Ende des Programms. Wir müssen ein paar einfache Funktionen erstellen. Zuerst baue ich eine Version von drop
, genannt i
. i
unterscheidet sich davon, drop
dass wenn wir versuchen, über das Ende der Zeichenfolge hinauszugehen, diese nur zurückgegeben wird "y"
. i
unterscheidet sich von drop auch darin, dass beim Versuch, eine neue Zeile zu löschen, diese zurückgegeben wird "y"
. Diese sind nützlich, da wir später, wenn wir überprüfen, ob das Programm ein Dreieck ist, zurückkehren können, False
wenn die letzte Zeile nicht vollständig ist oder wenn Eine Zeile endet früh.
Als nächstes haben wir, k
was tatsächlich bestätigt, dass eine Zeichenfolge dreieckig ist. k
ist ziemlich einfach, es braucht eine Zahl und eine Zeichenkette . Wenn leer ist, wird es zurückgegeben . Wenn die Zeichenfolge mit einer neuen Zeile beginnt, werden die neue Zeile und Zeichen von vorne entfernt. Es ruft dann erneut mit und der neuen Zeichenfolge auf. Wenn die Zeichenfolge nicht mit einer neuen Zeile beginnt, wird sie zurückgegeben .s s n n + 1nssTrue
nk
n+1False
Wir machen dann einen Alias für k
, m
. m
steht nur k
mit 1
im ersten Argument, und dem zweiten Argument wird eine neue Zeile vorangestellt.
Als nächstes haben wir o
. o
nimmt eine Zahl und eine Zeichenfolge. Es wird bestimmt, ob sich die Zeichenfolgenbytes (ohne Berücksichtigung von Zeilenumbrüchen) in der Parität abwechseln (unter Verwendung unserer g
), beginnend mit der eingegebenen Nummer.
Zuletzt haben wir s
welche o
mit beiden läuft 1
und 0
wenn es gelingt, verschiebt es sich m
. Wenn beide fehlschlagen, wird nur zurückgegeben False
. Dies ist die Funktion, die wir wollen. Es stellt fest, dass die Eingabe dreieckig und abwechselnd ist.