二元解算器


10

介绍

拼图规则:

谜题Binary(也称为Takuzu或Subiku)很容易理解,并且只有几个规则:
由于游戏的名称是二进制,所以很明显,但是只能填充零和一。

  1. 同一数字最多只能垂直或水平相邻
  2. 每行和每一列必须包含相等数量的零和一(这意味着每个二进制游戏都将始终具有偶数维)。
  3. 可能没有重复的行,也没有重复的列(零和一的顺序完全相同)。

如果愿意,可以在www.binarypuzzle.com上玩游戏。

策略:

根据规则1,在以下情况下,我们始终可以填充数字:
-同一位数字中已有两个彼此垂直或水平相邻,在这种情况下,我们可以在两侧填充相对的数字。即.11...0110..
-在垂直或水平方向上有两个相同的数字,它们之间只有一个间隙。即.1.1...101..

根据规则1,当剩下三个空格并且我们不能有三个相邻的相同数字时,我们可以填充其中一个空格。即.0.1.010.1.0(我们仍然必须填写两个,而且中间不能有三个相邻的,所以第一个间隙必须是a 1。)

根据规则2,如果一半的空白已经用相反的数字填充,那么我们总是可以填充行或列中的剩余空白。即.1.011010011

根据规则3,如果在相等顺序的行上只剩下两个要求解的数字,我们总是可以填充相反的数字。即101100 & 1..100101100 & 110100

根据规则3,有时我们可以在一条有序排列的直线上留出三个间隙时填充一个间隙。即010011 & .1.01.010011 & .1.010(此处我们不能在1末尾填写a ,因为这意味着我们必须在其他两个空白处填充零,使两行顺序相等。)

例:

我们从以下6x6网格开始,其中填充了一些1和0(点是我们尚未填充的间隙):

.1....
.10.0.
1.11..
.1....
...1.0
......

根据规则1和2,我们可以填写以下数字:

.1.01.
.1010.
101100
010011
.0.1.0
.010..

根据规则1,我们可以在第5行第1列中填写1:

.1.01.
.1010.
101100
010011
10.1.0
.010..

根据规则3,我们可以在第1行第6列(当查看第4行时)填写0:

.1.010
.1010.
101100
010011
10.1.0
.010..

现在,由于规则1和2,我们可以继续用数字来填补空白。

.1.010
010101
101100
010011
10.1.0
.010.1

现在,根据规则3(在查看第3行时),我们可以完成第5行:

.1.010
010101
101100
010011
100110
.010.1

然后,根据规则1和规则2,我们可以完成难题:

011010
010101
101100
010011
100110
101001

挑战:

挑战很简单:给定起始网格,输出已解决的难题。

注意:您不必执行上述规则。您当然可以,并且它应该为您提供有关如何实施此挑战的提示,但是考虑到规则对解决方案进行暴力破解完全可以。
如何解决问题取决于您,但是挑战在于输出已解决的难题。

挑战规则:

  • 网格的输入和输出格式很灵活,但请说明您使用的格式。(即2D字节数组;带换行符的字符串;等等。)
  • 上面的内容也适用于所使用的字符。在示例中,我使用01.,但是如果您愿意,可以ABx改用。请说明您使用的输入/输出格式和字符。
  • 你可以假设仅将用于以下网格大小:6x6; 8x8; 10x10; 12x12; 14x14; 16x16

通用规则:

  • 这是,因此最短答案以字节为单位。
    不要让代码高尔夫球语言阻止您使用非代码高尔夫球语言发布答案。尝试针对“任何”编程语言提出尽可能简短的答案。
  • 标准规则适用于您的答案,因此允许您使用STDIN / STDOUT,具有适当参数的函数/方法,完整程序。您的来电。
  • 默认漏洞是禁止的。
  • 如果可能的话,请添加一个带有测试代码的链接。
  • 另外,如有必要,请添加说明。

测试用例:

添加这些点只是为了提高可读性,您可以随意使用空格或其他任何您喜欢的空格。输入和输出格式都很灵活。

Input:
1..0..
..00.1
.00..1
......
00.1..
.1..00

Output:
101010
010011
100101
011010
001101
110100

Input:
.1....
.10.0.
1.11..
.1....
...1.0
......

Output:
011010
010101
101100
010011
100110
101001

Input:
.......1..
.00..0..1.
.0..1..0.0
..1...1...
1.1......1
.......1..
.0..1...0.
....11...0
.0.0..1..0
0...0...1.

Output:
0110010101
1001100110
1001101010
0110011001
1010100101
0101010110
1001101001
0110110100
1010011010
0101001011


Answers:


4

Brachylog,34个字节

{ℕ<2}ᵐ²&≜{d?ọᵐctᵐ=&{ḅlᵐ⌉<3}ᵐ}&\↰₂&

在线尝试!

这真是太慢了,所以TIO上的测试用例是4x4。我目前正在计算机上运行6x6测试用例,以查看需要花费多少时间。

这将列表列表作为输入。未知值应该用变量表示,即用全大写的字符串表示(并且它们都应该是不同的,否则您将指示某些单元格必须具有相同的值)

说明

我们将值限制在中{0,1},然后尝试实例化变量,直到其中一个遵守所有3条规则。这就是为什么它这么慢的原因(因为它将尝试所有方法直到找到一个;并且因为在这种情况下,Brachylog的实现不够好,因此可以在尝试可能的矩阵之前施加约束)。

                                 &  Output = Input
{   }ᵐ²                             Map two levels on the Input (i.e. each cell):
 ℕ<2                                  The cell is either 0 or 1
       &≜                           Assign values to all cells
         {                  }       Define predicate 2:
          d?                          The Input with no duplicates is still the Input
                                        (i.e. all rows are different)
           ?ọᵐctᵐ=                    All occurences of 1s and 0s for each rows are equal
                  &{      }ᵐ          Map on rows:
                    ḅlᵐ                 Get the lengths of runs of equal values
                       ⌉<3              The largest one is strictly less than 3
                             &\↰₂   Apply predicate 2 on the transpose of the Input
                                      (i.e. do the same checks but on columns)

出于好奇,Brachylog如何显示大写字母以外的变量?因此,假设您的解决方案可以更快地运行,它将无法使用Athrough YZ作为输出参数)填充14x14网格上的所有空白区域。是否继续AAAB等?
凯文·克鲁伊森

2
@KevinCruijssen任何全大写标识符都是变量,因此yes AA是变量,KEVINCRUIJSSEN也是变量。
致命一战

3
正如我所怀疑的,对于Brachylog来说是一个挑战:D
乔纳森·艾伦

3

的JavaScript(ES6),274个 270字节

将输入作为2D数组,其中空单元格用标记2。将所有可能的解决方案打印到控制台。

f=(a,x=0,y=0,w=a.length,p,R=a[y])=>(M=z=>!a.some((r,y)=>/(0|1),\1,\1/.exec(s=r.map((v,x)=>(v=z?v:a[x][y],b-=v&1,c-=!v,m|=v&2,v),b=c=w/2))||b*c<0|o[b*c||s]&(o[s]=1),o={}))(m=0)&M(1)&&(m?R&&[0,1].map(n=>(p=R[x])==n|p>1&&(R[x]=n,f(a,z=(x+1)%w,y+!z),R[x]=p)):console.log(a))

怎么运行的

代码的第一部分使用该M()功能在水平和垂直方向上检查当前板的有效性。

M = z =>
  !a.some((r, y) =>
    /(0|1),\1,\1/.exec(
      s = r.map((v, x) =>
        (
          v = z ? v : a[x][y],
          b -= v & 1,
          c -= !v,
          m |= v & 2,
          v
        ),
        b = c = w / 2
      )
    ) ||
    b * c < 0 |
    o[b * c || s] &
    (o[s] = 1),
    o = {}
  )

它将完整的行或列映射到字符串s。这实际上是强制转换为字符串的数组,因此看起来像"1,2,2,0,2,2"

它用:

  • /(0|1),\1,\1/用于检测3个或更多连续相同数字的正则表达式。
  • 计数器bc跟踪10的数量。每次遇到一个1或一个0时,两个计数器都初始化为w / 2,并递减。这导致:
    • b = c = 0 b * c = 0 →这行是完整且正确的( 1一样多)
    • B> 0 AND C> 0 B * C> 0 →行是不完整的,但到目前为止,正确的是(我们没有超过 W / 2 或大于 W / 2 的人
    • b <0或c <0 b * c <0 →该行无效
  • 如果板上至少有两个余数,则标志m(表示“丢失”)不为零。
  • 对象o跟踪到目前为止遇到的所有线型。

如果董事会无效,我们将立即停止。如果该板有效且完整,则将其打印到控制台。否则,代码的第二部分将尝试使用或用递归调用将1替换为2

[0, 1].map(n =>
  (p = a[y][x]) == n |
  p > 1 && (
    a[y][x] = n,
    f(a, z = (x + 1) % w, y + !z),
    a[y][x] = p
  )
)

演示版


感谢您添加解释。我喜欢您如何打印所有可能的输出,而不仅仅是一个!
凯文·克鲁伊森

1
@KevinCruijssen这可能远非最佳,但写起来很有趣。好挑战!
Arnauld

1

果冻53 51 字节

ṡ€3ḄFf0,7L
SḤnLṀȯÇ
⁻QȯÇ
Fṣ©2L’0,1ṗż@€®F€s€LÇÐḟZÇ$Ðḟ

采用代表网格列表,包含列表012(空格)。返回列表列表的列表,每个列表列表的格式相同(尽管没有2s),并且表示输入的可能解决方案。

在线尝试!(由于内存限制,这将不会运行任何问题的测试用例-所有2个 nSpaces网格都将作为整数列表的列表创建-但我在单个解决方案中放了一个相对较重的用例)。页脚分开并格式化网格。

纯蛮力方法-实施规则并检查将每个2s 替换为1s或0s 可能形成的每个网格的规则。

ṡ€3ḄFf0,7L - Link 1, # of runs of 3 1s or 3 0s by row: list of lists
ṡ€3        - all contiguous slices of length 3 for €ach list
   Ḅ       - convert all results from binary
    F      - flatten into one list
     f     - filter keep values in:
      0,7  -   0 paired with 7: [0,7]
         L - length

SḤnLṀȯÇ - Link 2, unequal counts of 1s and 0s by column ...or link 1: list of lists
S       - sum (vectorises, hence "by column", counts 1s since only 1s or 0s appear)
 Ḥ      - double
   L    - length (number of rows - OK since square)
  n     - not equal? (vectorises)
    Ṁ   - maximum (1 if any not equal)
     ȯÇ - ... or last link (1) as a monad

⁻QȯÇ - Link 3, rows are unique ...or link 2: list of lists
 Q   - unique
⁻    - not equal?
  ȯÇ - ... or last link (2) as a monad

Fṣ©2L’0,1ṗż@€®F€s€LÇÐḟZÇ$Ðḟ - Main link: list of lists
F                           - flatten
 ṣ©2                        - split at 2s and copy the result to the register
    L                       - length (# of such slices)
     ’                      - decrement (# of 2s)
      0,1                   - 0 paired with 1
         ṗ                  - Cartesian power (all binary lists of length # of 2s)
             ®              - recall value from register (the flat version split at 2s)
          ż@€               - zip (reversed @rguments) for €ach (1s & 0s where 2s were)
              F€            - flatten €ach
                s€L         - split €ach into chunks of length length(input) (into rows)
                    Ðḟ      - filter discard if:
                   Ç        -   call last link(3) as a monad
                         Ðḟ - filter discard if:
                        $   -   last two links as a monad:
                      Z     -     transpose
                       Ç    -     call last link(3) as a monad
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.