Sự kết hợp Java và Python

Đầu tiên, chúng ta sẽ thảo luận và triển khai cả thuật toán đệ quy và thuật toán lặp để tạo ra tất cả các kết hợp có kích thước nhất định. Sau đó, chúng tôi sẽ xem xét các giải pháp sử dụng các thư viện Java phổ biến

2. Tổng quan về kết hợp

Nói một cách đơn giản, một sự kết hợp là một tập hợp con của các phần tử từ một tập hợp nhất định

Không giống như hoán vị, thứ tự chúng ta chọn các phần tử riêng lẻ không quan trọng. Thay vào đó, chúng ta chỉ quan tâm liệu một phần tử cụ thể có nằm trong vùng chọn hay không

Ví dụ, trong một trò chơi bài, chúng ta phải chia 5 quân bài trong bộ gồm 52 quân bài. Chúng tôi không quan tâm đến thứ tự chọn 5 thẻ. Thay vào đó, chúng tôi chỉ quan tâm những lá bài nào có trong tay

Một số vấn đề yêu cầu chúng tôi đánh giá tất cả các kết hợp có thể. Để làm điều này, chúng tôi liệt kê các kết hợp khác nhau

Số cách khác nhau để chọn phần tử “r” từ tập hợp phần tử “n” có thể được biểu diễn bằng toán học theo công thức sau

Sự kết hợp Java và Python

Do đó, số cách chọn phần tử có thể tăng theo cấp số nhân trong trường hợp xấu nhất. Do đó, đối với các quần thể lớn, có thể không liệt kê được các lựa chọn khác nhau

Trong những trường hợp như vậy, chúng tôi có thể chọn ngẫu nhiên một vài lựa chọn đại diện. Quá trình này được gọi là lấy mẫu

Tiếp theo, chúng tôi sẽ xem xét các thuật toán khác nhau để liệt kê các kết hợp

3. Thuật toán đệ quy để tạo kết hợp

Các thuật toán đệ quy thường hoạt động bằng cách phân vùng một vấn đề thành các vấn đề nhỏ hơn tương tự. Quá trình này tiếp tục cho đến khi chúng ta đạt đến điều kiện kết thúc, đây cũng là trường hợp cơ sở. Sau đó, chúng tôi giải quyết trường hợp cơ sở trực tiếp

Chúng ta sẽ thảo luận về hai cách để chia nhỏ nhiệm vụ chọn các phần tử từ một tập hợp. Cách tiếp cận đầu tiên phân chia vấn đề theo các phần tử trong tập hợp. Cách tiếp cận thứ hai phân chia vấn đề bằng cách chỉ theo dõi các phần tử đã chọn

3. 1. Phân vùng theo các phần tử trong toàn bộ tập hợp

Hãy phân chia nhiệm vụ chọn “r” phần tử từ “n” mục bằng cách kiểm tra từng mục một. Đối với mỗi mục trong bộ, chúng tôi có thể đưa nó vào lựa chọn hoặc loại trừ nó

Nếu chúng tôi bao gồm mục đầu tiên, thì chúng tôi cần chọn phần tử “r – 1″ từ “n – 1″ mục còn lại. Mặt khác, nếu chúng ta loại bỏ mục đầu tiên, thì chúng ta cần chọn phần tử “r” trong số “n – 1” phần tử còn lại

Điều này có thể được biểu thị bằng toán học như

Sự kết hợp Java và Python

Bây giờ, hãy xem xét việc triển khai đệ quy của phương pháp này

private void helper(List combinations, int data[], int start, int end, int index) {
    if (index == data.length) {
        int[] combination = data.clone();
        combinations.add(combination);
    } else if (start <= end) {
        data[index] = start;
        helper(combinations, data, start + 1, end, index + 1);
        helper(combinations, data, start + 1, end, index);
    }
}

Phương thức trợ giúp thực hiện hai cuộc gọi đệ quy tới chính nó. Cuộc gọi đầu tiên bao gồm phần tử hiện tại. Cuộc gọi thứ hai loại bỏ phần tử hiện tại

Tiếp theo, hãy viết trình tạo kết hợp bằng phương thức trợ giúp này

public List generate(int n, int r) {
    List combinations = new ArrayList<>();
    helper(combinations, new int[r], 0, n-1, 0);
    return combinations;
}

Trong đoạn mã trên, phương thức tạo thiết lập cuộc gọi đầu tiên đến phương thức trợ giúp và chuyển các tham số thích hợp

Tiếp theo, hãy gọi phương thức này để tạo kết hợp

List combinations = generate(N, R);
for (int[] combination : combinations) {
    System.out.println(Arrays.toString(combination));
}
System.out.printf("generated %d combinations of %d items from %d ", combinations.size(), R, N);

Khi thực hiện chương trình, chúng tôi nhận được đầu ra sau

[0, 1]
[0, 2]
[0, 3]
[0, 4]
[1, 2]
[1, 3]
[1, 4]
[2, 3]
[2, 4]
[3, 4]
generated 10 combinations of 2 items from 5

Cuối cùng, hãy viết test case

@Test
public void givenSetAndSelectionSize_whenCalculatedUsingSetRecursiveAlgorithm_thenExpectedCount() {
    SetRecursiveCombinationGenerator generator = new SetRecursiveCombinationGenerator();
    List selection = generator.generate(N, R);
    assertEquals(nCr, selection.size());
}

Dễ dàng nhận thấy rằng kích thước ngăn xếp cần thiết là số phần tử trong tập hợp. Khi số lượng phần tử trong tập hợp lớn, chẳng hạn như lớn hơn độ sâu tối đa của ngăn xếp cuộc gọi, chúng tôi sẽ làm tràn ngăn xếp và nhận được lỗi StackOverflowError

Do đó, phương pháp này không hoạt động nếu bộ đầu vào lớn

3. 2. Phân vùng theo các phần tử trong tổ hợp

Thay vì theo dõi các phần tử trong tập hợp đầu vào, chúng tôi sẽ phân chia nhiệm vụ bằng cách theo dõi các mục trong vùng chọn

Trước tiên, hãy sắp xếp thứ tự các mục trong bộ đầu vào bằng cách sử dụng các chỉ số “1” đến “n”. Bây giờ, chúng ta có thể chọn mục đầu tiên từ “n-r+1″ mục đầu tiên

Giả sử rằng chúng ta đã chọn mục thứ k. Sau đó, chúng ta cần chọn “r – 1″ mục từ “n – k” mục còn lại được lập chỉ mục “k + 1″ đến “n”

Chúng tôi thể hiện quá trình này một cách toán học như

Sự kết hợp Java và Python

Tiếp theo, hãy viết phương thức đệ quy để thực hiện phương pháp này

private void helper(List combinations, int data[], int start, int end, int index) {
    if (index == data.length) {
        int[] combination = data.clone();
        combinations.add(combination);
    } else {
        int max = Math.min(end, end + 1 - data.length + index);
        for (int i = start; i <= max; i++) {
            data[index] = i;
            helper(combinations, data, i + 1, end, index + 1);
        }
    }
}

Trong đoạn mã trên, vòng lặp for chọn mục tiếp theo, Sau đó, nó gọi đệ quy phương thức helper() để chọn các mục còn lại. Chúng tôi dừng lại khi số lượng mục cần thiết đã được chọn

Tiếp theo, hãy sử dụng phương thức trợ giúp để tạo các lựa chọn

public List generate(int n, int r) {
    List combinations = new ArrayList<>();
    helper(combinations, new int[r], 0, n - 1, 0);
    return combinations;
}

Cuối cùng, hãy viết một trường hợp thử nghiệm

@Test
public void givenSetAndSelectionSize_whenCalculatedUsingSelectionRecursiveAlgorithm_thenExpectedCount() {
    SelectionRecursiveCombinationGenerator generator = new SelectionRecursiveCombinationGenerator();
    List selection = generator.generate(N, R);
    assertEquals(nCr, selection.size());
}

Kích thước ngăn xếp cuộc gọi được sử dụng bởi phương pháp này giống như số lượng phần tử trong lựa chọn. Do đó, phương pháp này có thể hoạt động đối với các đầu vào lớn miễn là số lượng phần tử được chọn nhỏ hơn độ sâu ngăn xếp cuộc gọi tối đa

Nếu số lượng phần tử được chọn cũng lớn, phương pháp này sẽ không hoạt động

4. Thuật toán lặp

Trong cách tiếp cận lặp đi lặp lại, chúng tôi bắt đầu với một sự kết hợp ban đầu. Sau đó, chúng tôi tiếp tục tạo kết hợp tiếp theo từ kết hợp hiện tại cho đến khi chúng tôi tạo tất cả các kết hợp

Hãy tạo các kết hợp theo thứ tự từ điển. Chúng tôi bắt đầu với sự kết hợp từ điển thấp nhất

Để có được kết hợp tiếp theo từ kết hợp hiện tại, chúng tôi tìm vị trí ngoài cùng bên phải trong kết hợp hiện tại có thể tăng dần. Sau đó, chúng tôi tăng vị trí và tạo tổ hợp từ điển thấp nhất có thể ở bên phải của vị trí đó

Hãy viết mã theo cách tiếp cận này

________số 8

Tiếp theo, hãy viết test case

@Test
public void givenSetAndSelectionSize_whenCalculatedUsingIterativeAlgorithm_thenExpectedCount() {
    IterativeCombinationGenerator generator = new IterativeCombinationGenerator();
    List selection = generator.generate(N, R);
    assertEquals(nCr, selection.size());
}

Bây giờ, chúng ta hãy sử dụng một số thư viện Java để giải quyết vấn đề

5. Thư viện Java Triển khai kết hợp

Trong chừng mực có thể, chúng ta nên sử dụng lại các triển khai thư viện hiện có thay vì triển khai triển khai của riêng mình. Trong phần này, chúng ta sẽ khám phá các thư viện Java sau triển khai các kết hợp

  • Apache Commons
  • Trái ổi
  • Tổ hợpLib

5. 1. Apache Commons

Lớp CombinatoricsUtils từ Apache Commons cung cấp nhiều hàm tiện ích kết hợp. Cụ thể, phương thức này trả về một trình vòng lặp sẽ tạo ra các kết hợp theo thứ tự từ điển

Trước tiên, hãy thêm phụ thuộc Maven commons-math3 vào dự án

public List generate(int n, int r) {
    List combinations = new ArrayList<>();
    helper(combinations, new int[r], 0, n-1, 0);
    return combinations;
}
0

Tiếp theo, hãy sử dụng phương thức tổ hợpIterator để in các tổ hợp

public List generate(int n, int r) {
    List combinations = new ArrayList<>();
    helper(combinations, new int[r], 0, n-1, 0);
    return combinations;
}
1

5. 2. Ổi Google

Lớp Sets từ thư viện Guava cung cấp các phương thức tiện ích cho các hoạt động liên quan đến set. Phương thức trả về tất cả các tập hợp con của một kích thước nhất định

Đầu tiên, hãy thêm phụ thuộc maven cho thư viện Guava vào dự án

public List generate(int n, int r) {
    List combinations = new ArrayList<>();
    helper(combinations, new int[r], 0, n-1, 0);
    return combinations;
}
2

Tiếp theo, hãy sử dụng phương pháp kết hợp để tạo kết hợp

public List generate(int n, int r) {
    List combinations = new ArrayList<>();
    helper(combinations, new int[r], 0, n-1, 0);
    return combinations;
}
3

Ở đây, chúng tôi đang sử dụng ImmutableSet. của phương pháp để tạo một tập hợp từ các số đã cho

5. 3. Tổ hợpLib

CombinatoricsLib là một thư viện Java nhỏ và đơn giản dành cho hoán vị, tổ hợp, tập con, phân hoạch số nguyên và tích cartesian

Để sử dụng nó trong dự án, hãy thêm phụ thuộc maven combinatoricslib3

public List generate(int n, int r) {
    List combinations = new ArrayList<>();
    helper(combinations, new int[r], 0, n-1, 0);
    return combinations;
}
4

Tiếp theo, hãy sử dụng thư viện để in các kết hợp

public List generate(int n, int r) {
    List combinations = new ArrayList<>();
    helper(combinations, new int[r], 0, n-1, 0);
    return combinations;
}
5

Điều này tạo ra đầu ra sau khi thực hiện

public List generate(int n, int r) {
    List combinations = new ArrayList<>();
    helper(combinations, new int[r], 0, n-1, 0);
    return combinations;
}
6

Nhiều ví dụ hơn có sẵn tại combinatoricslib3-example

6. Phần kết luận

Trong bài viết này, chúng tôi đã triển khai một số thuật toán để tạo kết hợp

Chúng tôi cũng đã xem xét một vài triển khai thư viện. Thông thường, chúng tôi sẽ sử dụng những thứ này thay vì tự lăn

Python và Java có phải là một sự kết hợp tốt không?

Vì những lý do này, Python phù hợp hơn nhiều với tư cách là ngôn ngữ "keo", trong khi Java được coi là ngôn ngữ triển khai cấp thấp tốt hơn. Trên thực tế, cả hai cùng nhau tạo nên một sự kết hợp tuyệt vời .

Bạn có thể sử dụng Python trong Java không?

Có thể sử dụng lớp này trong mã Java được gọi từ trình thông dịch Python hoặc có thể sử dụng lớp này trong Java để chạy Python nhúng trong Java . Lớp CPython liên kết trình thông dịch Python với JVM và cung cấp khả năng thực thi các tập lệnh Python. Tranh luận. tập lệnh – Tập lệnh Python để thực thi.

Tôi có thể kiếm một công việc với Python và Java không?

Không. Chỉ Python thôi sẽ không đủ để kiếm việc làm .

Kết hợp tốt với Python là gì?

Ngôn ngữ hoàn hảo là sự kết hợp giữa Java và Python.