Les mosaïques Duodyadic sont des types de blocs de fonction carrés qui prennent deux entrées, une de leur côté supérieur et une de leur côté gauche, et ont deux sorties, une de leur côté droit et une de leur côté inférieur. Chacune de leurs sorties est une fonction distincte de leurs deux entrées.
Par exemple, si #
représente une mosaïque générique, la sortie droite R
est une fonction f
des entrées T
et L
, et la sortie du bas B
est une autre fonction g
de T
et L
:
T
L#R R = f(T, L)
B B = g(T, L)
(Les tuiles sont appelées "duo" puisqu'il y a deux fonctions et "dyadiques" puisque les deux fonctions ont deux arguments .)
Les tuiles peuvent ensuite être composées ensemble sur une grille, les sorties d'une tuile allant directement aux entrées des tuiles qu'elle voisine. Ici par exemple, la sortie droite de gauche #
va dans l'entrée gauche de droite #
:
AB D = f(f(A, C), B)
C##D E = g(A, C)
EF F = g(f(A, C), B)
Vous pouvez imaginer qu'avec un ensemble de mosaïques duodyadiques, chacune avec une fonctionnalité spécifique, des compositions complexes (et potentiellement utiles) pourraient être créées.
Dans ce défi, nous ne nous intéresserons qu'au jeu traditionnel de dix mosaïques duodyadiques basées sur la logique , dans lesquelles toutes les entrées et sorties sont des nombres binaires à un bit (zéros ou uns). Nous utiliserons un caractère ASCII distinct pour désigner chaque type de mosaïque.
Les caractères de mosaïque et leurs relations d'entrée-sortie sont les suivants:
( T
est pour l'entrée supérieure, L
pour l'entrée gauche, R
pour la sortie droite, B
pour la sortie inférieure.)
- Zéro:
0
ou(espace) →
R = 0
,B = 0
- Un:
1
→R = 1
,B = 1
- Croix:
+
→R = L
,B = T
- Miroir:
\
→R = T
,B = L
- Haut seulement:
U
→R = T
,B = T
- Gauche seulement:
)
→R = L
,B = L
- Non:
!
→R = not L
,B = not T
- Et:
&
→R = L and T
,B = L and T
- Ou:
|
→R = L or T
,B = L or T
- Xor:
^
→R = L xor T
,B = L xor T
Défi
Ecrivez un programme ou une fonction prenant une grille rectangulaire de caractères 0 1+\U)!&|^
qui représente un "circuit" réalisé à l'aide des dix mosaïques duodyadiques à base logique. Vous devez également prendre en compte deux chaînes de 0
'et 1
'; un sera la colonne de gauche et un la première ligne. Votre programme / fonction doit imprimer / retourner la ligne de sortie inférieure et la colonne de sortie droite (également dans 0
's et 1
' s).
Par exemple, dans cette grille
+++
+++
toutes les entrées passent directement à travers la grille vers les sorties
ABC
D+++D
E+++E
ABC
donc une entrée de 010
/ 01
aurait la sortie 010
/ 01
:
010
0+++0
1+++1
010
Le résultat exact de votre programme serait [bottom output row]\n[right output column]
ou [bottom output row]/[right output column]
:
010
01
ou
010/01
Si vous avez écrit une fonction, vous pouvez renvoyer les deux chaînes dans un tuple ou une liste (ou encore les imprimer).
Détails
- Prenez les trois entrées comme des chaînes de manière raisonnable (de préférence dans la grille de commande, la ligne du haut, la colonne de gauche): ligne de commande, fichier texte, sdtin, fonction arg.
- Vous pouvez supposer que la longueur des lignes et des colonnes en entrée correspondra aux dimensions de la grille et ne contiendra que
0
les s et1
'. - Votre grille doit utiliser les caractères appropriés (
0 1+\U)!&|^
). N'oubliez pas cela0
etsignifie la même chose.
Cas de test
(Lire I / O sous la forme top
/ left
→ bottom
/ right
.)
Nand:
&!
00
/ 0
→ 01
/ 1
00
/ 1
→ 01
/ 1
10
/ 0
→ → 01
/ 1
10
/ 1
→ 11
/0
Tous les uns:
1111
1\+\
1+\+
1\+\
Toute entrée doit avoir pour résultat 1111
/ 1111
.
Xor from Nand: (notez la colonne d'espaces finaux)
\)+\
U&!&
+! !
\&!&
!
00000
/ 00000
→ 00000
/ 00000
00000
/ 10000
→ 00010
/ 00000
10000
/ 00000
→ → 00010
/ 00000
10000
/ 10000
→ 00000
/00000
Zig zag:
+++\00000000
000\!!!!\000
00000000\+++
Le premier bit de l'entrée de gauche devient le dernier bit de la sortie de droite. Tout le reste est 0
.
000000000000
/ 000
→ 000000000000
/ 000
000000000000
/ 100
→ 000000000000
/001
Propagation:
)))
UUU
U+U
U+U
UUU
Le premier bit de l'entrée de gauche va à toutes les sorties.
000
/ 00000
→ 000
/ 00000
000
/ 10000
→ 111
/11111
Voici une liste de tous les cas de test de grille 1 × 1.
Notation
La soumission la plus courte en octets l' emporte.
Bonus: Quels "circuits" cool pouvez-vous faire?
PS Ne vous embêtez pas sur Google "tuiles duodyadiques". Je les ai inventées hier; D
Si vous souhaitez discuter de l’extension de cette idée dans un langage de programmation à part entière, présentez-vous à cette salle de discussion .
la source
Réponses:
Pyth, 122
Une sorte de monstre. Utilise simplement la récursivité, rien de plus sophistiqué que la programmation dynamique.
Démonstration en ligne .
L’entrée est la suivante: d’abord la grille (pas d’échappement, pas de symboles supplémentaires), puis les deux lignes d’entrée, par exemple (Zig-zag)
la source
Mathematica,
331276270267264262252250 octetsle
s'agit d'un caractère Unicode à usage privé que Mathematica utilise en exposantT
, c'est-à-dire qu'il s'agit de l'opérateur de transposition.Voici une version plus lisible:
C'est une fonction sans nom qui prend les trois chaînes pour les entrées grille, haut et gauche et imprime les sorties bas et droite.
Explication
Passons en revue cette étape par étape (j'essaierai de ne pas assumer les connaissances de Mathematica). Vous devez en quelque sorte lire le code à l'envers. L’algorithme de base balaye les lignes en calculant chaque fonction et en enregistrant les résultats dans
f
pour que les tuiles suivantes puissent y accéder.Traitement d'entrée
C'est ce bit:
Cela divise simplement la grille en une liste imbriquée de caractères (remarque que j'ai définie
h
comme un alias pourCharacter
quelque part dans le code), puis ajoute une ligne et une colonne avec les entrées. Cela fonctionne, parce que1
et0
sont aussi les noms des tuiles fonction constante, donc en fait de les mettre sur le a le même effet que l' alimentation des entrées manuellement. Comme ce sont des fonctions, ils vont techniquement prendre leur entrée en dehors de la grille, mais étant donné que ce sont des fonctions constantes, cela n'a pas d'importance. Le coin en haut à gauche devient un0
mais cela est assez arbitraire car les résultats de cette tuile ne sont jamais utilisés.Notez également la transposition. L'ajout de colonnes prend plus de caractères que l'ajout de lignes. Je transpose donc la grille après avoir ajouté la ligne du haut. Cela signifie que haut / bas et gauche / droite sont échangés pour la partie principale du programme, mais ils sont complètement échangeables, donc peu importe. Je dois juste m'assurer de renvoyer les résultats dans le bon ordre.
Résoudre la grille
(Cette section est légèrement obsolète. Je vais y remédier une fois que je suis vraiment sûr d’avoir terminé le golf.)
Ensuite, nous parcourons
MapIndexed
le niveau interne de cette liste imbriquée. Ceci appelle la fonction anonyme fournie en tant que premier argument pour chaque caractère de la grille, également donnant une liste avec les deux coordonnées actuelles. La grille étant parcourue dans l’ordre, nous pouvons calculer en toute sécurité chaque cellule en fonction des cellules précédentes.Nous utilisons les variables
r
(ight) etb
(ottom) comme tables de recherche pour les résultats de chaque cellule. Notre fonction anonyme a les coordonnées actuelles dans#2
, donc nous obtenons les entrées de toute cellule avecNotez que dans la première ligne et la première colonne, cela permettra d'accéder aux valeurs non définies de
r
etb
. Mathematica n’a pas vraiment de problème avec cela et vous redonne simplement vos coordonnées, mais nous écartons néanmoins ce résultat, car toutes les mosaïques de cette rangée / colonne sont des fonctions constantes.Maintenant cette chose:
Est une forme de golf de
Ce qui à son tour est une fonction qui, étant donné les deux entrées de mosaïque, retourne une Association (on l'appelle une table de hachage ou une table dans d'autres langues), contenant tous les résultats de mosaïque possibles pour ces deux entrées. Pour comprendre comment toutes les fonctions sont implémentées, vous devez savoir que le premier argument d’une telle fonction est accessible avec
#
le second#2
. En outre,##
vous donne une séquence des deux arguments qui peuvent être utilisés pour "splat" les arguments.0
: est simple, nous retournons simplement une constante{0, 0}
et l'assignons égalementz
pour une utilisation future (par exemple, dans la vignette d'espace).1
: est essentiellement juste{1,1}
, mais avoirz
cela est raccourci à1+z
. Nous enregistrons également celao
, car il sera utile pour toutes les mosaïques où les deux sorties sont identiques.+
: Nous utilisons ici la séquence.{##}
est identique à{#,#2}
et passe les deux entrées inchangées.\
: Nous échangeons les deux arguments,{#2,#}
.U
: Maintenant, nous pouvons utilisero
.o#2
signifie{1,1}*#2
donc que nous venons de mettre l'argument supérieur dans les deux sorties.)
: Pour l'argument analogue gauche:o#
.!
: Négation binaire est gênant dans Mathematica, mais étant donné que nous ne jamais avoir0
et1
, nous pouvons tout simplement soustraire les deux entrées de1
(ce qui les inverser) et les transmettre:1-{##}
.&
: Celui-ci est assez chouette. Nous remarquons d’abord que bitwise et pour0
et1
est identique à la multiplication. En outre,o##
est le même queo*#*#2
.|
: Encore une fois, nous utilisons une fonction équivalente. Bitwise ou est le même queMax
dans ce cas, nous appliquonsMax
donc aux arguments d'entrée et multiplions le résultat{1,1}
.^
: Le plus court que j'ai trouvé pour xor est de prendre la différence et de la corriger (pour assurer la positivité), donc nous avonso(#-#2)^2
.Une fois que cette fonction est terminée et renvoie l'association complète, nous utilisons le caractère de la cellule actuelle pour extraire l'élément qui nous intéresse et le stocker dans
r
etb
. Notez que c’est aussi la valeur de retour de la fonction anonyme utilisée dansMapIndexed
, de sorte que le mappage me donnera en réalité une grille de tous les résultats.Traitement de sortie
MapIndexed
retourne une grille 3D, où la première dimension correspond à la coordonnée de la grille horizontale (rappelez-vous la transposition précédente), la deuxième dimension correspond à la coordonnée de la grille verticale et la troisième indique si nous avons une sortie en bas ou à gauche. Notez que cela contient également la ligne et la colonne en entrée dont nous devons nous débarrasser. Nous avons donc accès à la sortie inférieure de la rangée du bas avecet la sortie droite de la dernière colonne avec
Notez que
2;;
s'agit d'une plage allant du deuxième au dernier élément.Enfin, nous appliquons
Print
à tous les deux (en utilisant en@@@
tant que sucre syntaxique pour le deuxième niveauApply
), qui affiche simplement tous ses arguments dos à dos (et puisqu'il est appliqué à deux expressions distinctes, il y aura une nouvelle ligne entre sortie droite).la source
C,
332309272270266259247225 octetsVoir les résultats en ligne ici!
Cela définit une fonction
void f(char*, char*, char*)
, qui doit prendre le tableau en tant que première entrée, puis la rangée d’entrée supérieure, puis la rangée d’entrée gauche.Voici ce que j'ai utilisé pour le tester:
Ainsi, en entrant le multiplicateur à 2 bits de Sp3000:
On a:
Sur une autre note, avec le demi-additionneur de Sp3000 en tête, j'aimerais voir un additionneur complet ...L'un de vous l'a fait! Je ne pense pas que le système soit autonome en tant que langage de programmation, mais il a été très intéressant. Cela semble être une excellente cible pour le métagolf!Une courte explication:
Voici le code dévoilé et commenté:
Nous itérons sur
c
, de gauche à droite (puis de haut en bas), réécrivant lest
entrées à chaque fois et en poussant une sortie la plus à droite qui est poussé dans lal
chaîne. On peut imaginer que cela remplace la rangée supérieure dec
avec1
et0
' de manière itérative, tout en gardant une trace des bits qui sont poussés vers la droite.Voici une séquence plus visuelle, ligne par ligne:
Cela devient évidemment plus compliqué avec des symboles et des tailles différentes, mais l'idée centrale est la même. Cela ne fonctionne que parce que les données ne remontent jamais ni ne sortent.
la source
f
enf(c,t,l)char*c,*t,*l
(ne vous inquiétez pas du type de retour).f(c,t,l)char*c,*t,*l;
. Ne compilez pas en mode C11, car la règle int implicite permettant de supprimer le type de retour a été supprimée dans cette révision.*l
? Il compile en mode C99 sur ma machine.Python 2, 316 octets
Cette fonction crée 10 fonctions lambda en mosaïque, puis itère dans la grille en mettant à jour les états logiques. Les états logiques finaux vertical et horizontal sont ensuite imprimés.
Le code non-golfé comprenant des tests:
Le
test.txt
fichier (y compris 2 autres tests réalisés par Sp3000):La sortie de test:
la source
Python 2,
384338325 octetsSérieusement, si ce n'est pas déjà un jouet, vous devriez commencer à faire sonner des usines de jouets.
Plus golfé et beaucoup moins efficace maintenant, mais je n’ai toujours pas rattrapé CarpetPython. Comme en entrée
f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010")
, la sortie est un tuple de deux chaînes. Assurez-vous que le tableau ne comporte pas de saut de ligne, ce qui risquerait de casser des choses.Programme de test
Vous pouvez également tester tous les cas possibles avec
test_all()
.Cas de test supplémentaires
Demi additionneur
Voici un demi additionneur qui ajoute les bits en haut à gauche
<input bit> <carry> <sum>
:Tests:
La sortie doit être la même, même si les deuxième / troisième bits des entrées sont modifiés.
Décalage droit
Étant donné
abc / def
, cela génèrefab / cde
:Tests:
Trieur 3 bits
Trie les trois premiers bits du haut dans les trois derniers bits du bas. La sortie droite est indésirable.
Tests:
Multiplicateur 2 bits par 2 bits
Prend les 1er / 2ème bits de top comme premier chiffre et les 3ème / 4ème bits de top comme deuxième nombre. Affiche les quatre derniers bits du bas. La sortie droite est indésirable.
Edit: Golfé une colonne et deux lignes.
Tests:
la source
R,
524517Probablement beaucoup de place pour réduire cela pour le moment, mais cela a été vraiment intéressant à faire. Il y a deux fonctions. La fonction d est le travailleur et f le comparateur.
La fonction d est appelée avec 3 chaînes, Gates, Top et Left. Les portes sont placées dans une matrice déterminée par la largeur.
Un peu formaté
Quelques tests
la source