Task: Sum and product puzzle


C++: #include <algorithm>
#include <iostream>
#include <map>
#include <vector>

std::ostream &operator<<(std::ostream &os, std::vector<std::pair<int, int>> &v) {
    for (auto &p : v) {
        auto sum = p.first + p.second;
        auto prod = p.first * p.second;
        os << '[' << p.first << ", " << p.second << "] S=" << sum << " P=" << prod;
    }
    return os << '\n';
}

void print_count(const std::vector<std::pair<int, int>> &candidates) {
    auto c = candidates.size();
    if (c == 0) {
        std::cout << "no candidates\n";
    } else if (c == 1) {
        std::cout << "one candidate\n";
    } else {
        std::cout << c << " candidates\n";
    }
}

auto setup() {
    std::vector<std::pair<int, int>> candidates;

    
    for (int x = 2; x <= 98; x++) {
        
        for (int y = x + 1; y <= 98; y++) {
            if (x + y <= 100) {
                candidates.push_back(std::make_pair(x, y));
            }
        }
    }

    return candidates;
}

void remove_by_sum(std::vector<std::pair<int, int>> &candidates, const int sum) {
    candidates.erase(std::remove_if(
        candidates.begin(), candidates.end(),
        [sum](const std::pair<int, int> &pair) {
            auto s = pair.first + pair.second;
            return s == sum;
        }
    ), candidates.end());
}

void remove_by_prod(std::vector<std::pair<int, int>> &candidates, const int prod) {
    candidates.erase(std::remove_if(
        candidates.begin(), candidates.end(),
        [prod](const std::pair<int, int> &pair) {
            auto p = pair.first * pair.second;
            return p == prod;
        }
    ), candidates.end());
}

void statement1(std::vector<std::pair<int, int>> &candidates) {
    std::map<int, int> uniqueMap;

    std::for_each(
        candidates.cbegin(), candidates.cend(),
        [&uniqueMap](const std::pair<int, int> &pair) {
            auto prod = pair.first * pair.second;
            uniqueMap[prod]++;
        }
    );

    bool loop;
    do {
        loop = false;
        for (auto &pair : candidates) {
            auto prod = pair.first * pair.second;
            if (uniqueMap[prod] == 1) {
                auto sum = pair.first + pair.second;
                remove_by_sum(candidates, sum);

                loop = true;
                break;
            }
        }
    } while (loop);
}

void statement2(std::vector<std::pair<int, int>> &candidates) {
    std::map<int, int> uniqueMap;

    std::for_each(
        candidates.cbegin(), candidates.cend(),
        [&uniqueMap](const std::pair<int, int> &pair) {
            auto prod = pair.first * pair.second;
            uniqueMap[prod]++;
        }
    );

    bool loop;
    do {
        loop = false;
        for (auto &pair : candidates) {
            auto prod = pair.first * pair.second;
            if (uniqueMap[prod] > 1) {
                remove_by_prod(candidates, prod);

                loop = true;
                break;
            }
        }
    } while (loop);
}

void statement3(std::vector<std::pair<int, int>> &candidates) {
    std::map<int, int> uniqueMap;

    std::for_each(
        candidates.cbegin(), candidates.cend(),
        [&uniqueMap](const std::pair<int, int> &pair) {
            auto sum = pair.first + pair.second;
            uniqueMap[sum]++;
        }
    );

    bool loop;
    do {
        loop = false;
        for (auto &pair : candidates) {
            auto sum = pair.first + pair.second;
            if (uniqueMap[sum] > 1) {
                remove_by_sum(candidates, sum);

                loop = true;
                break;
            }
        }
    } while (loop);
}

int main() {
    auto candidates = setup();
    print_count(candidates);

    statement1(candidates);
    print_count(candidates);

    statement2(candidates);
    print_count(candidates);

    statement3(candidates);
    print_count(candidates);

    std::cout << candidates;

    return 0;
}




Java: package org.rosettacode;

import java.util.ArrayList;
import java.util.List;



public class SumAndProductPuzzle {
    private final long beginning;
    private final int maxSum;
    private static final int MIN_VALUE = 2;
    private List<int[]> firstConditionExcludes = new ArrayList<>();
    private List<int[]> secondConditionExcludes = new ArrayList<>();
    
    public static void main(String... args){
        
        if (args.length == 0){
            new SumAndProductPuzzle(100).run();
            new SumAndProductPuzzle(1684).run();
            new SumAndProductPuzzle(1685).run();
        } else {
            for (String arg : args){
                try{
                    new SumAndProductPuzzle(Integer.valueOf(arg)).run();
                } catch (NumberFormatException e){
                    System.out.println("Please provide only integer arguments. " +
                            "Provided argument " + arg + " was not an integer. " +
                            "Alternatively, calling the program with no arguments " +
                            "will run the puzzle where maximum sum equals 100, 1684, and 1865.");
                }
            }
        }
    }
    
    public SumAndProductPuzzle(int maxSum){
        this.beginning = System.currentTimeMillis();
        this.maxSum = maxSum;
        System.out.println("Run with maximum sum of " + String.valueOf(maxSum) + 
                " started at " + String.valueOf(beginning) + ".");
    }
    
    public void run(){
        for (int x = MIN_VALUE; x < maxSum - MIN_VALUE; x++){
            for (int y = x + 1; y < maxSum - MIN_VALUE; y++){
                
                if (isSumNoGreaterThanMax(x,y) &&
                    isSKnowsPCannotKnow(x,y) &&
                    isPKnowsNow(x,y) &&
                    isSKnowsNow(x,y)
                    ){
                    System.out.println("Found solution x is " + String.valueOf(x) + " y is " + String.valueOf(y) + 
                            " in " + String.valueOf(System.currentTimeMillis() - beginning) + "ms.");
                }
            }
        }
        System.out.println("Run with maximum sum of " + String.valueOf(maxSum) + 
                " ended in " + String.valueOf(System.currentTimeMillis() - beginning) + "ms.");
    }
    
    public boolean isSumNoGreaterThanMax(int x, int y){
        return x + y <= maxSum;
    }
    
    public boolean isSKnowsPCannotKnow(int x, int y){
        
        if (firstConditionExcludes.contains(new int[] {x, y})){
            return false;
        }
        
        for (int[] addends : sumAddends(x, y)){
            if ( !(productFactors(addends[0], addends[1]).size() > 1) ) {
                firstConditionExcludes.add(new int[] {x, y});
                return false;
            }
        }
        return true;
    }
    
    public boolean isPKnowsNow(int x, int y){
        
        if (secondConditionExcludes.contains(new int[] {x, y})){
            return false;
        }
        
        int countSolutions = 0;
        for (int[] factors : productFactors(x, y)){
            if (isSKnowsPCannotKnow(factors[0], factors[1])){
                countSolutions++;
            }
        }
        
        if (countSolutions == 1){
            return true;
        } else {
            secondConditionExcludes.add(new int[] {x, y});
            return false;
        }
    }
    
    public boolean isSKnowsNow(int x, int y){
        
        int countSolutions = 0;
        for (int[] addends : sumAddends(x, y)){
            if (isPKnowsNow(addends[0], addends[1])){
                countSolutions++;
            }
        }
        return countSolutions == 1;
    }
    
    public List<int[]> sumAddends(int x, int y){
        
        List<int[]> list = new ArrayList<>();
        int sum = x + y;
        
        for (int addend = MIN_VALUE; addend < sum - addend; addend++){
            if (isSumNoGreaterThanMax(addend, sum - addend)){
                list.add(new int[]{addend, sum - addend});
            }
        }
        return list;
    }
    
    public List<int[]> productFactors(int x, int y){
        
        List<int[]> list = new ArrayList<>();
        int product = x * y;
        
        for (int factor = MIN_VALUE; factor < product / factor; factor++){
            if (product % factor == 0){
                if (isSumNoGreaterThanMax(factor, product / factor)){
                    list.add(new int[]{factor, product / factor});
                }
            }
        }
        return list;
    }
}