Виконайте операції з мішком


20

Мішок , також званий мультімножество, це невпорядкована колекція. Ви можете назвати це набором, який дозволяє дублікати, або списком (або масивом), який не впорядкований / індексований. У цьому виклику вам пропонується здійснити операції з мішком: додавання, різницю, множення, поділ, підрахунок та перевірку рівності.

Операції

Зазначені операції можуть не бути звичайними.

  • Крім того, поєднує два пакети в один, зберігаючи загальну кількість кожного значення
    [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]
  • поділ є рідкісним: кожен n рівних елементів поміщається в n рівних нових мішків, елементи, які не можуть сформувати n-групу, залишаються в мішку. Поверніть будь-який із п нових мішків.
    [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
  • перевірка рівності перевіряє, чи є в двох пакетах однакові номери кожного елемента
    [1,2,2,3] == [3,2,1,2] = truthy [1,2,3] == [1,2,2,3] = falsy(можна також використовувати =для цього)

Якщо ви використовуєте власні символи для операторів, будь ласка, вкажіть.

Формати

Сумки відображатимуться як списки форми [1,1,2,3,4]. Ви можете використовувати будь-яку іншу дужку, ніж квадратну, або навіть використовувати лапки, або взагалі нічого. Елементи будуть цілими числами (математично, не обов'язково int) для цього питання. Мішки не слід сортувати.

Формат введення буде двома пакетами або мішком і цілим числом, з оператором. Ви можете вказати власний формат, якщо він містить ці три.

Формат виводу повинен бути одним пакетом одного формату.

Правила

  • ви не можете використовувати вбудовані функції, операції або бібліотеки (включаючи стандартну бібліотеку), які вже реалізують їх; добре, хоча використовувати конкатенацію та множення списку, оскільки вони є операціями зі списком визначення, а не операціями з мішками (які, як правило, роблять те саме)
  • застосовуються стандартні лазівки
  • виграє найкоротша відповідь

Тестові кейси

[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

2
Може, розслабте формат введення? Наприклад, дозвольте взяти сумку, сумку / номер та оператора як окремі аргументи, або у вільному форматі. Інакше важливою частиною виклику є аналіз даних, що не особливо цікаво
Луїс Мендо

@LuisMendo розділеного простору достатньо для розбору цього питання, якщо у вас є мова, яка може взагалі оцінювати рядки як списки, ви не думаєте? Я недосвідчений в опублікуванні викликів, тому, будь ласка, просвітліть мене :-)
busukxuan

Я не зміг знайти відповідне мета-повідомлення, але дивіться, наприклад, формулювання тут : ви можете прочитати ціле число у вигляді його десяткового подання, унарного подання (використовуючи вибраний вами символ), байтовий масив (великий або маленький ендіан) або однобайтовий (якщо це найбільший тип даних для ваших мов) . Або тут : формати введення та виведення є гнучкими, як зазвичай (масиви, списки, список списків, рядки з розумними роздільниками тощо ).
Луїс Мендо

@LuisMendo зараз це в основному безкоштовно. А щодо цілого числа я просто мав на увазі, що в математичному сенсі це не тип даних.
busukxuan

1
@LuisMendo nope, символи повинні мати сенс, навіть якщо їх небагато. Ну, ви можете використовувати один = для тесту на рівність.
busukxuan

Відповіді:


3

05AB1E, 92 87 83 82 77 байт

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

Розділити за операцією

>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

Пояснення

Доповнення

‚˜,}

Покладіть один мішок в інший і розправте їх до одного мішка.

Множення

и˜Qis}

Переконайтеся, що номер знаходиться у верхній частині стека. Зателефонуйте цьому X.

GD})˜,}

Скопіюйте мішок X разів і приєднайтеся до одного мішка.

Рахувати

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

Для кожного елемента в мішку дільника підраховуйте кількість випадків виникнення в мішку дивідендів.
Мінімальна кількість - це кількість мішків, які ми можемо виготовити.

Рівність

 {s{Q,}

Сортуйте обидва пакети і перевірте, чи рівні вони.

Відділ

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

Порахуйте, скільки разів кожен унікальний елемент зустрічається в сумці.
Якщо це відбувається хоча б стільки разів, скільки дільник. Зберігайте (nr_of_copies_total // дільник) копії в сумці.

Різниця

svy†¬yQi¦}} 

Для кожного елемента в підряднику відсортуйте його в передній частині мінуса.
Якщо поточний підрядок, якщо він дорівнює першому елементу в минуті, вийміть його з мінусу.


9

APL (155)

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

Це визначає операторську «сумку», яка визначає операції з мішком для заданих функцій. Тобто +∆було б доповненням. Потім він зчитує рядок з клавіатури і оцінює його як вираз APL.

Функції:

  • +∆, доповнення
  • -∆, віднімання
  • ×∆, множення
  • ÷∆, поділ
  • ⊂∆, рахуючи
  • ≡∆, еквівалентність (хоча через гольф будь-яка нерозпізнана функція буде робити еквівалентність)

Пояснення:

  • ∆←{... }: визначте оператора :

    • O←⍺⍺: збережіть задану функцію в O( ⎕CRне працюватиме ⍺⍺безпосередньо)
    • O←⎕CR'O': отримати представлення рядка цієї функції
    • '+'=O... :: для додавання,
      • ⍺,⍵: об'єднайте два списки разом
      • R[⍋R←... ]: і сортуйте результат
    • '-'=O:: для віднімання,
      • ⍺{... }⍵: запустіть таку рекурсивну функцію:
        • ⍵≡⍬:⍺: якщо підрядок порожній, поверніть мінус
        • ⍺/⍨(⍳⍴⍺)≢⍺⍳⊃⍵∇1↓⍵: в іншому випадку вийміть перший елемент підрядника з підрядного і мінду та повторіть спробу
    • (⍬=⍴⍵)∧K←'×'=O: для множення, і якщо правильний аргумент не є пакетом:
      • ⍵/⍺: повторити кожен елемент у лівому аргументі правим аргументом
    • K:: ... і якщо правильним аргументом є сумка:
      • ⍺/⍵: повторити кожен елемент у правому аргументі лівим аргументом (це так, що множення є комутативним)
    • '÷'=O:: для поділу,
      • ⍵≤⍺∘.+⍺: подивіться, які елементи в ⍺ трапляються принаймні ⍵ разів,
      • ⍺/⍨: виберіть ті з ⍺,
      • : і видалити всі дублікати зі цього списку
    • '⊂'=O:: для підрахунку,
      • ⍵{... }⍺: запустіть таку рекурсивну функцію:
        • (∪⍺)≢∪⍵:0: якщо один список містить елементи, інший - ні, результат дорівнює 0
        • 1+⍺∇⍵-∆⍺: інакше відняти дивіденд від дільника, спробувати ще раз і збільшити результат.
    • : якщо нічого з перерахованого, зробіть тест на еквівалентність:
      • ⍺[⍋⍺]≡⍵[⍋⍵]: сортуйте обидва списки та подивіться, чи вони рівні
  • : прочитати вираз з клавіатури, оцінити його та вивести результат.

Тестові приклади:

      ∆←{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

Дійсно професійне рішення та чудова реєстрація! +1

Ваше написання та пояснення справді суцільне! Однак одне: але для поділу я вважаю, що специфікація формулюється так, що [2,2,2,2,2,2]/3має дати [2,2], але ваша, здається, дає [2].
Значення чорнила

Вам не потрібно кодувати REPL. Якщо ви просто визначитесь , користувач буде скинутий у рідну REPL APL, де зараз діє. Я думаю, ви можете зберегти кілька байт, перемістивши віднімання до кінця, оскільки це єдиний, який вимагає двох рядків. Замість символу ⎕CRвикористовуйте, *щоб символізувати підрахунок, і зробіть O←⍺⍺2, тоді 2=O:для плюс, 1=Oдля мульти, 0=O:для еквівалента, 7<O:для підрахунку та для діва 0<O:(з мається 0>O:на увазі для субтр).
Adám

6

JavaScript (ES6), 260 байт

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

Бере 3 параметри. Перший параметр - це масив, другий - оператор, третій залежить від оператора. Мішки повинні містити невід’ємні цілі числа.

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

Безголівки:

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

6

Октава, 253 244 226 байт

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

Ця функція повинна бути у файлі. Щоб записати функцію у вікно команд, ви повинні використовувати endfunctionабо end.

Завдяки Луїсу Мендо за збереження 18 байт.

Операції:

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

Приклад використання:

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

Безголівки:

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

5

Математика, 387 347 300 284 байт

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]

Трохи дегольфінований (він же і стара версія), не мав повної підтримки тестів на рівність (повернув тривожні значення, але залишив неоціненими для невідповідних мішків).

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)

Реалізує необхідний тип даних з головою b.

По-перше b, визначено як Orderless. Будь-який об’єкт, переданий до ядра з головою, bавтоматично запозичує його аргументи. Тож навіть якщо b[3,2,1]він набраний, оцінювач ніколи не побачить нічого іншого, крім b[1,2,3].

Додавання тривіально визначається як приєднання елементів.

Визначено спеціальне правило різниці двох мішків (пояснено нижче). Попередня версія мала допоміжний символ для виразів форми -bag.

Тоді множення (поки nце додатне ціле число) рекурсивно визначається тим, n*b[...] = b[...] + (n-1)*b[...]що з часом зменшиться до простої суми.

Спеціальне правило b[...] - b[...]підраховує кількість відмінних елементів у сумі мішків і віднімає сумку, яку потрібно відняти двічі від цього результату. Простіше пояснити:

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

Вище - перелік Keys->Values. KeyValueMapз Tableстворює списки кожного Key Valueразу. (є також Max[...,0]там, щоб не намагатися створити таблиці негативної довжини). Це виходить як:

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

який сплющений і голову Listзамінено b.

Ділення на цілі числа чимось подібне за функціями, які використовуються, це просто флоральний поділ підрахунків елементів на ціле число.

Поділ на набори або підрахунок я змінив з моменту оригінальної реалізації. Зараз це робиться рекурсивно так. Скажімо, ми ділимо мішок b1на b2(які в коді для гольфу є cі aвідповідно. Якщо (b1-b2) + b2 == b1, то додаємо 1 і додаємо до цього результат ділення (b1-b2)/b2. Якщо ні, повертаємо 0 і виходимо з рекурсії.

Якщо сумки збігаються, вбудована ==подає True. Останній рядок змушує a, Falseякщо вони цього не роблять.

Тестові приклади:

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

2

Q - 219 символів

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}

aдля додавання, sдля різниці (віднімання), mдля множення, dдля ділення, cдля підрахунку, eдля рівності.

Алгоритм додавання є очевидним, просто приєднуючись до мішків.

Показники функції віднімання у вхідному пакеті (представлені у вигляді масиву) з усім діапазоном індексів, за винятком перших nіндексів кожного класу еквівалентності, утворених рівністю кожного елемента в y, де nкількість копій цього представника y. Поводження з можливими дублікатами yробить це справжнім чудовиськом функції.

Функція множення приймає xзначення з кожного y, у випадку, якщо yце єдине значення, а не масив, він просто реплікує їх.

Функція поділу виробляє значення, кількість яких у масиві більше, ніж yпотім видаляє дублікати.

Функція підрахунку обчислює кількість кожного елемента в y, а потім повертає мінімум.

Два мішки рівні, якщо їх відсортовані представлення масиву рівні.


2

Ruby, відповідь на визначення класу, 323 291 байт

В основному просто хотіли зробити Bagвласне клас через гнучкість Рубі до класів. У цьому випадку він успадковується від того, Arrayщо це коротше, ніж ініціалізувати внутрішній масив та мати справу з іншими речами.

Я, мабуть, зроблю більш серйозну відповідь на гольф, яка використовує функцію для вирішення завдань завтра. Я дуже втомився, і мені було надто весело з цим, хоча мені довелося боротися з визначенням класу числових цифр, щоб Number * Bagнормально працювати. НАПРАВЛІТЬ ФУНКЦІЮ ПРИКЛАДУ ДЛЯ ВЗАЄМОГО ТА ТАК Я НЕ ПОТРІБНО ПОРУШИТИ ВИЗНАЧЕННЯ КЛЮЧНОГО КЛАСУ

Спробуйте в Інтернеті! (Білий пробіл не має значення в Ruby, тому код там злегка не зосереджений.)

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

1

Ruby, 201 байт

Як було обіцяно в іншій моїй відповіді, ось ця, яка використовує функції замість того, щоб будувати новий клас. Я так близький до порушення позначки в 200 байт ... Спробуйте це в Інтернеті

Він використовує ті самі опкоди, що і @Neil у своїй відповіді на JavaScript, і той самий порядок аргументів (lhs, opcode, rhs)

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

Кодекс:

->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][]}

1

C ++, 555 551 байт

(для читабельності додаються розриви рядків - потрібен і враховується лише перший новий рядок)

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

Пояснення

Ми реалізуємо наш мішок як карту (значення, кількість). Основні операції можна здійснити шляхом маніпулювання рахунками; віднімання та ціле ділення також потрібно видалити будь-які елементи, кількість яких досягає нуля, так що це std::map::operator==буде тестом рівності.

Наступний розширений код - це узагальнена версія вищезазначеного, набагато менш гольфу: ми використовуємо окремий, s()щоб видалити будь-які значення нульового рахунку, і ми реалізуємо constоперації з точки зору операторів присвоєння ідіоматичним способом C ++. Ми також використовуємо s()для множення, 0повертаючи справді порожній мішок (перевірений додаванням (B{1}*0 != B{})до main()); оригінал не дає цього тесту, і не ясно, чи це вимога.

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

Тести

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

Гарна відповідь! +1. Ваш код потребує належного форматування в публікації.
Yytsi

Я навмисно хотів, щоб код був завернутий, щоб ви могли це все побачити. Альтернативою було додати розриви рядків.
Toby Speight

1
Додано перерви в рядку - я вважаю, що це краще, тому що тепер добре працює.
Toby Speight

1

Python 2.7 - 447B (розмір файлів)

Це моя перша спроба в Codegolf, сподіваюся, це задовольнить. Мені потрібно 2 години. (Але я все ще новачок у Python)

Редагувати: Дякуючи "Кевін Лау - не Кенні", що вказав на це:

  • Аргументи пітонів у класі можна замінити чим завгодно
  • відступ має бути лише одним пробілом
  • вбудований сортування - функція (я знав, що бачив це, але вважав, що це метод у списках)
  • __ radd __ не потрібен (я підтримую лише додавання B-об'єктів (тип мішка))

Редагувати: Крім того, я заощадив простір, замінивши функції лямбдатами та новими рядками та відступами більше крапками з комою.

Код:

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

чеки:

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

Вихід:

True
True
True
True
True
True
True
True
True
False

Я можу спробувати це іншим разом із встановленою базою деякий час. Редагувати: Можливо, я навіть спробую лише з функціями.


Ласкаво просимо до PPCG! Що слід зазначити про Python, це те, що вам насправді не потрібно викликати перші параметри в класових функціях self- щось подібне Sбуло б так само добре. Ще одна хитрість полягає в тому, що вбудована sortedфункція робить саме те, що ви хочете, від вашої нової функції s, так що ви можете відмовитися від визначення функції (бачачи, як ви використовуєте її лише один раз). Вам ніколи не потрібно, __radd__тому що ви ніколи не додаєте мішки з мішками, хоча вони все ще потрібні __rmul__. Нарешті, вам потрібно лише одне пробіл замість чотирьох, що зменшує кількість байтів зовсім небагато
Value Ink
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.