Os blocos duodádicos são tipos de blocos funcionais quadrados que recebem duas entradas, uma do lado superior e outra do lado esquerdo, e têm duas saídas, uma no lado direito e outra no lado inferior. Cada uma de suas saídas é uma função separada de ambas as entradas.
Por exemplo, se #
representa um bloco genérico, a saída correta R
é uma função f
das entradas T
e L
, e a saída inferior B
é outra função g
de T
e L
:
T
L#R R = f(T, L)
B B = g(T, L)
(Os blocos são denominados "duo", pois existem duas funções, e "diádico", pois as duas funções têm dois argumentos .)
Os ladrilhos podem então ser compostos juntos em uma grade, as saídas de um ladrilho indo diretamente para as entradas dos ladrilhos vizinhos. Aqui, por exemplo, a saída direita da esquerda #
entra na entrada esquerda da direita #
:
AB D = f(f(A, C), B)
C##D E = g(A, C)
EF F = g(f(A, C), B)
Você pode imaginar que, dado um conjunto de blocos duodádicos, cada um com funcionalidade específica, composições complexas (e potencialmente úteis) possam ser feitas.
Neste desafio, nos preocuparemos apenas com o conjunto tradicional de dez blocos duodádicos baseados em lógica , em que todas as entradas e saídas são números binários de bit único (zeros ou uns). Usaremos um caractere ASCII separado para denotar cada tipo de bloco.
Os caracteres do bloco e suas relações de entrada e saída são os seguintes:
( T
é para entrada superior, L
entrada esquerda, R
saída direita,B
saída inferior).
- Zero:
0
ou(espaço) →
R = 0
,B = 0
- Um:
1
→R = 1
,B = 1
- Cruz:
+
→R = L
,B = T
- Espelho:
\
→R = T
,B = L
- Somente no topo:
U
→R = T
,B = T
- Apenas à esquerda:
)
→R = L
,B = L
- Não:
!
→R = not L
,B = not T
- E:
&
→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
Desafio
Escreva um programa ou função que 0 1+\U)!&|^
consiga uma grade retangular de caracteres que represente um "circuito" feito usando os dez ladrilhos duodádicos baseados em lógica. Você também precisa inserir duas cadeias de 0
's e 1
' s; uma será a coluna de entrada esquerda e a outra será a linha de entrada superior. Seu programa / função precisa imprimir / retornar a linha de saída inferior e a coluna de saída direita (também em 0
's e1
' s).
Por exemplo, nesta grade
+++
+++
todas as entradas fluem diretamente pela grade para as saídas
ABC
D+++D
E+++E
ABC
portanto, uma entrada de 010
/ 01
teria saída 010
/ 01
:
010
0+++0
1+++1
010
A saída exata do seu programa seria [bottom output row]\n[right output column]
ou [bottom output row]/[right output column]
:
010
01
ou
010/01
Se você escreveu uma função, você pode retornar as duas strings em uma tupla ou lista (ou ainda imprimi-las).
Detalhes
- Pegue as três entradas como seqüências de caracteres de qualquer maneira razoável (de preferência na grade de pedidos, linha superior, coluna esquerda): linha de comando, arquivo de texto, sdtin, função arg.
- Você pode assumir que os comprimentos de linha e coluna de entrada corresponderão às dimensões da grade e conterão apenas
0
's e1
' s. - Sua grade deve usar os caracteres adequados (
0 1+\U)!&|^
). Lembre-se disso0
esignifique a mesma coisa.
Casos de teste
(Leia E / S como top
/ left
→ bottom
/ right
.)
Nand:
&!
00
/ 0
→ 01
/ 1
00
/ 1
→ 01
/ 1
10
/ 0
→ 01
/ 1
10
/ 1
→ 11
/0
Todos:
1111
1\+\
1+\+
1\+\
Qualquer entrada deve resultar em 1111
/ 1111
.
Xor de Nand: (observe a coluna de espaços finais)
\)+\
U&!&
+! !
\&!&
!
00000
/ 00000
→ 00000
/ 00000
00000
/ 10000
→ 00010
/ 00000
10000
/ 00000
→ 00010
/ 00000
10000
/ 10000
→ 00000
/00000
Ziguezague:
+++\00000000
000\!!!!\000
00000000\+++
O primeiro bit da entrada esquerda se torna o último bit da saída direita. Tudo o resto é 0
.
000000000000
/ 000
→ 000000000000
/ 000
000000000000
/ 100
→ 000000000000
/001
Propagação:
)))
UUU
U+U
U+U
UUU
O primeiro bit da entrada esquerda vai para todas as saídas.
000
/ 00000
→ 000
/ 00000
000
/ 10000
→ 111
/11111
Aqui está uma pasta de todos os casos de teste de grade 1 × 1.
Pontuação
O menor envio em bytes vence.
Bônus: Que "circuitos" legais você pode fazer?
PS: Não se incomode com o Google "azulejos duodádicos". Eu as criei ontem; D
Se você quiser discutir a expansão dessa idéia em uma linguagem de programação completa, venha para esta sala de bate-papo .
fonte
Respostas:
Pyth, 122
Tipo de monstro. Usa simplesmente recursão, nada extravagante como programação dinâmica.
Demonstração online .
A entrada é da seguinte maneira: Primeiro a grade (sem escape, sem símbolos extras) e, em seguida, as duas linhas de entrada, por exemplo (Zig zag)
fonte
Mathematica,
331276270267264262252250 byteso
é um caractere Unicode de uso privado que o Mathematica usa como sobrescritoT
, ou seja, é o operador de transposição.Aqui está uma versão mais legível:
Esta é uma função sem nome que pega as três seqüências de caracteres para as entradas de grade, superior e esquerda e imprime as saídas inferior e direita.
Explicação
Vamos seguir este passo a passo (tentarei não assumir nenhum conhecimento do Mathematica). Você precisa ler o código de trás para frente. O algoritmo básico apenas varre as linhas computando cada função e armazenando os resultados em
f
para serem acessados pelos blocos subsequentes.Processamento de entrada
É esse pedaço:
Isso apenas divide a grade em uma lista aninhada de caracteres (observe que eu defini
h
como um alias paraCharacter
algum lugar no código) e, em seguida, precede uma linha e uma coluna com as entradas. Isso funciona, porque1
e0
também são os nomes dos blocos de função constante; portanto, colocá-los na mesma tem o mesmo efeito que alimentar as entradas manualmente. Como essas são funções, elas tecnicamente receberão sua entrada de fora da grade, mas, como são funções constantes, isso não importa. O canto superior esquerdo recebe uma0
mas isso é bastante arbitrário, pois os resultados desse bloco nunca são usados.Observe também a transposição. A adição de colunas ocupa mais caracteres do que a adição de linhas, por isso transponho a grade depois de adicionar a linha superior. Isso significa que as partes superior / inferior e esquerda / direita são trocadas pela parte principal do programa, mas são completamente trocáveis, portanto não importa. Eu só preciso garantir os resultados na ordem correta.
Resolvendo a grade
(Esta seção está um pouco desatualizada. Será corrigida assim que tiver certeza de que terminei de jogar golfe).
Em seguida, executamos
MapIndexed
o nível interno dessa lista aninhada. Isso chama a função anônima fornecida como o primeiro argumento para cada caractere na grade, também fornecendo uma lista com as duas coordenadas atuais. A grade é atravessada em ordem, para que possamos calcular com segurança cada célula com base nas anteriores.Usamos as variáveis
r
(ight) eb
(ottom) como tabelas de pesquisa para os resultados de cada célula. Nossa função anônima possui as coordenadas atuais em#2
, obtemos as entradas para qualquer célula comObserve que na primeira linha e coluna isso acessará valores indefinidos de
r
eb
. O Mathematica realmente não tem um problema com isso e apenas devolve suas coordenadas, mas descartamos esse resultado de qualquer maneira, pois todos os blocos nessa linha / coluna são funções constantes.Agora essa coisa:
É uma forma de golfe
Por sua vez, é uma função que, dadas as duas entradas do bloco, retorna uma Associação (você chamaria de hashmap ou tabela em outros idiomas), que contém todos os resultados possíveis do bloco para essas duas entradas. Para entender como todas as funções são implementadas, você precisa saber que o primeiro argumento dessa função pode ser acessado com
#
e o segundo com#2
. Além disso,##
fornece uma sequência de ambos os argumentos que podem ser usados para "dividir" os argumentos.0
: é simples, basta retornar uma constante{0, 0}
e também atribuí-la az
para uso futuro (por exemplo, no espaço).1
: é essencialmente justo{1,1}
, masz
reduzi-lo para isso1+z
. Também salvamos issoo
, porque será útil para todos os blocos em que ambas as saídas são idênticas.+
: Aqui fazemos uso da sequência.{##}
é o mesmo{#,#2}
e passa as duas entradas inalteradas.\
: Trocamos os dois argumentos,{#2,#}
,.U
: Agora podemos fazer usoo
.o#2
significa{1,1}*#2
que apenas colocamos o argumento principal em ambas as saídas.)
: Analogamente para o argumento da esquerda:o#
.!
: Bitwise not não é chato no Mathematica, mas como só temos0
e1
podemos subtrair ambas as entradas1
(invertendo-as) e repassá-las:1-{##}
.&
: Este é bastante bacana. Primeiro, notamos que bit a bit e para0
e1
é idêntico à multiplicação. Além disso,o##
é o mesmo queo*#*#2
.|
: Novamente, usamos uma função equivalente. Bit a bit ou é o mesmo queMax
neste caso, então aplicamosMax
aos argumentos de entrada e multiplicamos o resultado em{1,1}
.^
: O mais curto que encontrei para o xor é pegar a diferença e quadrá-la (para garantir a positividade), então temoso(#-#2)^2
.Após essa função concluir e retornar a associação completa, usamos o caractere da célula atual para extrair o elemento em que estamos interessados e armazená-lo
r
eb
. Observe que esse também é o valor de retorno da função anônima usada noMapIndexed
, portanto, o mapeamento me fornecerá uma grade de todos os resultados.Processamento de saída
MapIndexed
retorna uma grade 3D, onde a primeira dimensão corresponde à coordenada da grade horizontal (lembre-se da transposição anterior), a segunda dimensão corresponde à coordenada da grade vertical e a terceira indica se temos uma saída inferior ou esquerda. Observe que isso também contém a linha e a coluna de entrada das quais precisamos nos livrar. Então, acessamos a saída inferior da linha inferior come a saída correta da coluna final com
Observe que
2;;
é um intervalo do segundo ao último elemento.Por fim, aplicamos
Print
a ambos (usando@@@
como o açúcar sintático para o segundo nívelApply
), que apenas imprime todos os seus argumentos lado a lado (e, como é aplicado a duas expressões separadas, haverá uma nova linha entre inferior e saída direita).fonte
C,
332309272270266259247225 bytesVeja os resultados online aqui!
Isso define uma função
void f(char*, char*, char*)
, que deve considerar o quadro como sua primeira entrada, a linha superior da entrada e a linha esquerda da entrada.Aqui está o que eu costumava testá-lo:
Assim, inserindo o multiplicador de 2 bits do Sp3000:
Nós temos:
Em outra nota, com o meio adicionador do Sp3000 em mente, eu gostaria de ver um adicionador completo ...Um de vocês conseguiu! Eu não acho que o sistema se sustente por si só como uma linguagem de programação, mas tem sido muito interessante. Este parece ser um excelente alvo para o metagolfe!Uma breve explicação:
Aqui está o código comentado e desvendado:
Repetimos
c
, da esquerda para a direita (de cima para baixo), reescrevendo ast
entradas a cada vez e pressionando uma saída mais à direita, que é inserida nal
string. Podemos imaginar isso substituindo a linha superior dec
com1
s e0
iterativamente, e acompanhando os bits que são empurrados para a direita.Aqui está uma sequência mais visual, linha por linha:
Obviamente, isso se torna mais complicado com símbolos e tamanhos diferentes, mas a ideia central é válida. Isso funciona apenas porque os dados nunca fluem para cima ou para a esquerda.
fonte
f
paraf(c,t,l)char*c,*t,*l
(não dê a mínima para o tipo de retorno).f(c,t,l)char*c,*t,*l;
. Não compile no modo C11, pois a regra int implícita que nos permite descartar o tipo de retorno foi descartada nessa revisão.*l
? Compila no modo C99 na minha máquina.Python 2, 316 bytes
Essa função cria 10 funções lambda de bloco e itera pela grade, atualizando os estados lógicos. Os estados lógicos verticais e horizontais finais são impressos.
O código não protegido, incluindo testes:
O
test.txt
arquivo (incluindo outros 2 testes do Sp3000):A saída do teste:
fonte
Python 2,
384338325 bytesSério CH, se este ainda não é um brinquedo, você deve começar a ligar para algumas fábricas de brinquedos.
Mais jogado e muito menos eficiente agora, mas ainda não alcançou o CarpetPython. Entrada como
f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010")
, saída é uma tupla de duas strings. Certifique-se de que o quadro não tenha uma nova linha à direita, o que quebrará as coisas.Programa de teste
Você também pode testar todos os casos possíveis com
test_all()
.Casos de teste extras
Meio adicionador
Aqui está um meio somador que adiciona os bits superiores esquerdos, produzindo
<input bit> <carry> <sum>
:Testes:
A saída deve ser a mesma, mesmo que os segundos / terceiros bits das entradas sejam alterados.
Deslocamento para a direita
Dado
abc / def
, isso gerafab / cde
:Testes:
Classificador de 3 bits
Classifica os três primeiros bits do topo nos últimos três bits do fundo. A saída correta é lixo.
Testes:
Multiplicador de 2 por 2 bits
Toma o 1º / 2º bits de topo como o primeiro número e o 3º / 4º bits de topo como o segundo número. Saídas para os últimos quatro bits da parte inferior. A saída correta é lixo.
Edit: Jogou fora uma coluna e duas linhas.
Testes:
fonte
R,
524517Provavelmente há muito espaço para reduzir isso no momento, mas isso tem sido realmente interessante de se fazer. Existem duas funções. A função d é o trabalhador ef é o comparador.
A função d é chamada com 3 strings, Gates, Top e Left. Os Gates são colocados em uma matriz determinada pela largura.
Formatado um pouco
Alguns testes
fonte