Combinazioni di Kakuro


12

Combinazioni di Kakuro

Poiché non riesco a fare l'aritmetica mentale, spesso faccio fatica con il Kakuro Puzzle, che richiede alla vittima di elaborare ripetutamente quali numeri distinti nell'intervallo da 1 a 9 (inclusi) si sommano a un altro numero nell'intervallo da 1 a 45 quando sai come ci sono molti numeri. Ad esempio, se vuoi sapere come ottenere 23 da 3 numeri, l'unica risposta è 6 + 8 + 9. (Questa è la stessa idea di Killer Sudoku se hai familiarità con quello).

A volte avrai altre informazioni, come ad esempio che il numero 1 non può essere presente, quindi per ottenere 8 in soli 2 numeri, puoi usare solo 2 + 6 e 3 + 5 (non puoi usare 4 + 4, perché sono non distinto). In alternativa, è possibile che tu abbia già trovato un 3 nella soluzione, quindi qualcosa come 19 in 3 numeri deve essere 3 + 7 + 9.

Il tuo compito è scrivere un programma che elenchi tutte le possibili soluzioni a un determinato problema, in un ordine rigoroso, in un layout rigoroso.

Ingresso

La tua soluzione può ricevere gli input come una singola stringa ASCII tramite stdin, un argomento della riga di comando, un argomento per una funzione, un valore lasciato nello stack o qualunque follia impieghi il tuo linguaggio esoterico preferito. La stringa è nella forma

number_to_achieve number_of_numbers_required list_of_rejected_numbers list_of_required_numbers

I primi 2 argomenti sono interi non-zero non negativi tipici di base 10 rispettivamente negli intervalli da 1 a 45 e da 1 a 9 (l'utilizzo di un punto decimale sarebbe un input non valido), le due liste sono solo cifre messe insieme senza delimitazione in nessun ordine particolare senza ripetizione o "0" se sono elenchi vuoti. Non ci possono essere cifre condivise tra gli elenchi (tranne 0). I delimitatori sono spazi singoli.

Produzione

L'output deve iniziare con una riga che contiene il numero di possibili soluzioni. Il tuo programma deve stampare le soluzioni delimitate da interruzioni di riga ordinate per ogni cifra sempre più significativa, dove ogni cifra è posizionata nella posizione che sarebbe se si elencassero i numeri da 1 a 9. Si spera che gli esempi seguenti lo chiariscano.

Se viene fornito un input non valido, non mi interessa cosa fa il tuo programma, anche se preferirei che non azzerasse il mio settore di avvio.

Esempi

Per questo esempio di input

19 3 0 0

L'output previsto sarebbe

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

Nota gli spazi al posto di ogni numero "mancante", questi sono richiesti; Non mi preoccupo degli spazi che non hanno un numero dopo di loro (come i 9 mancanti sopra). Puoi presumere che qualunque cosa tu stia stampando userà un carattere mono-spazio. Nota anche l'ordinamento, per cui le soluzioni con una cifra più piccola più piccola sono elencate per prime, e poi quelle con una cifra più piccola successiva più piccola, ecc.

Un altro esempio, basato su quello sopra

19 3 57 9

L'output previsto sarebbe

2
 2     89
   4 6  9

Si noti che ogni risultato contiene un 9 e nessun risultato contiene un 5 o 7.

Se non ci sono soluzioni, ad esempio

20 2 0 0

Quindi dovresti semplicemente generare una sola riga con uno 0 su di essa.

0

Ho intenzionalmente reso l'analisi dell'input parte del divertimento di questa domanda. Questo è code-golf, può vincere la soluzione più breve.


2
+1 esp. per "... Preferirei che non azzerasse il mio settore di avvio."
Michael Easter,

Risposte:


5

GolfScript, 88 caratteri

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

Un'implementazione diretta in GolfScript. Riceve input da STDIN o stack.

Il codice può essere testato qui .

Codice con alcuni commenti:

### 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) 172 180 275 296

Come funzione (testabile) con 1 argomento stringa e restituzione dell'output richiesto. Per avere una vera modifica dell'output, tornare con alert (), stesso conteggio byte, ma attenzione, il carattere di avviso non è 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
}

Test nella console FireFox o 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'))

Uscita di prova:

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

Ungolfed

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 byte

(Ammetto di aver iniziato a lavorarci mentre era ancora nella sandbox.)

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

Ungolfed

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

Si aspetta che la stringa di input venga archiviata i.

È abbastanza semplice. Innanzitutto, input di analisi. Quindi uso IntegerPartitionsper capire come posso dividere il primo numero nei numeri consentiti. Quindi filtrerò tutte le partizioni che usano duplicati o che non contengono numeri richiesti. E poi per ogni soluzione a creare un elenco da 1a 9e convertire i numeri presenti nella loro rappresentazione di stringa e le altre in spazi. E poi concateno tutto.


1

Groovy - 494 caratteri

Risposta ampia e non ispirata, ma utilizza Google Guava per generare il "power set".

golfed:

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

Esecuzioni campione:

$ 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

Ungolfed:

@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}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.