Kombinasi Kakuro

12

Kombinasi Kakuro

Karena saya tidak dapat melakukan aritmatika mental, saya sering bergumul dengan Puzzle Kakuro , yang mengharuskan korban untuk berulang kali mencari angka yang berbeda di kisaran 1 hingga 9 (termasuk) jumlah ke angka lain di kisaran 1 hingga 45 ketika Anda tahu caranya banyak jumlahnya ada. Misalnya, jika Anda ingin tahu cara mendapatkan 23 dari 3 angka, satu-satunya jawaban adalah 6 + 8 + 9. (Ini adalah ide yang sama dengan Killer Sudoku jika Anda terbiasa dengan itu).

Kadang-kadang Anda akan memiliki informasi lain, seperti bahwa angka 1 tidak dapat hadir, sehingga untuk mencapai 8 hanya dalam 2 angka, Anda hanya dapat menggunakan 2 + 6 dan 3 + 5 (Anda tidak dapat menggunakan 4 + 4, karena mereka adalah tidak berbeda). Atau, mungkin Anda telah menemukan angka 3 dalam solusi, dan sekitar 19 dalam 3 angka harus 3 + 7 + 9.

Tugas Anda adalah menulis program yang mencantumkan semua solusi yang mungkin untuk masalah yang diberikan, dalam urutan yang ketat, dalam tata letak yang ketat.

Memasukkan

Solusi Anda dapat menerima input sebagai string ASCII tunggal baik melalui stdin, argumen baris perintah, argumen ke fungsi, nilai yang tersisa di tumpukan, atau apa pun kegilaan yang dipekerjakan oleh bahasa esoterik favorit Anda. String dalam bentuk

number_to_achieve number_of_numbers_required list_of_rejected_numbers list_of_required_numbers

2 argumen pertama adalah tipikal basis-10 non-negatif bilangan bulat nol di kisaran 1 hingga 45 dan 1 hingga 9 masing-masing (menggunakan titik desimal akan menjadi input yang tidak valid), kedua daftar hanyalah digit yang digantung bersama tanpa batas dalam tidak ada urutan tertentu tanpa pengulangan, atau '0' jika daftar kosong. Tidak boleh ada angka bersama di antara daftar (kecuali untuk 0). Pembatas adalah ruang tunggal.

Keluaran

Output Anda harus mulai dengan garis yang berisi sejumlah solusi yang mungkin. Program Anda harus mencetak solusi batas-batas yang dipisah-pisah yang diurutkan berdasarkan setiap digit yang semakin signifikan, di mana setiap digit ditempatkan pada posisi semestinya jika Anda mencantumkan angka dari 1 hingga 9. Contoh-contoh di bawah ini diharapkan akan membuat ini lebih jelas.

Jika input yang tidak valid diberikan, saya tidak peduli apa program Anda, meskipun saya lebih suka itu tidak nol sektor boot saya.

Contohnya

Untuk input contoh ini

19 3 0 0

Output yang diharapkan adalah

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

Perhatikan spasi di tempat masing-masing nomor "hilang", ini diperlukan; Saya tidak peduli tentang ruang yang tidak memiliki nomor setelah mereka (seperti angka 9 yang hilang di atas). Anda dapat mengasumsikan bahwa apa pun yang Anda cetak akan menggunakan font mono-space. Perhatikan juga urutannya, di mana solusi dengan digit terkecil terkecil didaftar pertama, dan kemudian yang dengan digit terkecil terkecil berikutnya, dll.

Contoh lain, berdasarkan itu di atas

19 3 57 9

Output yang diharapkan adalah

2
 2     89
   4 6  9

Perhatikan bahwa setiap hasil berisi angka 9, dan tidak ada hasil yang mengandung angka 5 atau 7.

Jika tidak ada solusi, misalnya

20 2 0 0

Maka Anda harus menampilkan satu baris dengan 0 di atasnya.

0

Saya sengaja membuat parsing bagian input dari kesenangan dari pertanyaan ini. Ini kode-golf, semoga solusi terpendek menang.

VisualMelon
sumber
2
+1 esp. untuk "... Saya lebih suka itu tidak nol sektor boot saya."
Michael Easter

Jawaban:

5

GolfScript, 88 karakter

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

Implementasi langsung dalam GolfScript. Mengambil input dari STDIN atau stack.

Kode dapat diuji di sini .

Kode dengan beberapa komentar:

### 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
Howard
sumber
5

JavaScript (E6) 172 180 275 296

Sebagai fungsi (dapat diuji) dengan argumen 1 string dan mengembalikan output yang diminta. Untuk mendapatkan perubahan output nyata kembali dengan alert (), jumlah byte yang sama, tetapi waspadalah, font peringatan bukan monospace.

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
}

Tes di FireFox atau konsol 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'))

Hasil tes:

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

Tidak disatukan

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
}
edc65
sumber
4

Mathematica, 239 byte

(Saya akui saya mulai mengerjakan ini saat masih di kotak pasir.)

{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"]<>""

Tidak disatukan

{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"] <> ""

Ia mengharapkan string input untuk disimpan i.

Ini cukup mudah. Pertama, input parsing. Lalu saya gunakan IntegerPartitionsuntuk mencari tahu bagaimana saya bisa membagi angka pertama menjadi angka yang diizinkan. Lalu saya memfilter semua partisi yang menggunakan duplikat atau tidak mengandung angka yang diperlukan. Dan kemudian untuk setiap solusi saya membuat daftar dari 1ke 9dan mengubah angka sekarang menjadi representasi string mereka dan yang lainnya menjadi spasi. Dan kemudian saya menggabungkan semuanya.

Martin Ender
sumber
1

Groovy - 494 karakter

Besar, jawaban tidak terinspirasi, tetapi menggunakan Google Guava untuk menghasilkan "set daya".

Golf:

@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}

Sampel berjalan:

$ 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

Tidak Disatukan:

@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}
Michael Easter
sumber