Choisissez parmi un ensemble de pondérations existant pour faire une somme cible

9

Lorsque je fais de l'haltérophilie, je veux faire un poids spécifique en attachant plusieurs plaques à une barre.

J'ai les plaques suivantes:

  • 6 assiettes de 1 kg chacune
  • 6 assiettes de 2,5 kg chacune
  • 6 assiettes de 5 kg chacune
  • 6 assiettes de 10 kg chacune

La barre elle-même pèse 10 kg.

Il est uniquement permis de fixer les plaques par paires - elles sont fixées à chaque extrémité de la barre, et la disposition aux deux extrémités doit être complètement symétrique (par exemple, en fixant deux plaques de 5 kg à une extrémité et une plaque de 10 kg à l'autre extrémité est interdite pour des raisons de sécurité).

Faites un programme ou une fonction qui me dit combien de plaques de chaque type je dois utiliser pour obtenir un poids total donné. L'entrée est un entier supérieur à 11; la sortie est une liste / tableau / chaîne de 4 nombres. S'il est impossible de combiner des plaques existantes pour obtenir le poids cible, sortez un tableau zéro / vide, une chaîne invalide, lancez une exception ou une telle.

S'il existe plusieurs solutions, le code ne doit en générer qu'une seule (ne faites pas choisir l'utilisateur - il est trop occupé par d'autres choses).

Cas de test:

12 -> [2 0 0 0] - 2 plates of 1 kg plus the bar of 10 kg
13 -> [0 0 0 0] - a special-case output that means "impossible"
20 -> [0 0 2 0] - 2 plates of 5 kg + bar
20 -> [0 4 0 0] - a different acceptable solution for the above
21 -> [6 2 0 0] - 6 plates of 1 kg + 2 plates of 2.5 kg + bar
28 -> [0 0 0 0] - impossible
45 -> [0 2 6 0] - a solution for a random number in range
112 -> [2 4 6 6] - a solution for a random number in range
121 -> [6 6 6 6] - maximal weight for which a solution is possible

Si votre code sort les nombres dans l'ordre inverse (de la plaque lourde à la plaque légère), veuillez le spécifier explicitement pour éviter toute confusion.

anatolyg
la source
1
N'est-ce pas une dupe de la question de comptage de pièces minimum ? Je ne pense pas que le même algorithme gourmand échoue, sauf avec la restriction de 6 d'un même type de plaque. Je pense que ce n'est peut-être pas une différence suffisante, mais je ne suis pas sûr.
FryAmTheEggman
1
L'algorithme gourmand ne fonctionne pas (pas sans modification, au moins) exactement parce que les nombres sont limités
anatolyg
Lié , mais celui-ci est ASCII
AdmBorkBork
Oui, la raison pour laquelle j'ai posté était que je n'étais pas certain que la modification était suffisamment importante. J'ai posté pour essayer d'obtenir des commentaires de la communauté, et je supprimerai mon commentaire s'il semble que la communauté soit en désaccord avec moi.
FryAmTheEggman
Pouvons-nous produire toutes les solutions au lieu d'une seule?
Luis Mendo

Réponses:

5

Gelée , 22 octets

4ṗạµ×2,5,10,20S€+⁵iƓịḤ

Essayez-le en ligne! ou vérifiez tous les cas de test .

Comment ça fonctionne

4ṗạµ×2,5,10,20S€+⁵iƓịḤ  Main link. No arguments

4                       Set the left argument and initial return value to 4.
 ṗ                      Take the Cartesian power of [1, 2, 3, 4] and 4, i.e.,
                        generate all 4-tuples of integers between 1 and 4.
  ạ                     Take the absolute difference of all integers in the
                        4-tuples and the integer 4. This maps [1, 2, 3, 4] to
                        [3, 2, 1, 0] and places [0, 0, 0, 0] at index 0.
   µ                    Begin a new, monadic chain. Argument: A (list of 4-tuples)
     2,5,10,20          Yield [2, 5, 10, 20].
    ×                   Perform vectorized multiplication with each 4-tuple in A.
              S€        Sum each resulting 4-tuple.
                +⁵      Add 10 to each sum.
                   Ɠ    Read an integer from STDIN.
                  i     Find its first index in the array of sums (0 if not found).
                     Ḥ  Unhalve; yield the list A, with all integers doubled.
                    ị   Retrieve the 4-tuple at the proper index.
Dennis
la source
6

MATL , 29 28 octets

4t:qEZ^!"[l2.5AX]@Y*10+G=?@.

Pour les entrées qui n'ont pas de solution, cela produit une sortie vide (sans erreur).

Essayez-le en ligne!

Explication

4           % Push 4
t:q         % Duplicate 4 and transform into range [0 1 2 3]
E           % Multiply by 2: transform into [0 2 4 6]
Z^          % Cartesian power. Each row is a "combination" of the four numbers
!           % Transpose
"           % For each column
  [l2.5AX]  %   Push [1 2.5 5 10]
  @         %   Push current column
  Y*        %   Matrix multiply. Gives sum of products
  10+       %   Add 10
  G=        %   Compare with input: are they equal?
  ?         %   If so
    @       %     Push current column, to be displayed
    .       %     Break loop
            %   Implicit end
            % Implicit end
            % Implicit display
Luis Mendo
la source
5

Mathematica, 70 octets

Select[FrobeniusSolve[{2,5,10,20},2#-20],AllTrue[EvenQ@#&&#<7&]][[1]]&

Fonction anonyme. Prend un nombre en entrée, et génère une liste ou des erreurs et renvoie {}[[1]]s'il n'y a pas de solution.

LegionMammal978
la source
4

Gelée, 25 octets

×2,5,10,20S+⁵⁼³
4ṗ4’ÇÐfḢḤ

Essayez-le ici.

Lynn
la source
2,5,10,20->2,5,⁵,20
Leaky Nun
vraiment ... n'est-ce pas ,une dyade? Toute ma vie est un mensonge
Leaky Nun
@LeakyNun ,est une dyade, mais elle peut également être utilisée pour les littéraux. 2,5,⁵,20n'est pas un littéral cependant ( 2,5et le 20sont, mais ,, et ,sont des atomes), donc vous auriez besoin de quelque chose pour combiner les liens.
Dennis
3

Python 3, 112 octets

lambda n:[i for i in[[i//4**j%4*2for j in range(4)]for i in range(256)]if i[0]+2.5*i[1]+5*i[2]+10*i[3]+10==n][0]

Une fonction anonyme qui prend en entrée, via un argument, la masse cible et renvoie le numéro de chaque plaque sous forme de liste. Si aucune solution n'existe, une erreur est levée. C'est de la force brute pure.

Comment ça fonctionne

lambda n                                   Anonymous function with input target mass n
...for i in range(256)                     Loop for all possible arrangement indices i
[i//4**j%4*2for j in range(4)]             Create a base-4 representation of the index i,
                                           and multiply each digit by 2 to map from
                                           (0,1,2,3) to (0,2,4,6)
[...]                                      Package all possible arrangements in a list
...for i in...                             Loop for all possible arrangements i
i...if i[0]+2.5*i[1]+5*i[2]+10*i[3]+10==n  Return i if it gives the target mass
[...]                                      Package all solutions in a list
:...[0]                                    Return the first list element. This removes any
                                           multiple solutions, and throws an error if there
                                           being no solutions results in an empty list

Essayez-le sur Ideone

TheBikingViking
la source
2

Brachylog , 50 octets

,L##l4,L:{.~e[0:3]}a:[2:5:10:20]*+:10+?,L:{:2*.}a.

Retourne falselorsque cela n'est pas possible.

Fatalize
la source
1

Pyth, 34 31 25 octets

h + fqQ +; s * VT [1 2,5 5;) yMM ^ U4 4] * 4] 0 
yMh + fqQ +; s * VT [2 5; y;) ^ U4 4] * 4] 0
yMhfqQ +; s * VT [2 5; y;) ^ U4 4

Suite de tests.

Erreurs d'impossibilité.

Il s'agit essentiellement d'une force brute.

C'est assez rapide, car il n'y a que 256 dispositions possibles.

Leaky Nun
la source
1

Scala, 202 octets

Décidé que Scala n'a pas beaucoup d'amour ici, donc je présente une solution (probablement pas optimale) dans Scala.

def w(i:Int){var w=Map(20->0,10->0,5->0,2->0);var x=i-10;while(x>0){
var d=false;for(a<-w.keys)if(a<=x & w(a)<6 & !d){x=x-a;w=w.updated(a,w(a)+2);d=true;}
if(!d){println(0);return;}}
println(w.values);}

Le programme sort dans l'ordre inverse et avec des ordures supplémentaires par rapport aux solutions en poste. Lorsqu'une solution n'est pas trouvée, imprime 0.

Remarque: Je n'ai pas pu supprimer les sauts de ligne ou les espaces car Scala est stupide, donc je pense que pour réduire la taille, la méthode doit être refaite à moins que je manque quelque chose d'évident.

ejaszewski
la source
1

APL, 40 octets

{2×(4⍴4)⊤⍵⍳⍨10+2×,⊃∘.+/↓1 2.5 5 10∘.×⍳4}

Dans ⎕IO ← 0. En anglais:

  1. 10+2×,∘.+⌿1 2.5 5 10∘.×⍳4: construire le tableau de tous les poids possibles, en calculant la somme externe 4D des poids par type de poids;
  2. ⍵⍳⍨: recherche l'index du donné. S'il n'est pas trouvé, l'indice est 1 + le décompte du tableau à l'étape 1;
  3. (4⍴4)⊤: représente l'indice en base 4, c'est-à-dire calcule la coordonnée du poids donné dans l'espace 4D;
  4. : amène le résultat à l'espace du problème, où les coordonnées doivent être interprétées comme la moitié du nombre de plaques.

Exemple: {2 × (4⍴4) ⊤⍵⍳⍨10 + 2 ×, ⊃∘. + / ↓ 1 2,5 5 10∘. × ⍳4} 112 2 4 6 6

Bonus : comme APL est un langage de tableau, plusieurs poids peuvent être testés à la fois. Dans ce cas le résultat est transposé:

      {2×(4⍴4)⊤⍵⍳⍨10+2×,⊃∘.+/↓1 2.5 5 10∘.×⍳4}12 13 20 21 28 45 112 121
2 0 0 6 0 0 2 6
0 0 0 2 0 2 4 6
0 0 2 0 0 2 6 6
0 0 0 0 0 2 6 6
lstefano
la source
1

JavaScript (ES6), 109 octets

n=>`000${[...Array(256)].findIndex((_,i)=>i+(i&48)*9+(i&12)*79+(i&3)*639+320==n*32).toString(4)*2}`.slice(-4)

Retourne 00-2sur erreur. Solution alternative qui renvoie undefineden cas d'erreur, également 109 octets:

n=>[...Array(256)].map((_,i)=>`000${i.toString(4)*2}`.slice(-4)).find(s=>+s[0]+s[1]*2.5+s[2]*5+s[3]*10+10==n)
Neil
la source