Combinaisons Kakuro

12

Combinaisons Kakuro

Parce que je ne peux pas faire d'arithmétique mentale, j'ai souvent du mal avec le casse- tête de Kakuro , qui oblige la victime à répéter à plusieurs reprises quels nombres distincts compris entre 1 et 9 (inclus) totalisent un autre nombre compris entre 1 et 45 lorsque vous savez comment il y en a beaucoup. Par exemple, si vous voulez savoir comment obtenir 23 à partir de 3 nombres, la seule réponse est 6 + 8 + 9. (C'est la même idée que Killer Sudoku si vous êtes familier avec cela).

Parfois, vous aurez d'autres informations, telles que le nombre 1 ne peut pas être présent, donc pour obtenir 8 en seulement 2 nombres, vous ne pouvez utiliser que 2 + 6 et 3 + 5 (vous ne pouvez pas utiliser 4 + 4, car ils sont non distinct). Alternativement, il se peut que vous ayez déjà trouvé un 3 dans la solution, et donc quelque chose comme 19 en 3 chiffres doit être 3 + 7 + 9.

Votre tâche consiste à écrire un programme qui répertorie toutes les solutions possibles à un problème donné, dans un ordre strict, dans une mise en page stricte.

Contribution

Votre solution peut recevoir les entrées sous la forme d'une seule chaîne ASCII via stdin, un argument de ligne de commande, un argument vers une fonction, une valeur laissée sur la pile ou toute autre folie utilisée par votre langage ésotérique préféré. La chaîne est au format

number_to_achieve number_of_numbers_required list_of_rejected_numbers list_of_required_numbers

Les 2 premiers arguments sont des entiers non négatifs non négatifs de base 10 dans les plages 1 à 45 et 1 à 9 respectivement (l'utilisation d'un point décimal serait une entrée non valide), les deux listes ne sont que des chiffres enchaînés sans aucune délimitation dans pas d'ordre particulier sans répétition, ou '0' s'il s'agit de listes vides. Il ne peut y avoir aucun chiffre partagé entre les listes (à l'exception de 0). Les délimiteurs sont des espaces simples.

Production

Votre sortie doit commencer par une ligne contenant le nombre de solutions possibles. Votre programme doit imprimer des solutions délimitées par des sauts de ligne triées par chaque chiffre de plus en plus significatif, où chaque chiffre est placé à la position qu'il serait si vous listiez les nombres de 1 à 9. Les exemples ci-dessous devraient, nous l'espérons, le clarifier.

Si une entrée non valide est fournie, je me fiche de ce que fait votre programme, même si je préfère qu'il ne remette pas à zéro mon secteur de démarrage.

Exemples

Pour cet exemple d'entrée

19 3 0 0

Le résultat attendu serait

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

Notez les espaces à la place de chaque numéro "manquant", ceux-ci sont obligatoires; Je ne me soucie pas des espaces qui n'ont pas de numéro après eux (comme les 9 manquants ci-dessus). Vous pouvez supposer que tout ce que vous imprimez utilisera une police mono-espace. Notez également l'ordre, où les solutions avec un plus petit chiffre plus petit sont répertoriées en premier, puis celles avec un plus petit chiffre suivant, etc.

Un autre exemple, basé sur celui ci-dessus

19 3 57 9

Le résultat attendu serait

2
 2     89
   4 6  9

Notez que chaque résultat contient un 9 et aucun résultat ne contient un 5 ou 7.

S'il n'y a pas de solutions, par exemple

20 2 0 0

Ensuite, vous devez simplement sortir une seule ligne avec un 0 dessus.

0

J'ai intentionnellement fait l'analyse syntaxique de la partie entrée du plaisir de cette question. C'est le golf de code, que la solution la plus courte l'emporte.

VisualMelon
la source
2
+1 esp. pour "... Je préfère que cela n'ait pas mis à zéro mon secteur de démarrage."
Michael Easter

Réponses:

5

GolfScript, 88 caractères

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

Une implémentation simple dans GolfScript. Prend l'entrée de STDIN ou de la pile.

Le code peut être testé ici .

Code avec quelques commentaires:

### 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
la source
5

JavaScript (E6) 172180275296

En tant que fonction (testable) avec 1 argument de chaîne et renvoyant la sortie demandée. Pour avoir un retour de changement de sortie réel avec alert (), même nombre d'octets, mais attention, la police d'alerte n'est pas 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
}

Tester dans la console FireFox ou 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'))

Sortie de test:

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

Non golfé

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
la source
4

Mathematica, 239 octets

(J'avoue que j'ai commencé à travailler dessus alors qu'il était encore dans le bac à sable.)

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

Non golfé

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

Il s'attend à ce que la chaîne d'entrée soit stockée dans i.

C'est assez simple. Commencez par analyser les entrées. Ensuite, j'utilise IntegerPartitionspour comprendre comment je peux diviser le premier nombre en nombres autorisés. Ensuite, je filtre toutes les partitions qui utilisent des doublons ou ne contiennent pas de numéros requis. Et puis pour chaque solution, je crée une liste de 1à 9et convertis les nombres actuels en leur représentation sous forme de chaîne et les autres en espaces. Et puis je concatène tout.

Martin Ender
la source
1

Groovy - 494 caractères

Grande réponse sans inspiration, mais elle utilise Google Guava pour générer le "power set".

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}

Exemples de cycles:

$ 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

Non 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}
Michael Easter
la source