基于网格的数字逻辑(Duodyadic Tiles)


33

Duodyadic磁贴是正方形功能块的一种,具有两个输入,一个从顶部输入,一个从左侧输入,并具有两个输出,一个在右侧,一个在底部。它们的每个输出都是其两个输入的单独功能。

例如,如果#表示一个通用的瓦片,右输出R是函数f的输入TL,底部输出B是另一个函数gTL

 T
L#R         R = f(T, L)
 B          B = g(T, L)

(由于有两个函数,所以这些图块被称为“ duo”,而由于两个函数都有两个参数,它们被称为“ dyadic” 。)

然后,可以在网格上将图块组合在一起,一个图块的输出直接进入与其相邻的图块的输入。例如,在这里,左侧的右侧输出#进入右侧的左侧输入#

 AB         D = f(f(A, C), B)
C##D        E = g(A, C)
 EF         F = g(f(A, C), B)

您可以想象,如果给定一组Duodyadic磁贴,每个磁贴都具有特定的功能,则可以制作复杂(且可能有用)的合成。

在这个挑战中,我们将只关注传统的十组基于逻辑的双性平铺,其中所有输入和输出都是单位二进制数(零或一)。我们将使用单独的ASCII字符来表示每种类型的图块。

是瓷砖字符和它们的输入-输出关系,如下所示:
T为顶部输入,L为左输入,R用于右输出,B为底部输出。)

  1. 零:0(空格)→ R = 0B = 0
  2. 一:1R = 1B = 1
  3. 交叉:+R = LB = T
  4. 镜子:\R = TB = L
  5. 仅顶部:UR = TB = T
  6. 仅左:)R = LB = L
  7. 不是:!R = not LB = not T
  8. 并且:&R = L and TB = L and T
  9. 或者:|R = L or TB = L or T
  10. 异或:^R = L xor TB = L xor T

挑战

编写一个程序或函数,该程序或函数采用一个矩形字符网格,这些矩形网格0 1+\U)!&|^代表使用十个基于逻辑的双体平铺瓷砖制作的“电路”。您还需要输入两个字符串0的和1。一个将是左侧输入列,一个将是顶部输入行。您的程序/功能需要打印/返回底部的输出行和右侧的输出列(也在0s和1s中)。

例如,在此网格中

+++
+++

所有输入直接跨网格流向输出

 ABC
D+++D
E+++E
 ABC

因此,010/ 的输入01将输出010/ 01

 010
0+++0
1+++1
 010

程序的确切输出为[bottom output row]\n[right output column][bottom output row]/[right output column]

010
01

要么

010/01

如果编写了函数,则可以在一个元组或列表中返回两个字符串(或仍然打印它们)。

细节

  • 以任何合理的方式(最好在顺序网格,顶行,左列)将三个输入作为字符串:命令行,文本文件,sdtin,函数arg。
  • 您可以假设输入的行和列的长度与网格尺寸匹配,并且仅包含0“和1”。
  • 您的网格必须使用正确的字符(0 1+\U)!&|^)。记住这一点0意思是一样的。

测试用例

(将I / O读为top/ leftbottom/ right。)

南德:

&!

00/ 001/ 1
00/ 101/ 1
10/ 001/ 1
10/ 111/0

全部:

1111
1\+\
1+\+
1\+\

任何输入都应以1111/表示1111

来自Nand的Xor :(请注意尾随空格的列)

\)+\ 
U&!& 
+! ! 
\&!& 
   ! 

00000/ 0000000000/ 00000
00000/ 1000000010/ 00000
10000/ 0000000010/ 00000
10000/ 1000000000/00000

之字形:

+++\00000000
000\!!!!\000
00000000\+++

左输入的第一位变为右输出的最后一位。其他一切都是0

000000000000/ 000000000000000/ 000
000000000000/ 100000000000000/001

传播:

)))
UUU
U+U
U+U
UUU

左输入的第一位进入所有输出。

000/ 00000000/ 00000
000/ 10000111/11111

这是所有1×1网格测试用例的粘贴框。

计分

以字节为单位的最短提交获胜。

奖励:您可以制造出什么酷的“回路”?

PS不要打扰谷歌搜索“ duodyadic瓷砖”。我是昨天做的; D
如果您想讨论将这种想法扩展为成熟的编程语言,请进入此聊天室


11
+1是一项很酷的挑战,也是因为您发明了非常酷的Duodyadic Tiles。
Alex A.

3
+1实在对Google来说完全没有用:goo.gl/zuqfdW。好挑战!
BrainSteel

我和他们在一起。我对您的磁贴作为一种编程语言比对这个特殊的高尔夫挑战更感兴趣。PS:有16个可能的图块,因此想出其他六个的字母/名称会很整洁。
Sparr

拥有从不同方向输出/输入的块会很有趣,因为否则,您将无法制作闩锁,因为所有内容都是朝右方向流动的。
Sp3000 2015年

2
您可以将T / B更改为U(p)/ D(own),这样我们就可以以类似于Rubik多维数据集表示法的方式获得F / B,然后再更改。。。三体立方体?
Soham Chowdhury,2015年

Answers:


8

珀斯122

一种怪物。仅使用递归,没有动态编程那样的幻想。

D:NGHR@Cm+d[1HG&GH|GHxGH0),[GH!G)[HG!H)x"+\\!1U)&|^"N#aYw)M:@@YGH?hgGtHHv@eYG?egtGHGv@ePYHjkm+0egtleYklePYjkm+0hgbtlePYleY

在线演示

输入的方式如下:首先是网格(没有转义,没有多余的符号),然后是两行输入,例如(Zig zag)

+++\00000000
000\!!!!\000
00000000\+++
000000000000
100

8

Mathematica,331 276 270 267 264 262 252 250 250字节

Print@@@{#[[2;;,-1,2]],#[[-1,2;;,1]]}&@MapIndexed[h=Characters;({r@#2,b@#2}=<|##|>&@@Thread[h@"0 1+\\)U!&|^"->{0,0,1,i={##},{#2,#},##,1-i,1##,Max@i,(#-#2)^2}]&[r[#2-{1,0}],b[#2-{0,1}]]@#{1,1})&,Join[h@{"0"<>#3},h@StringSplit[#2<>"
"<>#,"
"]],{2}]&

是Mathematica用作上标的私有Unicode字符T,即它是转置运算符。

这是一个更具可读性的版本:

Print @@@ {#[[2 ;;, -1, 2]], #[[-1, 2 ;;, 1]]} &@
  MapIndexed[h = Characters;
   (
     {r@#2, b@#2} = <|##|> & @@ Thread[
            h@"0 1+\\)U!&|^" -> {
              0,
              0,
              1,
              i = {##},
              {#2, #},
              ##,
              1 - i,
              1 ##,
              Max@i,
              (# - #2)^2
              }] & [
          r[#2 - {1, 0}],
          b[#2 - {0, 1}]
          ] @ # {1, 1}
     ) &,
   Join[
    h@{"0" <> #3},
    h@StringSplit[#2 <> "\n" <> #, "\n"]\[Transpose]
   ],
   {2}] &

这是一个未命名的函数,它使用网格,顶部和左侧输入的三个字符串并输出底部和右侧输出。

说明

让我们逐步进行此过程(我将尽量不假设任何Mathematica知识)。您有点需要重新阅读代码。基本算法只需扫过计算每个功能的线,并将结果存储在其中f即可供后续图块访问。

输入处理

就是这样:

Join[
  h@{"0" <> #3},
  h@StringSplit[#2 <> "\n" <> #, "\n"]\[Transpose]
]

这只是将网格分割成一个嵌套的字符列表(请注意,我在代码中的某处定义h了别名Character),然后在行和列的前面加上了输入。这是有效的,因为1并且0也是常数函数磁贴的名称,因此实际上将它们放在上具有与手动输入输入相同的效果。由于这些是函数,因此从技术上讲,它们将从网格外部获取输入,但是由于它们是不变的函数,因此无关紧要。左上角有一个0但这是任意的,因为从未使用该图块的结果。

另请注意换位。添加列比添加行需要更多的字符,因此我在添加第一行后转置了网格。这意味着顶部/底部和左侧/右侧被交换为程序的主要部分,但是它们是完全可互换的,所以没关系。我只需要确保以正确的顺序返回结果即可。

解决网格

(本节略有过时。一旦我确定要打高尔夫球就可以解决。)

接下来,我们MapIndexed遍历此嵌套列表的内部级别。这将调用作为网格中每个字符的第一个参数提供的匿名函数,为其提供一个包含当前两个坐标的列表。网格按顺序遍历,因此我们可以安全地基于先前的网格计算每个单元。

我们使用变量r(ight)和b(ottom)作为每个单元格结果的查找表。我们的匿名函数的当前坐标为#2,因此我们可以通过

r[#2 - {1, 0}],
b[#2 - {0, 1}]

请注意,在第一行和第一列中,这将访问r和的未定义值b。Mathematica对此并没有真正的问题,只会将您的坐标返回给您,但是无论如何我们都会放弃此结果,因为该行/列中的所有图块都是常量函数。

现在这件事:

<|##|> & @@ Thread[
  h@"0 1+\\U)!&|^" -> {
     z = {0, 0}, z, o = 1 + z, {##}, ...
  }] &

是一种高尔夫形式

<|"0" -> (z = {0, 0}), " " -> z, "1" -> (o = 1 + z), "+" -> {##}, ... |> &

反过来,这是一个函数,给定这两个瓦片输入,它会返回一个关联(您将其称为哈希图或其他语言的表),其中包含这两个输入的所有可能的瓦片结果。要了解如何实现所有功能,您需要知道可以使用访问该函数的第一个参数,而使用可以访问#第二个参数#2。此外,还##为您提供了两个参数的序列,可用于“ splat”参数。

  • 0:很简单,我们只返回一个常量,{0, 0}并将其分配给z以后使用(例如在空格中)。
  • 1:本质上是公正的{1,1},但是z缩短为1+z。我们也将其保存在中o,因为对于两个输出相同的所有图块,它会派上用场。
  • +:在这里我们利用序列。{##}与相同,{#,#2}并且两个输入均保持不变。
  • \:我们交换两个参数{#2,#}
  • U:现在我们可以利用了oo#2的意思是,{1,1}*#2所以我们只将top参数放入两个输出中。
  • ):类似于左参数:o#
  • !:在Mathematica中,按位不是令人讨厌的方法,但是由于我们只有0and 1,因此我们可以简单地从1(减去它们)减去两个输入并将它们传递给:1-{##}
  • &:这很漂亮。首先,我们注意到按位与01与乘法相同。此外,o##与相同o*#*#2
  • |:同样,我们使用等效功能。按位或与Max本例相同,因此我们将其应用于Max输入参数并将结果乘以{1,1}
  • ^:我发现xor的最短方法是求差并求平方(以确保阳性),所以我们有了o(#-#2)^2

此函数完成并返回完整的关联后,我们使用当前单元格的字符提取我们感兴趣的元素并将其存储在rand中b。请注意,这也是在中使用的匿名函数的返回值MapIndexed,因此映射实际上将为我提供所有结果的网格。

输出处理

MapIndexed返回一个3D网格,其中第一个尺寸对应于水平网格坐标(请记住前面的转置),第二个尺寸对应于垂直网格坐标,第三个尺寸指示我们是底部输出还是左侧输出。请注意,这还包含我们需要删除的输入行和列。因此,我们使用以下命令访问底部行的底部输出

#[[2;;,-1,2]]

最后一列的正确输出为

#[[-1,2;;,1]]

请注意,这2;;是从第二个元素到最后一个元素的范围。

最后,我们将Print两者都应用(@@@用作第二层的语法糖Apply),它们仅以背对背的方式打印其所有参数(并且由于将其应用于两个单独的表达式,因此在下和下之间会有换行符正确的输出)。


8

C,332 309 272 270 266 259 247 225字节

#define C(x)*c-x?
i,k,T,L,m;f(c,t,l)char*c,*t,*l;{while(L=l[i]){for(k=0;T=t[k];c++)L=C(49)C(43)C(92)C(85)C(41)C(33)C(38)C('|')C(94)T=48:(T^=L-48):(T|=L):(T&=L):(T^=1,L^1):(T=L):T:(m=T,T=L,m):L:(T=49),t[k++]=T;c++;l[i++]=L;}}

在这里在线查看结果

这定义了一个函数void f(char*, char*, char*),该函数应将开发板作为其第一个输入,然后是输入的第一行,然后是输入的左行。

这是我用来测试的内容:

#include "stdio.h"
int main() {
    char buf[1024],top[33],left[33];
    /* Copy and paste an example circuit as the first input,
       and put a 'Q' immediately after it. 
       Note that the Q is never touched by the function f, and is used
       solely as a delimiter for input. */
    scanf("%[^Q]Q ",buf);
    /* Then enter your top inputs */
    scanf("%[01]%*[^01]", top);
    /* Then your left ones */
    scanf("%[01]", left);
    /* OUTPUT: Bottom\nRight */
    f(buf, top, left);
    return 0;
}

因此,通过输入Sp3000的2位乘法器:

UUUU))))
UU++)))&
UUU+)  U
UU++&))U
U++&+)^U
U)&\&)UU
   U+^UU
   \&UUUQ
11110000
00000000

我们得到:

00001001
11111111

另一方面,考虑到Sp3000的半加法器,我希望看到一个完整的加法器... 一个你们的做到了!我认为该系统不能独立作为一种编程语言,但是它非常有趣。不过,这似乎是metagolf的绝佳目标!

简短说明:

这是未整理的,已注释的代码:

/* We define the first half of the ?: conditional operator because, well,
   it appears over and over again. */
#define C(x)*c-x?
/* i,k are counting variables
   T,L are *current* top and left inputs */
i,k,T,L,m;
f(c,t,l)char*c,*t,*l;{
    /* The outer loop iterates from top to bottom over l and c */
    while(L=l[i]){
        /* Inner loop iterates from left to right over t and c */
        for(k=0;T=t[k];c++)
            /* This line looks awful, but it's just a bunch of character
            comparisons, and sets T and L to the output of the current c */
            L=C(49)C(43)C(92)C(85)C(41)C(33)C(38)C('|')C(94)T=48:(T^=L-48):(T|=L):(T&=L):(T^=1,L^1):(T=L):T:(m=T,T=L,m):L:(T=49),
            /* Write our output to our input, it will be used for the next row */
            t[k++]=T;
        c++; /*Absorbs the newline at the end of every row */
        /* Keep track of our right-most outputs, 
        and store them in the handy string passed to the function. */
        l[i++]=L;
    }
    /* Bottom output is now stored entirely in t, as is right output in l */        
}

我们遍历c,从左到右(然后从上到下),t每次都重写输入,并推出最右边的输出,将其推入l字符串中。我们可以想象这是替换的最上一行c1的和0的反复,以及在合适的压出位的跟踪。

这是逐行显示的更直观的序列:

 111                                  
1&+^  =>  110 ->0  =>     ->0  =>     0 Thus, "01" has been written to l,
1+&+     1+&+         110 ->1         1
                                  110   And "110" is stored currently in t.

显然,使用不同的符号和大小会变得更加复杂,但是中心思想仍然存在。这仅适用于数据永远不会向上流动或离开的情况。


打高尔夫球的潜力很大!首先将的标头更改ff(c,t,l)char*c,*t,*l(不要对返回类型感到讨厌)。
FUZxxl 2015年

@FUZxxl有人在聊天中提到了此内容,但我无法使其正常工作。这是行为标准吗?LLVM在该行上引发至少2个错误。
BrainSteel 2015年

抱歉。应该是f(c,t,l)char*c,*t,*l;。不要在C11模式下编译,因为隐式int规则允许我们删除返回类型,但在该修订版中已将其删除。
FUZxxl 2015年

@FUZxxl它也似乎在C99中失败。实际上,我为编译器设置的每种模式都拒绝了该代码。
BrainSteel

您是否在此之后添加了分号*l?它在我的计算机上以C99模式编译。
FUZxxl 2015年

7

Python 2,316字节

该函数将构建10个tile lambda函数,然后遍历网格以更新逻辑状态。然后打印最终的垂直和水平逻辑状态。

def b(d,j,g):
 h=enumerate;e=dict((s[0],eval('lambda T,L:('+s[1:]+')'))for s in' 0,0#00,0#11,1#+L,T#\\T,L#UT,T#)L,L#!1-L,1-T#&T&L,T&L#|T|L,T|L#^T^L,T^L'.split('#'));j=list(j+'\n');g=list(g)
 for y,k in h(d.split('\n')):
  L=g[y]
  for x,c in h(k):T=j[x];L,B=e[c](int(T),int(L));j[x]=`B`
  g[y]=`L`
 print''.join(j+g)

未经测试的代码包括测试:

def logic(grid, top, left):
    loop = enumerate;
    func = dict((s[0], eval('lambda T,L:('+s[1:]+')')) for s in ' 0,0#00,0#11,1#+L,T#\\T,L#UT,T#)L,L#!1-L,1-T#&T&L,T&L#|T|L,T|L#^T^L,T^L'.split('#'));
    top = list(top+'\n');
    left = list(left)
    for y,row in loop(grid.split('\n')):
        L = left[y]
        for x,cell in loop(row) :
            T = top[x];
            L, B = func[cell](int(T), int(L));
            top[x] = `B`
        left[y] = `L`
    print ''.join(top + left)

import re
testset = open('test.txt', 'rt').read().strip()
for test in testset.split('\n\n'):
    if test.endswith(':'):
        print '------------------\n'+test
    elif re.match('^[01/\n]+$', test, re.S):
        for run in test.split():
            top, left = run.split('/')
            print 'test', top, left
            logic(grid, top, left)
    else:
        grid = test

test.txt文件(包括Sp3000的其他2个测试):

Nand:

&!

00/0
00/1
10/0
10/1

All ones:

1111
1\+\
1+\+
1\+\

1001/1100

Xor from Nand (note the column of trailing spaces):

\)+\ 
U&!& 
+! ! 
\&!& 
   ! 

00000/00000
00000/10000
10000/00000
10000/10000

Half adder:

+))
U&+
U+^

000/000
000/100
100/000
100/100

Right shift:

\\\
\++
\++

001/110
010/101
101/100

测试输出:

------------------
Nand:
test 00 0
01
1
test 00 1
01
1
test 10 0
01
1
test 10 1
11
0
------------------
All ones:
test 1001 1100
1111
1111
------------------
Xor from Nand (note the column of trailing spaces):
test 00000 00000
00000
00000
test 00000 10000
00010
00000
test 10000 00000
00010
00000
test 10000 10000
00000
00000
------------------
Half adder:
test 000 000
000
000
test 000 100
001
101
test 100 000
101
001
test 100 100
110
110
------------------
Right shift:
test 001 110
000
111
test 010 101
101
010
test 101 100
010
110

7

Python 2中,384个 338 325字节

def f(G,T,L):
 def g(x,y):
  if x>-1<y:l=g(x-1,y)[1];t=g(x,y-1)[0];r=l,t,1-l,0,0,1,t,l,l&t,l|t,l^t;i="+\\!0 1U)&|^".index(G[y*-~W+x]);return((t,l,1-t)+r[3:])[i],r[i]
  return(int((y<0)*T[x]or L[y]),)*2
 H=G.count("\n")+1;W=len(G)/H;return eval('"".join(map(str,[g(%s]for _ in range(%s)])),'*2%('_,H-1)[0','W','W-1,_)[1','H'))

认真的CH,如果这还不是玩具,那么您应该开始召集一些玩具工厂。

现在高尔夫运动越来越多,效率越来越低,但是仍然没有赶上CarpetPython。输入像f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010"),输出是两个字符串的元组。确保主板上没有结尾的换行符,否则会造成问题。

测试程序

def f(G,T,L):
 def g(x,y):
  if x>-1<y:l=g(x-1,y)[1];t=g(x,y-1)[0];r=l,t,1-l,0,0,1,t,l,l&t,l|t,l^t;i="+\\!0 1U)&|^".index(G[y*-~W+x]);return((t,l,1-t)+r[3:])[i],r[i]
  return(int((y<0)*T[x]or L[y]),)*2
 H=G.count("\n")+1;W=len(G)/H;return eval('"".join(map(str,[g(%s]for _ in range(%s)])),'*2%('_,H-1)[0','W','W-1,_)[1','H'))


import itertools

G = r"""
+))
U&+
U+^
""".strip("\n")

def test(T, L):
    print f(G, T, L)

def test_all():
    W = len(G[0])
    H = len(G)

    for T in itertools.product([0, 1], repeat=len(G.split("\n")[0])):
        T = "".join(map(str, T))

        for L in itertools.product([0, 1], repeat=len(G.split("\n"))):
            L = "".join(map(str, L))

            print "[T = %s; L = %s]" % (T, L)
            test(T, L)
            print ""

test("000", "000")
test("000", "100")
test("100", "000")
test("100", "100")

您还可以使用来测试所有可能的情况test_all()

额外的测试用例

半加法器

这是一个半加法器,用于将左上角的位相加,输出<input bit> <carry> <sum>

+))
U&+
U+^

测试:

000 / 000  ->  000 / 000
000 / 100  ->  001 / 101
100 / 000  ->  101 / 001
100 / 100  ->  110 / 110

即使输入的第二/第三位发生变化,输出也应该相同。

右移

给定abc / def,此输出fab / cde

\\\
\++
\++

测试:

001 / 110 -> 000 / 111
010 / 101 -> 101 / 010
101 / 100 -> 010 / 110

3位分类器

将top的前三位排序为bottom的后三位。正确的输出是垃圾。

UUU)))
UU)U U
U&UU U
U+|&)U
\UU++|
 \)&UU
  \+|U
   UUU

测试:

000000 / 00000000 -> 000000 / 00000000
001000 / 00000000 -> 000001 / 11111111
010000 / 00000000 -> 000001 / 00001111
011000 / 00000000 -> 000011 / 11111111
100000 / 00000000 -> 000001 / 00001111
101000 / 00000000 -> 000011 / 11111111
110000 / 00000000 -> 000011 / 00001111
111000 / 00000000 -> 000111 / 11111111

2位乘2位乘法器

将top的第1/2位作为第一个数字,top的第3/4位作为第二个数字。输出到底部的最后四位。正确的输出是垃圾。

UUUU))))
UU++)))&
UUU+)  U
UU++&))U
U++&+)^U
U)&\&)UU
   U+^UU
   \&UUU

编辑:打出一列和两行。

测试:

00000000 / 00000000 -> 00000000 / 00000000
00010000 / 00000000 -> 00000000 / 10000000
00100000 / 00000000 -> 00000000 / 00000000
00110000 / 00000000 -> 00000000 / 10000000
01000000 / 00000000 -> 00000000 / 00000000
01010000 / 00000000 -> 00000001 / 11111111
01100000 / 00000000 -> 00000010 / 00000000
01110000 / 00000000 -> 00000011 / 11111111
10000000 / 00000000 -> 00000000 / 00000000
10010000 / 00000000 -> 00000010 / 10000000
10100000 / 00000000 -> 00000100 / 00000000
10110000 / 00000000 -> 00000110 / 10000000
11000000 / 00000000 -> 00000000 / 00000000
11010000 / 00000000 -> 00000011 / 11111111
11100000 / 00000000 -> 00000110 / 00000000
11110000 / 00000000 -> 00001001 / 11111111

1

R,524 517

目前可能有很多空间可以减少这种情况,但是这样做确实很有趣。有两个功能。函数d是工作程序,函数f是比较程序。

函数d由3个字符串Gates,Top和Left调用。将门放入由宽度确定的矩阵中。

I=strtoi;S=strsplit;m=matrix;f=function(L,T,G){O=I(c(0,1,L,T,!L,!T,L&T,L|T,xor(L,T)));X=which(S(' 01+\\U)!&|^','')[[1]]==G);M=m(c(1,1,1,2,1,1,3,2,2,4,3,4,5,4,3,6,4,4,7,3,3,8,5,6,9,7,7,10,8,8,11,9,9),nrow=3);return(c(O[M[2,X]],O[M[3,X]]))};d=function(G,U,L){W=nchar(U);H=nchar(L);U=c(list(I(S(U,'')[[1]])),rep(NA,H));L=c(list(I(S(L,'')[[1]])),rep(NA,W));G=m((S(G,'')[[1]]),nrow=W);for(i in 1:H)for(n in 1:W){X=f(L[[n]][i],U[[i]][n],G[n,i]);L[[n+1]][i]=X[1];U[[i+1]][n]=X[2]};cat(U[[H+1]],' / ',L[[W+1]],sep='',fill=T)}

格式化了一下

I=strtoi;S=strsplit;m=matrix;
f=function(L,T,G){
    O=I(c(0,1,L,T,!L,!T,L&T,L|T,xor(L,T)));
    X=which(S(' 01+\\U)!&|^','')[[1]]==G);
    M=m(c(1,1,1,2,1,1,3,2,2,4,3,4,5,4,3,6,4,4,7,3,3,8,5,6,9,7,7,10,8,8,11,9,9),nrow=3);
    return(c(O[M[2,X]],O[M[3,X]]))
};
d=function(G,U,L){
    W=nchar(U);H=nchar(L);
    U=c(list(I(S(U,'')[[1]])),rep(NA,H));
    L=c(list(I(S(L,'')[[1]])),rep(NA,W));
    G=m((S(G,'')[[1]]),nrow=W);
    for(i in 1:H)
        for(n in 1:W){
            X=f(L[[n]][i],U[[i]][n],G[n,i]);
            L[[n+1]][i]=X[1];
            U[[i+1]][n]=X[2]
        };
    cat(U[[H+1]],' / ',L[[W+1]],sep='',fill=T)
}

一些测试

> d('&!','00','0')
01 / 1
> d('&!','00','1')
01 / 1
> d('&!','10','0')
01 / 1
> d('&!','10','1')
11 / 0
> d('\\)+\\ U&!& +! ! \\&!&    ! ','00000','00000')
00000 / 00000
> d('\\)+\\ U&!& +! ! \\&!&    ! ','00000','10000')
00010 / 00000
> d('\\)+\\ U&!& +! ! \\&!&    ! ','10000','00000')
00010 / 00000
> d('\\)+\\ U&!& +! ! \\&!&    ! ','10000','10000')
00000 / 00000
> d('+++\\00000000000\\!!!!\\00000000000\\+++','000000000000','100')
000000000000 / 001
> d('+++\\00000000000\\!!!!\\00000000000\\+++','000000000000','000')
000000000000 / 000
> d('+))U&+U+^','000','000')
000 / 000
> d('+))U&+U+^','000','100')
001 / 101
> d('+))U&+U+^','100','000')
101 / 001
> d('+))U&+U+^','100','100')
110 / 110
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.