Home > Back-end >  Don't pass Kattis patuljci problem 13/14 test case
Don't pass Kattis patuljci problem 13/14 test case

Time:11-28

I have been trying this open.kattis.com problem but I don't know why the 13/14 test keeps giving me the wrong answer. I have already tried different solutions but keep giving me the same test case, I don't know if a declare some variables in the wrong way.

link to the problem

#include <iostream>

using namespace std;

int main(){
    int arr[9];
    int find = 0 , x, y;
    bool found = false;

    for(int i = 0; i < 9; i  ){
        cin >> arr[i];
        find  = arr[i];
    }

    find -= 100;

    for(int first = 0; first < 8; first  ){
        for(int second = first; second < 9; second  ){
            if(arr[second]   arr[first] == find){
                x = first;
                y = second;
                found = true;
                break;
            }
        }
        if(found)
            break;
    }

    for(int i = 0; i < 9; i  )
        if(i == x || i == y)
            continue;
        else
            cout << arr[i] << endl;

    
}

CodePudding user response:

Consider the following test case:

8 3 1 5 30 15 12 22 10

Note that: 3 3 == 1 5

In the posted code, the nested loop checking the dwarves looks like this

for ( int first = 0; first < 8; first  ) {
    for( int second = first; second < 9; second  ) {
        //   ^^^^^^^^^^^^^^
        // ...
    }
}

Meaning that it's considering the same dwarf twice, while it should be looking for two distinct ones:

for ( int first = 0; first < 8; first  ) {
    for( int second = first   1; second < 9; second  ) {
        //   ^^^^^^^^^^^^^^^^^^ Just pick the next one
        // ...
    }
}

CodePudding user response:

First we need to analyze the task and then draft a solution.

The given problem is related to combinatorics. We should select k elements from n overall elements and check, if they fulfill a condition (sum == 100).

This is called "n choose k". Therory can be found here.

For getting such combinations there is a standard approach in C . We use a so called Selector. The Selector selects k elements from the overall input data. And then we calculate all permutations of the Selector and use it in a loop, to select source data and add it up (if selected).

Some picture will help to understand better.

Assume 4 choose 2

Base Data:  1,2,3,4

            ^ ^ ^ ^
            | | | |

Selector:   0,0,1,1  --> 3,4
            0,1,1,0  --> 2,3
            0,1,0,1  --> 2,4
            1,0,0,1  --> 1,4
            1,0,1,0  --> 1,3
            1,1,0,0  --> 1,2

So, we can build a selector array and then select elements accordingly.

For the example at hand, we can use precalculated values, since 9 choose 7 is 36, so a small number.

So. selectors converted int number would be:

1       001111111  -- > 127
2       010111111  -- > 191
3       011011111  -- > 223
4       011101111  -- > 239
5       011110111  -- > 247
6       011111011  -- > 251
7       011111101  -- > 253
8       011111110  -- > 254
9       100111111  -- > 319
10      101011111  -- > 351
11      101101111  -- > 367
12      101110111  -- > 375
13      101111011  -- > 379
14      101111101  -- > 381
15      101111110  -- > 382
16      110011111  -- > 415
17      110101111  -- > 431
18      110110111  -- > 439
19      110111011  -- > 443
20      110111101  -- > 445
21      110111110  -- > 446
22      111001111  -- > 463
23      111010111  -- > 471
24      111011011  -- > 475
25      111011101  -- > 477
26      111011110  -- > 478
27      111100111  -- > 487
28      111101011  -- > 491
29      111101101  -- > 493
30      111101110  -- > 494
31      111110011  -- > 499
32      111110101  -- > 501
33      111110110  -- > 502
34      111111001  -- > 505
35      111111010  -- > 506
36      111111100  -- > 508

We can then use bit masking operations, to check, if a bit is set and then select the corresponding data.

One of many many possible solutions would be:

#include <iostream>

int main() {

    // Get user data
    unsigned int data[9] = {7,8,10,13,15,19,20,23,25};
    for (unsigned int k = 0; k < 9;   k) std::cin >> data[k];

    // Precomputed selectors
    unsigned int selector[36] = { 127,191,223,239,247,251,253,254,319,351,367,375,379,381,382,415,431,439,443,445,446,463,471,475,477,478,487,491,493,494,499,501,502,505,506,508 };

    // Go through all possible combinations of 9 choose 7
    for (unsigned k = 0; k < 36;   k) {

        // For masking out bits in the selector
        unsigned int mask = 1;

        // Accumulating, if selected
        unsigned int sum = 0;

        // Check, if selected
        for (unsigned int b = 0; b < 9;   b) {
            if (selector[k] & mask)
                sum  = data[b];
            mask <<= 1;
        }

        // Ceck if sum fulfils  requirement
        if (sum == 100) {
            mask = 1;
            // Output selected result
            for (unsigned int b = 0; b < 9;   b) {
                if (selector[k] & mask)
                    std::cout << data[b] << '\n';
            }
        }
    }
}


And the idiomatic correct approach using C algorithms could look like the below:

#include <iostream>
#include <vector>
#include <array>
#include <algorithm>
#include <iterator>
#include <numeric>

constexpr unsigned int TargetSum = 100u;
constexpr size_t NumberOverall = 9u;
constexpr size_t SelectedNumbers = 7u;

int main() {
    // Get source data from std::cin
    std::array<int, NumberOverall> data{ 7,8,10,13,15,19,20,23,25 };
    //for (int& i : data) std::cin >> i;
    
    // Define the selector with the same size as the input data vector
    std::vector<bool> selector(NumberOverall);

    // Set subSetSize elements in the selector element to true
    std::fill(selector.begin(), std::next(selector.begin(), SelectedNumbers), true);

    do {
        // Calculate the sum of selectedelement
        if (std::accumulate(data.begin(), data.end(), 0, [&, k = 0u](int sum, int i) mutable {if (selector[k  ]) sum  = i; return sum; }) == TargetSum) {

            // Show result
            std::copy_if(data.begin(), data.end(), std::ostream_iterator<int>(std::cout, "\n"), [&, k = 0u] (const int i) mutable{return selector[k  ];});
        }
        // Create the next permutation
    } while (std::prev_permutation(selector.begin(), selector.end()));
}

  • Related