Implementar operações de bolsa

20

Uma bolsa , também chamada de multiset, é uma coleção não ordenada. Você pode chamá-lo de um conjunto que permite duplicatas ou de uma lista (ou matriz) que não está ordenada / indexada. Nesse desafio, você é solicitado a implementar operações de bolsa: adição, diferença, multiplicação, divisão, contagem e teste de igualdade.

Operações

As operações especificadas podem não ser convencionais.

  • Além disso, combina duas malas em uma, conservando o número total de cada valor
    [1,2,2,3] + [1,2,4] = [1,1,2,2,2,3,4]
  • A diferença remove de uma sacola cada elemento de outra sacola ou não faz nada se esse elemento não existir
    [1,2,2,4] - [1,2] = [2,4] [1,2,3] - [2,4] = [1,3]
  • multiplicação multiplica cada elemento no saco.
    [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]
  • A divisão é incomum: cada n elementos iguais são colocados em n novas bolsas iguais, elementos que não podem formar um grupo n permanecem na bolsa. Devolva qualquer uma das n novas bolsas.
    [1,1,2,2,2] / 2 = [1,2] [1,2,2,3,3,3] / 3 = [3]
  • contagem conta quantas sacolas divisórias podem ser produzidas a partir da sacola de dividendos
    [1,1,2,2,2,2,3,3,3] c [1,2,3] = 2
  • teste de igualdade verifica se duas malas têm o mesmo número de cada elemento
    [1,2,2,3] == [3,2,1,2] = truthy [1,2,3] == [1,2,2,3] = falsy(também pode ser usado =para isso)

Se você estiver usando seus próprios símbolos para os operadores, especifique.

Formatos

As malas serão exibidas como listas do formulário [1,1,2,3,4]. Você pode usar qualquer outro suporte que não seja quadrado, ou mesmo usar aspas, ou nada. Os elementos serão inteiros (matematicamente, não necessariamente int) para os fins desta pergunta. As malas não precisam ser classificadas.

O formato de entrada será duas malas ou uma maleta e um número inteiro, com um operador. Você pode especificar seu próprio formato, desde que contenha esses três.

O formato de saída deve ser uma única bolsa do mesmo formato.

Regras

  • você não pode usar funções, operações ou bibliotecas internas (incluindo a biblioteca padrão) que já as implementam; não há problema em usar concatenação e multiplicação de lista, pois são por definição operações de lista, não operações de bolsa (que basicamente fazem a mesma coisa)
  • lacunas padrão se aplicam
  • resposta mais curta ganha

Casos de teste

[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
fonte
2
Talvez relaxe o formato de entrada? Por exemplo, permita levar a mala, a mala / número e o operador como argumentos separados ou em um formato livre. Caso contrário, uma parte importante do desafio é analisar a entrada, o que não é particularmente interessante
Luis Mendo
A divisão no espaço do @LuisMendo é suficiente para analisar isso, se você tiver um idioma que possa avaliar as strings como listas, não acha? Eu sou inexperiente em desafios de postagem, então por favor me esclareça :-)
busukxuan
Não consegui encontrar uma meta post relevante, mas veja, por exemplo, o texto aqui : você pode ler o número inteiro como sua representação decimal, representação unária (usando um caractere de sua escolha), matriz de bytes (endian grande ou pequeno) ou byte único (se esse for o maior tipo de dados do seu idioma) . Ou aqui : os formatos de entrada e saída são flexíveis como de costume (matrizes, listas, lista de listas, seqüências de caracteres com separadores razoáveis, etc. ).
Luis Mendo
@LuisMendo é basicamente grátis agora. E sobre o número inteiro, eu apenas quis dizer isso no sentido matemático, não no tipo de dados.
busukxuan
1
@LuisMendo não, os símbolos precisam fazer sentido, mesmo que apenas um pouco. Bem, você pode usar one = para teste de igualdade.
Busukxuan 03/07/16

Respostas:

3

05AB1E, 92 87 83 82 77 bytes

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

Dividir por operação

>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

Explicação

Adição

‚˜,}

Coloque uma sacola na outra e alise-as em uma sacola.

Multiplicação

и˜Qis}

Verifique se o número está no topo da pilha. Chame isso de X.

GD})˜,}

Duplique o saco X vezes e junte-o a um saco.

Contagem

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

Para cada elemento na sacola do divisor, conte o número de ocorrências na sacola de dividendos.
A contagem mínima será o número de sacolas que podemos fazer.

Igualdade

 {s{Q,}

Ordene as duas malas e verifique se são iguais.

Divisão

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

Conte quantas vezes cada elemento exclusivo ocorre na sacola.
Se ocorrer pelo menos quantas vezes o divisor. Mantenha (nr_of_copies_total // divisor) cópias na sacola.

Diferença

svy†¬yQi¦}} 

Para cada elemento no subtraendo, classifique-o na frente do minuendo.
Se o subtraendo atual for igual ao primeiro elemento no minuendo, remova-o do minuendo.

Emigna
fonte
9

APL (155)

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

Isso define um operador 'bolsa', que define as operações da bolsa para determinadas funções. Ou seja, +∆seria adição. Em seguida, ele lê uma linha do teclado e a avalia como uma expressão de APL.

As funções são:

  • +∆, Adição
  • -∆subtração
  • ×∆multiplicação
  • ÷∆divisão
  • ⊂∆contando
  • ≡∆, equivalência (embora, devido ao golfe, qualquer função não reconhecida faça equivalência)

Explicação:

  • ∆←{... }: define um operador :

    • O←⍺⍺: armazena a função fornecida em O( ⎕CRnão funcionará ⍺⍺diretamente)
    • O←⎕CR'O': obtém a representação de string dessa função
    • '+'=O... :: para adição,
      • ⍺,⍵: junte as duas listas
      • R[⍋R←... ]: e classifique o resultado
    • '-'=O:: para subtração,
      • ⍺{... }⍵: execute a seguinte função recursiva:
        • ⍵≡⍬:⍺: se o subtraendo estiver vazio, retorne o minuendo
        • ⍺/⍨(⍳⍴⍺)≢⍺⍳⊃⍵∇1↓⍵: caso contrário, remova o primeiro elemento do subtraendo do subtraendo e do minuendo e tente novamente
    • (⍬=⍴⍵)∧K←'×'=O: para multiplicação e se o argumento correto não for um saco:
      • ⍵/⍺: replica cada elemento no argumento esquerdo pelo argumento direito
    • K:: ... e se o argumento certo for um saco:
      • ⍺/⍵: replica cada elemento no argumento da direita pelo argumento da esquerda (para que a multiplicação seja comutativa)
    • '÷'=O:: para divisão,
      • ⍵≤⍺∘.+⍺: veja quais elementos em ⍺ ocorrem pelo menos ⍵ vezes,
      • ⍺/⍨: selecione aqueles de ⍺,
      • : e remova todas as duplicatas dessa lista
    • '⊂'=O:: para contar,
      • ⍵{... }⍺: execute a seguinte função recursiva:
        • (∪⍺)≢∪⍵:0: se uma lista contém elementos que a outra não, o resultado é 0
        • 1+⍺∇⍵-∆⍺: caso contrário, subtraia o dividendo do divisor, tente novamente e aumente o resultado.
    • : se nenhuma das opções acima, faça o teste de equivalência:
      • ⍺[⍋⍺]≡⍵[⍋⍵]: classifique as duas listas e veja se são iguais
  • : lê uma expressão do teclado, avalia-a e gera o resultado.

Casos de teste:

      ∆←{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
fonte
Solução realmente profissional e excelente redação! 1
Sua redação e explicação são realmente sólidas! Uma coisa, no entanto: para divisão, acredito que a especificação está redigida de uma maneira que [2,2,2,2,2,2]/3deve dar [2,2], mas a sua parece dar [2].
Value Ink
Você não precisa codificar o REPL. Se você acabou de definir , o usuário será despejado no REPL nativo da APL, onde agora é válido. Eu acho que você pode salvar alguns bytes movendo a subtração para o final, pois é o único que requer duas linhas. Em vez de ⎕CR, use *para simbolizar contagem, e faça O←⍺⍺2, então 2=O:para mais, 1=Opara mult, 0=O:para equiv, 7<O:para contagem e 0<O:para div (com implícito 0>O:para subtr).
Adám 29/08/16
6

JavaScript (ES6), 260 bytes

(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))

Leva 3 parâmetros. O primeiro parâmetro é uma matriz, o segundo é um operador e o terceiro depende do operador. São necessários sacos para armazenar números inteiros não negativos.

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

Ungolfed:

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
fonte
6

Octave, 253 244 226 bytes

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

Esta função deve estar em um arquivo. Para escrever a função na janela de comando, você deve usar endfunctionou end.

Agradecemos a Luis Mendo por salvar 18 bytes.

As operações são:

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

Exemplo de uso:

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

Ungolfed:

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
fonte
5

Mathematica, 387 347 300 284 bytes

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]

Ligeiramente degolfado (também conhecido como versão antiga), não tinha suporte total para testes de igualdade (retornou valores verdadeiros, mas foi deixado sem avaliação para bolsas não correspondentes).

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)

Implementa o tipo de dados necessário com o cabeçalho b.

Primeiro bé definido como sendo Orderless. Qualquer objeto passado para o kernel com cabeça classificará bautomaticamente seus argumentos. Portanto, mesmo se b[3,2,1]digitado, o avaliador nunca verá outra coisa senão b[1,2,3].

A adição é trivialmente definida como unir os elementos.

Uma regra especial para a diferença de duas malas é definida (explicada abaixo). A versão anterior tinha um símbolo auxiliar para expressões de forma -bag.

Então a multiplicação (contanto que nseja um número inteiro positivo) é recursivamente definida, o n*b[...] = b[...] + (n-1)*b[...]que eventualmente reduzirá a uma soma simples.

A regra especial para b[...] - b[...]conta o número de elementos distintos na soma dos sacos e subtrai o saco a ser subtraído duas vezes desse resultado. Mais fácil de explicar:

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

Acima está uma lista de Keys->Values. KeyValueMapcom Tablecria listas de cada Key Valuevez. (também Max[...,0]existe um para não tentar criar tabelas de comprimento negativo). Isso sai como:

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

que é achatado e a cabeça Listé substituída por b.

A divisão por números inteiros é um pouco semelhante nas funções usadas, é simplesmente a divisão do elemento contada pelo número inteiro.

Divisão por conjuntos ou contando Eu mudei desde a implementação original. Agora é feito recursivamente da seguinte maneira. Digamos, dividimos o saco b1por b2(que no código golfado são ce arespectivamente. Se (b1-b2) + b2 == b1, adicione 1 e adicione o resultado da divisão (b1-b2)/b2. Se não, retorne 0 e saia da recursão.

Se as malas coincidirem, a built-in é ==fornecida True. A última linha força a Falsese não o fizerem.

Casos de teste:

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
fonte
2

Q - 219 caracteres

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}

apor adição, spor diferença (subtração), mpor multiplicação, dpor divisão, cpor contagem, epor igualdade.

O algoritmo de adição é óbvio, apenas juntando as malas.

A função de subtração indexa na bolsa de entrada (representada como uma matriz) com todo o intervalo de índice, exceto os primeiros níndices de cada classe de equivalência formada por igualdade para cada elemento em y, onde né o número de cópias desse representante em y. O manuseio de possíveis duplicatas o ytorna um verdadeiro monstro de uma função.

A função de multiplicação pega xvalores de cada um y, no caso de yum valor único, em vez de uma matriz, apenas os replica.

A função de divisão produz os valores cuja contagem na matriz é maior que ye remove as duplicatas.

A função de contagem calcula as contagens de cada elemento ye retorna o mínimo.

Duas bolsas são iguais se as representações de matriz ordenadas forem iguais.

C. Quilley
fonte
2

Ruby, resposta de definição de classe, 323 291 bytes

Principalmente, só queria fazer da Bagclasse uma verdadeira, devido à flexibilidade de Ruby com as classes. Nesse caso, ele é herdado Arrayporque é mais curto do que ter que inicializar uma matriz interna e lidar com outras coisas.

Provavelmente darei uma resposta mais séria ao golfe, que usa uma função para lidar com as operações amanhã. Estou muito cansado e me diverti muito com isso , apesar de ter que discutir com a definição da classeNumber * Bag numérica para começar a funcionar adequadamente.

Experimente online! (O espaço em branco não importa em Ruby, portanto, o código é um pouco sem uso de lá).

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
Value Ink
fonte
1

Ruby, 201 bytes

Como prometido na minha outra resposta, aqui está uma que usa funções em vez de criar uma nova classe. Estou tão perto de violar a marca de 200 bytes ... Experimente on-line

Ele usa os mesmos opcodes que @Neil em sua resposta JavaScript e a mesma ordem de argumentos (lhs, opcode, rhs)

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

O código:

->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][]}
Value Ink
fonte
1

C ++, 555 551 bytes

(quebras de linha adicionadas para facilitar a leitura - somente a primeira nova linha é necessária e contada)

#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;}

Explicação

Implementamos nossa bolsa como um mapa de (valor, contagem). As operações básicas podem ser implementadas manipulando as contagens; subtração e divisão inteira também precisam remover todos os elementos cuja contagem chega a zero, para que std::map::operator==funcione como teste de igualdade.

O código expandido a seguir é uma versão genérica dos itens acima, muito menos eficientes: usamos um separado s()para extrair quaisquer valores de contagem zero e implementamos constoperações em termos de operadores de atribuição da maneira idiomática em C ++. Também usamos s()para fazer a multiplicação 0retornando uma bolsa verdadeiramente vazia (testada adicionando (B{1}*0 != B{})a main()); o original falha neste teste e não está claro se é um requisito.

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>;

Testes

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
fonte
Boa resposta! +1. Seu código precisa de formatação adequada na postagem.
Yytsi 06/07/19
Eu queria deliberadamente que o código envolvesse, para que você possa ver tudo. A alternativa foi adicionar quebras de linha.
precisa
1
Quebras de linha adicionadas - acho que isso é melhor, porque agora a prettify funciona.
precisa
1

Python 2.7 - 447B (tamanho do arquivo)

Esta é a minha primeira tentativa no Codegolf, espero que satisfaça. Eu precisava de 2h. (Mas eu ainda sou iniciante em Python)

Edit: Obrigado a "Kevin Lau - não Kenny" por apontar estes:

  • pythons auto argumento em uma classe pode ser substituído por qualquer coisa
  • recuo só precisa ser um espaço único
  • o built-in classificado - funktion (eu sabia que tinha visto, mas achei que fosse um método nas listas)
  • __ radd __ não é necessário (apenas suporte a adição de objetos B (tipo Bag))

Edit: Além disso, economizei espaço substituindo funções por lambdas e novas linhas e recuos com mais ponto e vírgula.

Código:

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])

Verificações:

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

Saída:

True
True
True
True
True
True
True
True
True
False

Eu poderia tentar outra hora com o set como base algum tempo. Edit: Talvez eu até tente apenas com funções.

Teck-freak
fonte
Bem-vindo ao PPCG! Um ponto a ser observado no Python é que você não precisa chamar os primeiros parâmetros nas funções de classe self- algo como Sfaria também. Outro truque é que a sortedfunção interna faz exatamente o que você deseja da sua nova função s, para que você possa renunciar à definição da função (visto que você a usa apenas uma vez). Você nunca precisa, __radd__porque nunca adiciona não-sacolas com malas, embora ainda precise __rmul__. Finalmente, você só precisa de um espaço de travessão em vez de quatro, que corta para baixo sua contagem de bytes por um pouco
Valor Ink