Kakuro组合


12

Kakuro组合

因为我无法进行心理算术,所以我经常会遇到“ Kakuro难题”,这需要受害者反复计算出1到9(含)范围内的不同数字加起来到1到45范围内的另一个数字。有很多数字。例如,如果您可能想知道如何从3个数字中获取23,则唯一的答案是6 + 8 +9。(如果您熟悉此方法,则与Killer Sudoku相同)。

有时您还会有其他信息,例如无法显示数字1 ,因此仅用2个数字就获得8,则只能使用2 + 6和3 + 5(不能使用4 + 4,因为它们是不明显)。另外,也可能是您已经在解决方案中找到3,所以像3中19这样的数字必须是3 + 7 + 9。

您的任务是编写一个程序,该程序以严格的顺序和严格的布局列出给定问题的所有可能解决方案。

输入值

您的解决方案可以通过stdin,命令行参数,函数的参数,堆栈上的值或您喜欢的深奥语言所采用的任何疯狂方式,将输入作为单个ASCII字符串接收。字符串形式为

number_to_achieve number_of_numbers_required list_of_rejected_numbers list_of_required_numbers

前两个参数是典型的以10为底的非负非零整数,分别在1到45和1到9的范围内(使用小数点将是无效的输入),这两个列表只是数字串在一起而在没有重复的特定顺序,如果为空列表则为'0'。列表之间不能有共享数字(0除外)。分隔符是单个空格。

输出量

您的输出必须以包含可能的解决方案数量的一行开头。您的程序必须打印出以换行符分隔的解决方案,这些解决方案按每个递增的有效数字进行排序,其中每个数字都位于您列出从1到9的数字的位置。下面的示例有望使这一点更加清楚。

如果提供了无效的输入,我不在乎您的程序会做什么,尽管我希望它不会将引导扇区清零。

例子

对于此示例输入

19 3 0 0

预期的输出将是

5
 2     89
  3   7 9
   4 6  9
   4  78 
    56 8 

注意每个“缺失”数字的空格,这些是必需的;我不担心空格后面没有数字的空格(例如上面缺少的9)。您可以假定要打印的内容将使用等宽字体。还要注意排序,即首先列出具有较小最小数字的解决方案,然后列出具有最小第二个最小数字的解决方案,依此类推。

另一个例子,基于上面的例子

19 3 57 9

预期的输出将是

2
 2     89
   4 6  9

请注意,每个结果都包含9,没有结果包含5或7。

例如,如果没有解决方案

20 2 0 0

然后,您应该只输出一行0。

0

我故意将输入部分的解析作为此问题的乐趣。这是代码问题,可能是最短的解决方案。


2
+1特别是 为“ ...我希望它没有将我的引导扇区清零。”
2014年

Answers:


5

GolfScript,88个字符

~[[]]10,:T{{1$+}+%}/\{\0+`-!}+,\{0`+\`&!}+,\{\,=}+,\{\{+}*=}+,.,n@{1T>''*T@-{`/' '*}/n}/

GolfScript中的直接实现。从STDIN或堆栈获取输入。

可以在这里测试代码。

带有一些注释的代码:

### evaluate the input string
~                     

### build all possible combinations of 0...9
[[]]              # start with set of empty combination
10,:T             #
{                 # for 0..9
  {1$+}+%         #   copy each item of set and append current digit to this copy
}/                # end for

### only keep combination which the digits given as last argument (minus 0)
\{                # start of filter block
  \0+`            #   add zero to combination and make string out of it
  -!              #   subtract from last argument -> check argument contains any
                  #     excess characters
}+,               # end of filter block


### remove any combination which contains either 0 or any digit from 2nd last argument
\{                # start of filter block
  0`+             #   take argument and append 0
  \`              #   stringify combination
  &!              #   check if no characters are common
}+,               # end of filter block

### filter for correct length
\{                # start of filter block
  \,              #   calc length of combination
  =               #   check if equal to second argument
}+,               # end of filter block

### filter for correct sum
\{                # start of filter block
  \{+}*           #   sum all digits of combination
  =               #   compare with first argument
}+,               # end of filter block

### output
.,                # determine size of set
n                 # append newline
@{                # for each combination in set
  1T>''*          #   generate "123456789"
  T@-             #   generate anti-set of current combination  
  {`/' '*}/       #   replace (in the string) each digit within the 
                  #   anti-combination with a space characters
  n               #   append newline
}/                # end for

5

JavaScript(E6)172180275296

作为具有1个字符串参数并返回请求的输出的(可测试)函数。要使用alert()具有相同的字节数返回真实的输出更改返回值,但是请注意,警报字体不是等宽字体。

F=i=>{
  [t,d,f,m]=i.split(' ');
  for(l=0,r='',k=512;--k;!z&!h&!o&&(++l,r+=n))
    for(z=n='\n',h=d,o=t,b=i=1;i<=9;b+=b)
      z-=~(b&k?(--h,o-=i,n+=i,f):(n+=' ',m)).search(i++);
  return l+r
}

在FireFox或FireBug控制台中测试

console.log(['19 3 0 0','19 3 57 9','19 3 57 4','20 2 0 0'].map(x=>'\n'+x+'\n' +F(x)).join('\n'))

测试输出:

19 3 0 0
5
 2     89
  3   7 9
   4 6  9
   4  78 
    56 8 

19 3 57 9
2
 2     89
   4 6  9

19 3 57 4
1
   4 6  9

20 2 0 0
0

不打高尔夫球

F=i=>{
  [target, digits, forbidden, mandatory]=i.split(' ')

  result = '', nsol=0
  for (mask = 0b1000000000; --mask > 0;)
  {
    cdigits = digits
    ctarget = target
    bit = 1
    numbers = ''
    for (digit = 9; digit > 0; bit += bit, digit--)
    {

      if (bit & mask)
      {
        if (forbidden.search(digit)>=0) break;
        cdigits--;
        ctarget -= digit;
        numbers = digit + numbers;
      }
      else
      {
        if (mandatory.search(digit)>=0) break;
        numbers = ' '+numbers;
      }
    }
    if (ctarget==0 && cdigits == 0)
    {
        result += '\n'+numbers
        nsol++
    }
  }
  return nsol + result
}

4

Mathematica,239个字节

(我承认我仍在沙盒中时开始进行此工作。)

{t,n,a,b}=FromDigits/@StringSplit@i;Riffle[c=Cases[Union/@IntegerPartitions[t,n,Complement[r=Range@9,(d=IntegerDigits)@a]],k_/;(l=Length)@k==n&&(b==0||l[k⋂d@b]>0)];{(s=ToString)@l@c}~Join~((m=#;If[m~MemberQ~#,s@#," "]&/@r)&/@c),"\n"]<>""

不打高尔夫球

{t, n, a, b} = FromDigits /@ StringSplit@i;
Riffle[
  c = Cases[
    Union /@ IntegerPartitions[
      t, n, Complement[r = Range@9, (d = IntegerDigits)@a
       ]
      ],
    k_ /; (l = Length)@k == 
       n && (b == 0 || l[k ⋂ d@b] > 0)
    ];
  {(s = ToString)@l@c}~
   Join~((m = #; If[m~MemberQ~#, s@#, " "] & /@ r) & /@ c),
  "\n"] <> ""

它期望输入字符串存储在中i

这很简单。首先,输入解析。然后,我IntegerPartitions要弄清楚如何将第一个数字分成允许的数字。然后,我过滤掉所有使用重复或不包含必需数字的分区。然后为每个解决方案创建一个从1到的列表9,并将当前数字转换为它们的字符串表示形式,将其他数字转换为空格。然后,我将所有内容连接在一起。


1

Groovy-494个字符

大的,没有启发性的答案,但是它使用Google Guava生成“功率集”。

打高尔夫球:

@Grab(group='com.google.guava', module='guava', version='17.0')
m=(args.join(" ")=~/(\d+) (\d+) (\d+) (\d+)/)[0]
i={it as int}
n=i(m[1])
r=i(m[2])
j=[]
m[3].each{if(i(it))j<<i(it)}
q=[]
m[4].each{if(i(it))q<<i(it)}
d=1..9 as Set<Integer>
t=[]
com.google.common.collect.Sets.powerSet(d).each{x->
if(x.sum()==n&&x.size()==r&&x.disjoint(j)&&x.containsAll(q)) {
s="";for(i in 0..8){if(x.contains(i+1)){s+=(i+1) as String}else{s+=" "}};t<<s}
}
p={println it}
p t.size()
t.sort().reverse().each{p it}

样品运行:

$ groovy K.groovy 19 3 0 0 
5
 2     89
  3   7 9
   4 6  9
   4  78 
    56 8 
$ groovy K.groovy 19 3 5 0 
4
 2     89
  3   7 9
   4 6  9
   4  78 
$ groovy K.groovy 19 3 5 9
3
 2     89
  3   7 9
   4 6  9
$ groovy K.groovy 20 2 0 0 
0

取消高尔夫:

@Grab(group='com.google.guava', module='guava', version='17.0')

m=(args.join(" ")=~/(\d+) (\d+) (\d+) (\d+)/)[0]
i={it as int}
n=i(m[1])
r=i(m[2])

j=[]
m[3].each{if(i(it))j<<i(it)}
q=[]
m[4].each{if(i(it))q<<i(it)}

d=1..9 as Set<Integer>
t=[]

com.google.common.collect.Sets.powerSet(d).each{ x ->
    if(x.sum()==n && x.size()==r && x.disjoint(j) && x.containsAll(q)) {
        s=""
        for(i in 0..8) {
            if(x.contains(i+1)){s+=(i+1) as String}else{s+=" "}
        }
        t<<s
    }
}

p={println it}
p t.size()
t.sort().reverse().each{p it}
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.