Mettre en œuvre des opérations de sac

20

Un sac , également appelé multiset, est une collection non ordonnée. Vous pouvez l'appeler un ensemble qui autorise les doublons, ou une liste (ou un tableau) qui n'est pas ordonnée / indexée. Dans ce défi, il vous est demandé de mettre en œuvre des opérations de sacs: addition, différence, multiplication, division, comptage et test d'égalité.

Les opérations

Les opérations spécifiées peuvent ne pas être conventionnelles.

  • addition combine deux sacs en un, conservant le nombre total de chaque valeur
    [1,2,2,3] + [1,2,4] = [1,1,2,2,2,3,4]
  • la différence supprime d'un sac chaque élément d'un autre sac, ou ne fait rien si aucun de ces éléments
    [1,2,2,4] - [1,2] = [2,4] [1,2,3] - [2,4] = [1,3]
  • la multiplication multiplie chaque élément du sac.
    [1,2,3,3,4] * 3 = [1,1,1,2,2,2,3,3,3,3,3,3,4,4,4] 2 * [1,3] = [1,1,3,3]
  • la division est rare: chaque élément n égal est placé dans n nouveaux sacs égaux, les éléments qui ne peuvent pas former un groupe n restent dans le sac. Retournez l'un des n nouveaux sacs.
    [1,1,2,2,2] / 2 = [1,2] [1,2,2,3,3,3] / 3 = [3]
  • compter compter combien de sacs diviseurs peuvent être produits à partir du sac de dividendes
    [1,1,2,2,2,2,3,3,3] c [1,2,3] = 2
  • test d'égalité vérifie si deux sacs ont le même numéro de chaque élément
    [1,2,2,3] == [3,2,1,2] = truthy [1,2,3] == [1,2,2,3] = falsy(peut également être utilisé =pour cela)

Si vous utilisez vos propres symboles pour les opérateurs, veuillez préciser.

Les formats

Les sacs seront affichés sous forme de listes du formulaire [1,1,2,3,4]. Vous pouvez utiliser n'importe quel autre support que les carrés, ou même utiliser des guillemets, ou rien du tout. Les éléments seront des entiers (mathématiquement, pas nécessairement int) aux fins de cette question. Les sacs n'ont pas besoin d'être triés.

Le format d'entrée sera deux sacs ou un sac et un entier, avec un opérateur. Vous pouvez spécifier votre propre format tant qu'il contient ces trois formats.

Le format de sortie doit être un seul sac du même format.

Règles

  • vous ne pouvez pas utiliser de fonctions, d'opérations ou de bibliothèques intégrées (y compris la bibliothèque standard) qui les mettent déjà en œuvre; il est cependant correct d'utiliser la concaténation et la multiplication de listes, car ce sont par définition des opérations de liste, et non des opérations de sac (qui font essentiellement la même chose)
  • les échappatoires standard s'appliquent
  • réponse la plus courte gagne

Cas de test

[1,2,2,3] + [1,2,4]
[1,1,2,2,2,3,4]

[1,2,2,4] - [1,2]
[2,4]

[1,2,3] - [2,4]
[1,3]

[1,2,3,3,4] * 3
[1,1,1,2,2,2,3,3,3,3,3,3,4,4,4]

2 * [1,3]
[1,1,3,3]

[1,1,2,2,2] / 2
[1,2]

[1,2,2,3,3,3] / 3
[3]

[1,1,2,2,2,2,3,3,3] c [1,2,3]
2

[3,2,1,2] == [1,2,2,3]
truthy

[1,2,3] == [1,2,2,3]
falsy
busukxuan
la source
2
Peut-être assouplir le format d'entrée? Par exemple, permet de prendre le sac, le sac / numéro et l'opérateur comme arguments séparés, ou dans un format libre. Sinon, une partie importante du défi consiste à analyser l'entrée, ce qui n'est pas particulièrement intéressant
Luis Mendo
@LuisMendo split-on-space est suffisant pour analyser cela, si vous avez un langage qui peut évaluer les chaînes comme des listes, ne pensez-vous pas? Je n'ai pas d'expérience dans la publication de défis, alors s'il vous plaît, éclairez-moi :-)
busukxuan
Je n'ai pas trouvé de méta post pertinent, mais voyez par exemple le libellé ici : vous pouvez lire l'entier comme sa représentation décimale, une représentation unaire (en utilisant un caractère de votre choix), un tableau d'octets (grand ou petit endian) ou un octet unique (s'il s'agit du plus grand type de données de votre langue) . Ou ici : les formats d'entrée et de sortie sont flexibles comme d'habitude (tableaux, listes, liste de listes, chaînes avec des séparateurs raisonnables, etc. ).
Luis Mendo
@LuisMendo c'est fondamentalement gratuit maintenant. Et à propos de l'entier, je voulais juste dire que dans le sens mathématique, pas le type de données.
busukxuan
1
@LuisMendo nope, les symboles doivent avoir du sens, même si ce n'est qu'un petit peu. Eh bien, vous pouvez utiliser un = pour le test d'égalité.
busukxuan

Réponses:

3

05AB1E, 92 87 83 82 77 octets

>i‚˜,}¹iи˜Qis}GD})˜,}¹<i³v²y¢O}){0è,}¹Íi{s{Q,}¹Í<iÙv²y¢O³‹_iy}}),}svy†¬yQi¦}}

Division par opération

>i                      # if 0
  ‚˜,}                  # addition
¹i                      # if 1
  и˜Qis}GD})˜,}        # multiplication
¹<i                     # if 2
   ³v²y¢O}){0è,}        # count
¹Íi                     # if 3
   {s{Q,}               # equality
¹Í<i                    # if 4
   Ùv²y¢O³÷Fy}}),}      # division
                        # else
   svy†¬yQi¦}}          # difference

Explication

Une addition

‚˜,}

Mettez un sac dans un autre et aplatissez-les dans un sac.

Multiplication

и˜Qis}

Assurez-vous que le numéro est en haut de la pile. Appelez cela X.

GD})˜,}

Dupliquez le sac X fois et joignez-le à un sac.

Compter

³v²y¢O}){0è,}

Pour chaque élément du sac diviseur, comptez le nombre d'occurrences dans le sac de dividendes.
Le nombre minimum sera le nombre de sacs que nous pouvons faire.

Égalité

 {s{Q,}

Triez les deux sacs et vérifiez s'ils sont égaux.

Division

Ùv²y¢O³÷Fy}}),}

Comptez le nombre de fois que chaque élément unique se produit dans le sac.
Si cela se produit au moins autant de fois que le diviseur. Gardez (nr_of_copies_total // divisor) des copies dans le sac.

Différence

svy†¬yQi¦}} 

Pour chaque élément du subtrahend, triez-le à l'avant du minuend.
Si le subtrahend actuel est égal au premier élément du minuend, supprimez-le du minuend.

Emigna
la source
9

APL (155)

∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕

Ceci définit un «sac» d' opérateur , qui définit les opérations de sac pour des fonctions données. C'est à dire+∆ serait l'addition. Il lit ensuite une ligne du clavier et l'évalue comme une expression APL.

Les fonctions sont:

  • +∆, une addition
  • -∆, soustraction
  • ×∆, multiplication
  • ÷∆, division
  • ⊂∆, en comptant
  • ≡∆, équivalence (bien qu'en raison du golf, toute fonction non reconnue fera l'équivalence)

Explication:

  • ∆←{... }: définir un opérateur :

    • O←⍺⍺: stocke la fonction donnée dans O( ⎕CRne fonctionnera pas ⍺⍺directement avec )
    • O←⎕CR'O': obtenir la représentation sous forme de chaîne de cette fonction
    • '+'=O... :: pour addition,
      • ⍺,⍵: joindre les deux listes ensemble
      • R[⍋R←... ]: et trier le résultat
    • '-'=O:: pour la soustraction,
      • ⍺{... }⍵: exécutez la fonction récursive suivante:
        • ⍵≡⍬:⍺: si le subtrahend est vide, retourne le minuend
        • ⍺/⍨(⍳⍴⍺)≢⍺⍳⊃⍵∇1↓⍵: sinon, supprimez le premier élément du subtrahend du subtrahend et du minuend et réessayez
    • (⍬=⍴⍵)∧K←'×'=O: pour la multiplication, et si le bon argument n'est pas un sac:
      • ⍵/⍺: réplique chaque élément de l'argument de gauche par l'argument de droite
    • K:: ... et si le bon argument est un sac:
      • ⍺/⍵: réplique chaque élément de l'argument de droite par l'argument de gauche (c'est pour que la multiplication soit commutative)
    • '÷'=O:: pour la division,
      • ⍵≤⍺∘.+⍺: voir quels éléments dans ⍺ se produisent au moins ⍵ fois,
      • ⍺/⍨: sélectionnez ceux parmi ⍺,
      • : et supprimez tous les doublons de cette liste
    • '⊂'=O:: pour compter,
      • ⍵{... }⍺: exécutez la fonction récursive suivante:
        • (∪⍺)≢∪⍵:0: si une liste contient des éléments que l'autre ne contient pas, le résultat est 0
        • 1+⍺∇⍵-∆⍺: sinon, soustrayez le dividende du diviseur, réessayez et incrémentez le résultat.
    • : si rien de ce qui précède, faites le test d'équivalence:
      • ⍺[⍋⍺]≡⍵[⍋⍵]: trier les deux listes et voir si elles sont égales
  • : lire une expression à partir du clavier, l'évaluer et afficher le résultat.

Cas de test:

      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      1 2 2 3 +∆ 1 2 4
1 1 2 2 2 3 4
      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      1 2 2 4 -∆ 1 2
2 4
      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      1 2 3 -∆ 2 4
1 3
      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      1 2 3 3 4 ×∆ 3
1 1 1 2 2 2 3 3 3 3 3 3 4 4 4
      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      2 ×∆ 1 3
1 1 3 3
      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      1 1 2 2 2 ÷∆ 2
1 2
      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      1 2 2 3 3 3 ÷∆ 3
3
      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      1 1 2 2 2 2 3 3 3 ⊂∆ 1 2 3
2
      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      3 2 1 2 ≡∆ 1 2 2 3
1
      ∆←{O←⍺⍺⋄'+'=O←⎕CR'O':R[⍋R←⍺,⍵]⋄'-'=O:⍺{⍵≡⍬:⍺⋄(⍺/⍨(⍳⍴⍺)≠⍺⍳⊃⍵)∇1↓⍵}⍵⋄(⍬≡⍴⍵)∧K←'×'=O:⍵/⍺⋄K:⍺/⍵⋄'÷'=O:∪⍺⌿⍨⍵≤+/⍺∘.=⍺⋄'⊂'=O:⍵{(∪⍺)≢∪⍵:0⋄1+⍺∇⍵-∆⍺}⍺⋄⍺[⍋⍺]≡⍵[⍋⍵]}⋄⎕
⎕:
      1 2 3 ≡∆ 1 2 2 3
0
marinus
la source
Solution vraiment professionnelle et grande rédaction! +1
Votre rédaction et explication est vraiment solide! Une chose, cependant: pour la division, je crois que la spécification est formulée d'une manière qui [2,2,2,2,2,2]/3devrait donner [2,2], mais la vôtre semble donner [2].
Value Ink
Vous n'avez pas besoin de coder le REPL. Si vous venez de définir , l'utilisateur sera vidé dans le REPL natif d'APL, où il est maintenant valide. Je pense que vous pouvez économiser quelques octets en déplaçant la soustraction à la fin car c'est la seule qui nécessite deux lignes. Au lieu de ⎕CR, utilisez *pour symboliser count, et faire O←⍺⍺2, puis 2=O:pour plus, 1=Opour mult, 0=O:pour equiv, 7<O:pour count et 0<O:pour div (avec implicite 0>O:pour subtr).
Adám
6

JavaScript (ES6), 260 octets

(x,o,y,a=a=>a.reduce((r,e,i)=>[...r,...Array(e).fill(i)],[]),b=(a,r=[])=>a.map(e=>r[e]=-~r[e])&&r)=>[z=>a(b(y,z)),z=>y.map(e=>z[e]&&z[e]--)&&a(z),z=>a(z.map(e=>e*y)),z=>a(z.map(i=>i/y|0)),z=>b(y).map((e,i)=>r=Math.min(r,z[i]/e),r=1/0)|r,z=>``+z==b(y)][o](b(x))

Prend 3 paramètres. Le premier paramètre est un tableau, le second est un opérateur, le troisième dépend de l'opérateur. Les sacs doivent contenir des entiers non négatifs.

[...] 0 [...] -> addition
[...] 1 [...] -> difference
[...] 2 <n> -> multiplication
[...] 3 <n> -> division
[...] 4 [...] -> counting
[...] 5 [...] -> equality

Non golfé:

function do_bag_op(lhs, op, rhs) {
    function bag2array(bag) {
        return bag.reduce(function (result, entry, index) {
            return result.concat(Array(entry).fill(index));
        }, []);
    }
    function array2bag(array, bag) {
        if (!bag) bag = [];
        array.forEach(function (entry) {
            if (bag[entry]) bag[entry]++;
            else bag[entry] = 1;
        }
        return bag;
    }
    var bag = array2bag(lhs);
    switch (o) {
    case 0: // addition
        return bag2array(array2bag(rhs, bag));
    case 1: // difference
        rhs.forEach(function(entry) {
            if (bag[entry]) bag[entry]--;
        });
        return bag2array(bag);
    case 2: // multiplication
        return bag2array(bag.map(function (entry) {
            return entry * rhs;
        }));
    case 3: // division
        return bag2array(bag.map(function (entry) {
            return Math.floor(entry / rhs);
        }));
    case 4: // counting
        return Math.floor(array2bag(rhs).reduce(function (count, entry, index) {
            return Math.min(count, bag[index] / entry);
        }, Infinity));
    case 5: // equality
        return String(bag) == String(array2bag(rhs));
    }
}
Neil
la source
6

Octave, 253 244 226 octets

function r=f(a,b,o)
u=union(a,b);p=hist(a,u);q=hist(b,u);m=d=0;if(numel(b)==1)m=p.*b;d=p/b;elseif(numel(a)==1)m=a.*q;end
r={p+q,p-q,m,d,min(fix(p./q)),isequal(p,q)}{o};if(o<5)r=[arrayfun(@(x,y)repmat(y,1,x),r,u,'un',0){:}];end

Cette fonction doit être dans un fichier. Pour écrire la fonction dans la fenêtre de commande, vous devez utiliser endfunctionou end.

Merci à Luis Mendo d' avoir économisé 18 octets.

Les opérations sont:

1 = addition
2 = difference
3 = multiplication
4 = division
5 = counting
6 = equality test

Exemple d'utilisation:

>> f([1,2,2,3], [1,2,4], 1)
ans = 1   1   2   2   2   3   4

>> f([1,2,2,4], [1,2], 2)
ans = 2   4

>> f([1,2,3], [2,4], 2)
ans = 1   3

>> f([1,2,3,3,4], 3, 3)
ans = 1   1   1   2   2   2   3   3   3   3   3   3   4   4   4

>> f(2, [1,3], 3)
ans = 1   1   3   3

>> f([1,1,2,2,2], 2, 4)
ans = 1   2

>> f([1,2,2,3,3,3], 3, 4)
ans =  3

>> f([1,1,2,2,2,2,3,3,3], [1,2,3], 5)
ans =  2

>> f([3,2,1,2], [1,2,2,3], 6)
ans =  1

>> f([1,2,3], [1,2,2,3], 6)
ans = 0

Non golfé:

function r = f(a,b,o)
    u = union(a,b);
    p = hist(a,u);
    q = hist(b,u);
    m = d = 0;
    if (numel(b)==1)
        m = p.*b;
        d = p/b;
    elseif (numel(a)==1) 
        m = a.*q;
    end
    r = {p+q, p-q, m, d, min(fix(p./q)), isequal(p,q)}{o};
    if (o<5)
        r = [arrayfun(@(x,y) repmat(y, 1, x), r, u, 'un', 0){:}];
    end
end
Marco
la source
5

Mathematica, 387 347 300 284 octets

k=KeyValueMap[Table,#]&;j=b@@Join@@#&;l=List;q=Counts
b~SetAttributes~Orderless
a_b+c_b^:=j@{a,c}
c_b-a_b^:=j@k@Merge[q/@(l@@@{a+c,2a}),-Min[0,+##2-#]&@@#&]
a_b*n_Integer/;n>0^:=a+a*(n-1)
a_Rational c_b^:=j@k[⌊a#⌋&/@q@*l@@c]
a_b==d_b^:=l@@a==l@@d
c_b/a_b^:=If[(c-a)+a==c,1+(c-a)/a,0]

Légèrement dégouliné (aka ancienne version), n'a pas eu un support complet pour les tests d'égalité (a retourné des valeurs véridiques, mais n'a pas été évalué pour les sacs non correspondants).

SetAttributes[b,Orderless]
b/:-a_b:=d@@a
b/:a_b+c_b:=Join[a,c]
d/:a_b+c_d:=b@@Join@@KeyValueMap[Table,Merge[Counts/@(List@@@{a+b@@c,b@@c+b@@c}),Max[0,#-(+##2)]&@@#&]]
b/:Rational[1,a_]c_b:=b@@Join@@KeyValueMap[Table,Floor[#/a]&/@Counts@*List@@c]
b/:(a_b)^-1:=c@@a
c/:a_b d_c:=Min@Merge[Counts/@(List@@@{a,d}),If[+##2==0,\[Infinity],#/+##2]&@@#&]
b/:a_b*n_Integer:=a+a*(n-1)

Implémente le type de données requis avec head b.

Le premier best défini comme étant Orderless. Tout objet passé au noyau avec head btriera automatiquement ses arguments. Donc, même s'il b[3,2,1]est tapé, l'évaluateur ne verra jamais rien d'autre que b[1,2,3].

L'addition est trivialement définie comme joignant les éléments.

Une règle spéciale pour la différence de deux sacs est définie (expliquée ci-dessous). La version précédente avait un symbole auxiliaire pour les expressions de forme -bag.

Ensuite, la multiplication (tant qu'il ns'agit d'un entier positif) est définie récursivement comme n*b[...] = b[...] + (n-1)*b[...]ce qui finira par se réduire à une simple somme.

La règle spéciale pour b[...] - b[...]compter le nombre d'éléments distincts dans la somme des sacs et soustraire le sac à soustraire deux fois de ce résultat. Plus facile à expliquer:

b[1,2,3,4,5] - b[2,3,6]
Element counts in sum of bags: <|1->1, 2->2, 3->2, 4->1, 5->1, 6->1|>
Element counts in 2x second bag:     <|2->2, 3->2, 6->2|>
Subtracting the corresponding values:
                               <|1->1, 2->0, 3->0, 4->1, 5->1, 6->-1|>

Ci-dessus est une liste de Keys->Values. KeyValueMapavec Tablecrée des listes de chaque Key Valuefois. (il y a aussi Max[...,0]là pour ne pas tenter de créer des tables de longueur négatives). Cela se présente comme:

{{1},{},{},{4},{5},{}}

qui est aplati et la tête Listest remplacée par b.

La division par des nombres entiers est quelque peu similaire dans les fonctions utilisées, c'est simplement la division au sol des nombres d'éléments par le nombre entier.

Division par ensembles ou comptage, j'ai changé depuis l'implémentation d'origine. Il est maintenant récursivement effectué comme suit. Disons, nous divisons le sac b1par b2(qui dans le code golfé sont ceta respectivement. Si (b1-b2) + b2 == b1, alors ajoutez 1 et ajoutez à cela le résultat de la division (b1-b2)/b2. Sinon, retournez 0 et quittez la récursivité.

Si les sacs correspondent, la fonction intégrée ==donneTrue . La dernière ligne force un Falsesi ce n'est pas le cas.

Cas de test:

Input:
b[1, 2, 2, 3] + b[1, 2, 4]
b[1, 2, 2, 4] - b[1, 2]
b[1, 2, 3] - b[2, 4]
b[1, 2, 3, 3, 4]*3
2*b[1, 3]
b[1, 1, 2, 2, 2]/2
b[1, 2, 2, 3, 3, 3]/3
b[1, 1, 2, 2, 2, 2, 3, 3, 3] /b[1, 2, 3]
b[3, 2, 1, 2] == b[1, 2, 2, 3]
b[1, 2, 3] == b[1, 2, 2, 3]

Output:
b[1, 1, 2, 2, 2, 3, 4]
b[2, 4]
b[1, 3]
b[1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4]
b[1, 1, 3, 3]
b[1, 2]
b[3]
2
True
False
LLlAMnYP
la source
2

Q - 219 caractères

a:(,)
s:{[x;y]x((!:)(#:)x)except(,/)({.[(#);x]}')flip(7h$(({(+/)x=y}[y]')(?:)y);(({where x=y}[x]')y))}
m:{(,/)$[0>(@:)x;(#[x]')y;(#[y]')x]}
d:{(?:)x(&:)({y<=(+/)x=z}[x;y]')x}
c:{min({(+/)x=y}[x]')y}
e:{(asc x)~asc y}

apour addition, spour différence (soustraction), mpour multiplication, dpour division,c pour le comptage, epour l'égalité.

L'algorithme d'addition est évident, il suffit de joindre les sacs.

La fonction de soustraction indexe dans le sac d'entrée (représenté sous forme de tableau) avec la plage d'index entière, à l'exception des premiers nindices de chaque classe d'équivalence formés par égalité à chaque élément dans y, où nest le nombre de copies de ce représentant dans y. La gestion des doublons possibles en yfait un véritable monstre de fonction.

La fonction de multiplication prend des xvaleurs de chacun y, dans le cas où il ys'agit d'une valeur unique, au lieu d'un tableau, elle les réplique simplement.

La fonction de division produit les valeurs dont le nombre dans le tableau est supérieur à y , puis supprime les doublons.

La fonction de comptage calcule le nombre de chaque élément dans y , puis renvoie le minimum.

Deux sacs sont égaux si leurs représentations matricielles triées sont égales.

C. Quilley
la source
2

Ruby, réponse de définition de classe, 323 291 octets

Je voulais surtout faire Bag une classe réelle en raison de la flexibilité de Ruby avec les classes. Dans ce cas, il hérite de Arrayparce qu'il est plus court que d'avoir à initialiser un tableau interne et à traiter les autres choses.

Je ferai probablement une réponse plus sérieuse au golf qui utilise une fonction pour gérer les opérations de demain. Je suis très fatigué et je me suis trop amusé avec ça même si j'ai dû me débattre avec la définition de la classe numérique pour bien Number * Bagtravailler LOUANGEZ LA FONCTION COERCE POUR LA FAIRE.

Essayez-le en ligne! (L'espace blanc n'a pas d'importance dans Ruby, donc le code n'y est pas légèrement dissipé.)

class B<Array
def == o
sort==o.sort
end
def + o
B.new super
end
def - o
r=to_a
o.map{|i|r[r.index(i)||size]=p}
B.new r-[p]
end
def * i
B.new super
end
def / i
B.new uniq.map{|o|[o]*(count(o)/i)}.flatten
end
def c o
o.map{|i|count i}.min
end
def inspect
sort
end
def coerce o
[self,o]
end
end
Encre de valeur
la source
1

Rubis, 201 octets

Comme promis dans mon autre réponse, en voici une qui utilise des fonctions au lieu de construire une nouvelle classe. Je suis si près de franchir la barre des 200 octets ... Essayez-le en ligne

Celui-ci utilise les mêmes opcodes que @Neil dans sa réponse JavaScript, et le même ordre d'arguments (lhs, opcode, rhs)

0: Addition
1: Difference
2: Multiplication
3: Division
4: Counting
5: Equality

Le code:

->x,o,y{[->{(x+y).sort},->r=[*x]{y.map{|i|r[r.index(i)||x.size]=p};r-[p]},->{(x==[*x]?x*y :y*x).sort},->{x.uniq.map{|i|[i]*(x.count(i)/y)}.flatten},->{y.map{|i|x.count i}.min},->{x.sort==y.sort}][o][]}
Encre de valeur
la source
1

C ++, 555 551 octets

(sauts de ligne ajoutés pour plus de lisibilité - seule la première nouvelle ligne est requise et comptée)

#include<map>
struct B:std::map<int,int>{
B(std::initializer_list<int>l){for(auto i:l)++(*this)[i];}};
B operator+(B a,B b){for(auto m:b)a[m.first]+=m.second;return a;}
B operator-(B a,B b){for(auto m:b){int&x=a[m.first];x-=x>m.second?m.second:x;if(!x)a.erase(m.first);};return a;}
B operator*(B b,int n){for(auto m:b)b[m.first]*=n;return b;}
B operator*(int n,B b){return b*n;}
B operator/(B b,int n){for(auto m:b)if(!(b[m.first]/=n))b.erase(m.first);return b;}
int operator/(B a,B b){auto r=~0u;for(auto m:b){int x=a[m.first]/m.second;r=r>x?x:r;}return r;}

Explication

Nous implémentons notre sac comme une carte de (valeur, nombre). Les opérations de base peuvent être implémentées en manipulant les comptages; la soustraction et la division entière doivent également supprimer tous les éléments dont le nombre atteint zéro, de sorte questd::map::operator== cela fonctionne comme le test d'égalité.

Le code développé suivant est une version générique de ce qui précède, beaucoup moins golfé: nous utilisons un séparé s()pour extraire toutes les valeurs de comptage nul, et nous implémentons des constopérations en termes d'opérateurs d'affectation de la manière idiomatique C ++. Nous utilisons également s()pour effectuer la multiplication en 0retournant un sac vraiment vide (testé en ajoutant (B{1}*0 != B{})à main()); l'original échoue à ce test, et il n'est pas clair si c'est une exigence.

template<class T>
struct Bag{
    std::map<T,int>b;
    Bag(const std::initializer_list<T>& l){for(auto i:l)++b[i];}
    Bag&s(){for(auto i=b.begin();i!=b.end();i=i->second?++i:b.erase(i));return*this;}
    Bag&operator+=(const Bag& o){for(auto m:o.b)b[m.first]+=m.second;return*this;}
    Bag&operator-=(const Bag& o){for(auto m:o.b){auto&x=b[m.first];x-=x>m.second?m.second:x;}return s();}
    Bag&operator*=(int n){for(auto m:b)b[m.first]*=n;return s();}
    Bag&operator/=(int n){for(auto m:b)b[m.first]/=n;return s();}
    auto operator/=(const Bag& o){auto r=~0u;for(auto m:o.b){int x=b[m.first]/m.second;r=r>x?x:r;}return r;}
    bool operator==(const Bag& o)const{return b==o.b;}

    Bag operator+(Bag o)const{return o+=*this;}
    Bag operator-(const Bag& o)const{Bag t=*this;return t-=o;}
    Bag operator*(int n)const{Bag t=*this;return t*=n;}
    friend Bag operator*(int n,const Bag& b){return b*n;}
    auto operator/(auto n)const{Bag t=*this;return t/=n;}
    bool operator!=(const Bag& o)const{return b!=o.b;}
};

using B = Bag<int>;

Les tests

bool operator!=(B a,B b){return!(a==b);}
int main()
{
    return 0
        + (B{1,2,2,3}+B{1,2,4}  !=  B{1,1,2,2,2,3,4})
        + (B{1,2,2,4}-B{1,2}  !=  B{2,4})
        + (B{1,2,3}-B{2,4}  !=  B{1,3})
        + (B{1,2,3,3,4}*3  !=  B{1,1,1,2,2,2,3,3,3,3,3,3,4,4,4})
        + (2*B{1,3}  !=  B{1,1,3,3})
        + (B{1,1,2,2,2}/2  !=  B{1,2})
        + (B{1,2,2,3,3,3}/3  !=  B{3})
        + (B{1,1,2,2,2,2,3,3,3}/B{1,2,3} != 2)
        + (B{3,2,1,2}  !=  B{1,2,2,3})
        + (B{1,2,3}  ==  B{1,2,2,3})
        ;
}
Toby Speight
la source
Bonne réponse! +1. Votre code doit être correctement formaté dans la publication.
Yytsi
Je voulais délibérément que le code soit bouclé, donc vous pouvez tout voir. L'alternative était d'ajouter des sauts de ligne.
Toby Speight
1
Les sauts de ligne ont été ajoutés - je pense que c'est mieux, car la mise en forme fonctionne maintenant.
Toby Speight
1

Python 2.7 - 447B (taille de fichier)

Ceci est mon premier essai chez Codegolf, j'espère qu'il vous satisfera. J'avais besoin de 2h. (Mais je suis toujours un débutant à Python)

Edit: Merci à "Kevin Lau - pas Kenny" pour avoir souligné ceux-ci:

  • pythons auto argument dans une classe peut être remplacé par quoi que ce soit
  • l'indentation ne doit être qu'un seul espace
  • le builtin trié - funktion (je savais je l'avais vu, mais je pensais que c'était une méthode dans les listes)
  • __ radd __ n'est pas nécessaire (je ne supporte que l'ajout d'objets B (de type sac))

Edit: De plus, j'ai économisé de l'espace en remplaçant les fonctions par des lambdas et de nouvelles lignes et indentations par plus de points-virgules.

Code:

class B:
 def __init__(S,L=[]):S.L=sorted(list(L));S.p=lambda:[[i]*S.L.count(i)for k,i in enumerate(S.L)if i!=S.L[k-1]];S.__eq__=lambda o:S.L==o.L;S.__rmul__=S.__mul__=lambda o:B(S.L*o);S.__add__=lambda o:B(S.L+o.L);S.__sub__=lambda o:B([i for k in S.p()for i in k[:max(0,S.L.count(k[0])-o.L.count(k[0]))]]);S.__div__=lambda o:B([i for k in S.p()for i in k[::o][:[-1,None][len(k)%o==0]]]);S.c=lambda o:min([S.L.count(i)//o.L.count(i)for i in o.L])

contrôles:

print B([1,2,2,3]) + B([1,2,4]) == B([1,1,2,2,2,3,4]) # Add

print B([1,2,2,4]) - B([1,2]) == B([2,4]) #Substract
print B([1,2,3])   - B([2,4]) == B([1,3]) #Substract

print B([1,2,3,3,4]) * 3 == B([1,1,1,2,2,2,3,3,3,3,3,3,4,4,4])#Multiply
print 2 * B([1,3]) == B([1,1,3,3])                            #

print B([1,1,2,2,2])   /2 == B([1,2]) #Divide
print B([1,2,2,3,3,3]) /3 == B([3])   #

print B([1,1,2,2,2,2,3,3,3]).c(B([1,2,3]))==2 #Contained n times

print B([3,2,1,2]) == B([1,2,2,3]) # Equal
print B([1,2,3])   == B([1,2,2,3]) # Unequal

Production:

True
True
True
True
True
True
True
True
True
False

Je pourrais l'essayer une autre fois avec comme base un certain temps. Edit: je vais peut-être même essayer avec des fonctions uniquement.

Teck-freak
la source
Bienvenue chez PPCG! Une chose à noter à propos de Python est que vous n'avez pas réellement besoin d'appeler les premiers paramètres dans les fonctions de classe self- quelque chose comme Sferait aussi bien. Une autre astuce est que la sortedfonction intégrée fait exactement ce que vous voulez de votre nouvelle fonction s, vous pouvez donc renoncer à la définition de la fonction (car vous ne l'utilisez qu'une seule fois). Vous n'en avez jamais besoin __radd__car vous n'ajoutez jamais de non-sacs avec des sacs, bien que vous en ayez toujours besoin __rmul__. Enfin, vous n'avez besoin que d'un espace de retrait au lieu de quatre, ce qui réduit considérablement le nombre d'octets
Value Ink