%% Hádanka
% Jsou dána dvě přirozená čísla a,b>1. Ctirad zná pouze jejich součin a\cdot b, Damián zná pouze součet a+b. Na základě jejich rozhovoru o číslech a,b najděte tato čísla, pokud víte, že jsou oba excelentní matematici.
% Ctirad: Nevím, která jsou to čísla.
% Damián: To jsem vědel.
% Ctirad: A tak já už je vím.
% Damián: No já teď už taky!
%% Formalizace
% Označme
% \begin{array}{l}
% a\cdot b=c,\\
% a+b=d\ldotp
% \end{array}
% Z jednotlivých výroků po řadě plyne:
% a,b nejsou současně obě prvočísla.
% d=a+b nelze vyjádřit jako součet dvou prvočísel.
% Z možných faktorizací c na součin dvou čísel c_1 ,c_2 právě jedna možnost \left\lbrace c_1 ,c_2 \right\rbrace =\left\lbrace a,b\right\rbrace splňuje 2., kde c_1 +c_2 vystoupí v roli d.
% Z možných rozkladů d na součet dvou sčítanců d_1 ,d_2 právě jedna možnost \left\lbrace d_1 ,d_2 \right\rbrace =\left\lbrace a,b\right\rbrace splňuje, že d_1 \cdot d_2 splňuje 3., kde d_1 \cdot d_2 vystoupí v roli c.

clear
seznam = [];

%
% Hledáme a testujeme vlastnost 4. ( předchozí vlastnosti jsou v tom zahrnuty). Bereme v úvahu, že uvažujeme pouze součiny menší než 100.

for a = 2:50
    for b = a:50
        if a*b >= 100
            continue
        end
        if ctyri(a, b)
            seznam = [seznam; a, b]; %#ok<AGROW> 
        end
    end
end

% Vypíšeme nalezená řešení:

disp(seznam)

%
%% Funkce
% Kontrola vlastnosti 4.:

function tf = ctyri(a, b)
    d = a + b;
    
    % připravíme všechny sčítance mimo 1, d-1 (jednička nás nezajímá)
    soucty = [(2:floor(d/2))', d-(2:floor(d/2))'];
    
    % připravíme pole pro výsledky kontroly všech součtů
    varianty = false(size(soucty, 1), 1);
    
    % projdeme všechny součty
    for i = 1:length(varianty)
        varianty(i) = tri(soucty(i, 1)*soucty(i, 2), a, b);
    end
    
    % kontrola je úspěšná, jestliže vlastnost 3. splňuje právě jeden součet
    tf = sum(varianty) == 1;
    
    % ...a je to právě dvojice a, b
    tf = tf && tri(a*b, a, b);
end

% Kontrola vlastnosti 3.:

function tf = tri(c, a, b)
    % připravíme všechny součinitele
    kandidati = 2:ceil(sqrt(c));
    k = kandidati(rem(c, kandidati) == 0);
    souciny = [k', c./k'];
    
    % připravíme pole pro výsledky kontroly všech součinů
    varianty = false(size(souciny, 1), 1);
    
    % projdeme všechny součiny
    for i = 1:length(varianty)
        varianty(i) = dva(souciny(i, 1), souciny(i, 2));
    end
    
    % kontrola je úspěšná, jestliže vlastnost 2. splňuje právě jeden součin
    tf = sum(varianty) == 1;
    
    % ...a je to právě dvojice a, b
    tf = tf && dva(a, b);
end

% Kontrola vlastnosti 2.:

function tf = dva(a, b)
    d = a + b;

    % připravíme pole pro výsledky kontroly všech součtů
    varianty = false(floor(d/2), 1);
    
    % projdeme všechny součty mimo 1, d-1 (jednička nás nezajímá)
    for i = 2:length(varianty)
        varianty(i) = isprime(i) && isprime(d-i);
    end
    
    % kontrola je úspěšná, jestliže neexistuje rozklad na součet prvočísel
    tf = sum(varianty) == 0;         
end

%