1

Тема: count_if чи звичайний цикл?

Треба знайти максимальну кількість чисел із наданих кандидатів, bitwise AND яких не дорівнює нулю.
Це сьогоднішнє завдання з Leetcode.
Ось два рішення:
Перше зі звичайним циклом.

int largestCombination(const vector<int> &candidates) {
    if (candidates.size() == 1) return 1;
    int answer { 0 };
    for (int i = 0; i < 24; ++i) {
        int count {0};
        for (const auto& item: candidates){
            if (item & (1 << i)){
                ++count;
            }
        }
        answer = max(answer, count);
    }
    return answer;
}

Друге з count_if.

int largestCombination(const vector<int> &candidates) {
    if (candidates.size() == 1) return 1;
    int answer { 0 };
    for (int i = 0; i < 24; ++i) {
        auto same_bit = [i](auto number) { return number & (1 << i); };
        int count = count_if(candidates.begin(), candidates.end(), same_bit);
        answer = max(answer, count);
    }
    return answer;
}

Що з цього краще?
При перевірці синтаксису мені порадили використати count_if,
але я не помітив значної різниці в швидкості виконання програми.

2

Re: count_if чи звичайний цикл?

Я в таких випадках віддаю перевагу простому циклу. І так видно, що відбувається. count_if дає перевагу лише з політикою виконання (execution policy) при досить великих вхідних даних.
Єдине що я б іншу послідовність операцій обрав: (item>>i)&1 виглядає природніше, бо повертає конкретно 0 або 1. Або навіть

for (int i = 1, end = 1 << 24; i < end; i <<= 1) {
    ... item & i ...
}

Утім, підозрюю, що оптимізатор і так витисне з коду більше, ніж усі ці фокуси (хоча це треба тестувати).

Подякували: Teg Miles, leofun012

3

Re: count_if чи звичайний цикл?

koala написав:

Я в таких випадках віддаю перевагу простому циклу. І так видно, що відбувається. count_if дає перевагу лише з політикою виконання (execution policy) при досить великих вхідних даних.
Єдине що я б іншу послідовність операцій обрав: (item>>i)&1 виглядає природніше, бо повертає конкретно 0 або 1. Або навіть

for (int i = 1, end = 1 << 24; i < end; i <<= 1) {
    ... item & i ...
}

Утім, підозрюю, що оптимізатор і так витисне з коду більше, ніж усі ці фокуси (хоча це треба тестувати).

Ваша пропозиція працює швидше з простим циклом, ніж з count_if.
Але не набагато швидше за те, що було раніше.
Я на їхньому сайті перевіряв.

4

Re: count_if чи звичайний цикл?

Teg Miles написав:

Треба знайти максимальну кількість чисел із наданих кандидатів, bitwise AND яких не дорівнює нулю.

Teg Miles, я знов не буду оригінальним: дайте будь ласка, пряме посилання на завдання, чи скопiюйте його тест дослівно.

5

Re: count_if чи звичайний цикл?

steamwater написав:
Teg Miles написав:

Треба знайти максимальну кількість чисел із наданих кандидатів, bitwise AND яких не дорівнює нулю.

Teg Miles, я знов не буду оригінальним: дайте будь ласка, пряме посилання на завдання, чи скопiюйте його тест дослівно.

Не пам'ятаю його назви. Та й воно давно вже вирішене.

6 Востаннє редагувалося steamwater (16.11.2024 21:38:46)

Re: count_if чи звичайний цикл?

Teg Miles написав:

Не пам'ятаю його назви. Та й воно давно вже вирішене.

Справа в тому, що по ключових словах я знайшов тiльки рiшення. Принаймнi, одне з них, отут, наприклад:
https://gfgpotd.com/2275-largest-combin … e_vignette
майже спiвпадає з тим що показали ви. Але текст задачi (мабуть неповний) зовсiм не вiдповiдає формулi:

Teg Miles написав:

Треба знайти максимальну кількість чисел із наданих кандидатів, bitwise AND яких не дорівнює нулю.

Тому й питаю. Досить дивно, що знайти пряме посилання на LeetCode менi не вдалося. Може погано шукаю, чи все ж таки це завдання не коректне й було видалене з сайту. Невiдомо.
Доречи, раджу вам першим коментом до коду рiшення робити щось таке:

//завдання з https//leetcode.com/bla-bla-bla

Дуже зручно.

7

Re: count_if чи звичайний цикл?

Здається, знайшов: https://leetcode.com/problems/largest-c … scription/
Teg Miles, чи це саме воно?

8

Re: count_if чи звичайний цикл?

steamwater написав:

Здається, знайшов: https://leetcode.com/problems/largest-c … scription/
Teg Miles, чи це саме воно?

Так, воно.

9

Re: count_if чи звичайний цикл?

Rust, де count_if реалізовано у природний спосіб (filter+count)

        (0..32).map(
                 |bit|candidates.iter()
                                .filter(|&&candidate|(candidate>>bit)&1==1)
                                .count()
              ).max()
              .unwrap() as i32

10 Востаннє редагувалося steamwater (16.11.2024 18:37:29)

Re: count_if чи звичайний цикл?

Teg Miles, в мене поки що два питання. Перше: Чи рiшення що ви привели, написанi вами власноруч? Друге буде потiм.

11

Re: count_if чи звичайний цикл?

steamwater написав:

Teg Miles, в мене поки що два питання. Перше: Чи рiшення що ви привели, написанi вами власноруч? Друге буде потiм.

Від мене там тільки count_if:) У мене не дуже з побітовими операціями поки що.

12

Re: count_if чи звичайний цикл?

Teg Miles написав:

Від мене там тільки count_if:) У мене не дуже з побітовими операціями поки що.

Я так i думав. А чи зрозумiли ви, що саме робить алгоритм у циклах? Це вже те, другу питання, пiсля якого можна було б перейти до std::count_if. Поки що, можу наперед сказати, що count_if реалiзовано як прямий послiдовний проход по заданому iтераторами, iнтервалу з перевiркою унарного предiкату на кожному елементi, пiдвищуючи лiчильник для true, який потiм повертається як результат. У складних випадках, таких як текучий, вiн не кращий за цикл, а враховуючи нетрiвiальнiсть задачи написання предiкату, - цикл гнучкіший, тому у цьому я пiдтримую позицiю koala.

13

Re: count_if чи звичайний цикл?

steamwater написав:
Teg Miles написав:

Від мене там тільки count_if:) У мене не дуже з побітовими операціями поки що.

Я так i думав. А чи зрозумiли ви, що саме робить алгоритм у циклах? Це вже те, другу питання, пiсля якого можна було б перейти до std::count_if. Поки що, можу наперед сказати, що count_if реалiзовано як прямий послiдовний проход по заданому iтераторами, iнтервалу з перевiркою унарного предiкату на кожному елементi, пiдвищуючи лiчильник для true, який потiм повертається як результат. У складних випадках, таких як текучий, вiн не кращий за цикл, а враховуючи нетрiвiальнiсть задачи написання предiкату, - цикл гнучкіший, тому у цьому я пiдтримую позицiю koala.

Зрозумів, там, де я брав код, було пояснення.

Подякували: steamwater1

14 Востаннє редагувалося steamwater (19.11.2024 04:55:17)

Re: count_if чи звичайний цикл?

Я трохи поквапився з висновками, виклавши сирий код.
А уточнений дав тi ж результати, але значно повiльнiше. Тому видалив.