/*==============================================================================
  Лабораторна робота №1. Завдання 2. Варіант 19.
  Тема: типи даних, функції введення-виведення, обчислення виразів.

  Умова: нехай число ab містить цифри a і b. Довести, що число ab + ba
         ділиться на 11.

  Аналіз задачі (аналітичне обґрунтування).
      Двоцифрове число ab у позиційній десятковій системі має значення
              ab = 10*a + b,
      а число, записане тими самими цифрами у зворотному порядку,
              ba = 10*b + a.
      Тоді
              ab + ba = (10a + b) + (10b + a) = 11a + 11b = 11*(a + b).
      Отже сума є добутком числа 11 на ціле число (a + b), тобто ділиться
      на 11 без остачі, причому частка дорівнює сумі цифр. Що й треба було
      довести.

  Метод програмної перевірки: програма
      1) обчислює ab + ba для введеного користувачем числа і показує
         покроково всі складові тотожності;
      2) виконує вичерпну перевірку тотожності для ВСІХ двоцифрових чисел
         (a = 1..9, b = 0..9) — обчислювальне підтвердження доведення.

  Введення-виведення: об'єкти класів потоків std::cin / std::cout
         (форматне введення-виведення scanf/printf застосовано в завданні 1).

  Виконав: Одарчук Олексій, КНУ імені Тараса Шевченка, ФІТ, група ІПЗ-11.

  Компілятор: g++ -std=c++17
==============================================================================*/

#include <iostream>

/*------------------------------------------------------------------------------
  reverseTwoDigit — побудувати число з переставленими цифрами.

  Параметри:
      n [вхідний] — двоцифрове число ab (10..99).

  Повертає: число ba = 10*b + a.

  Локальні змінні:
      a — цифра десятків числа n;
      b — цифра одиниць числа n.
------------------------------------------------------------------------------*/
int reverseTwoDigit(int n)
{
    const int a = n / 10;
    const int b = n % 10;
    return 10 * b + a;
}

/*------------------------------------------------------------------------------
  proveForAll — вичерпна перевірка тотожності ab + ba = 11*(a+b) для всіх
                двоцифрових чисел.

  Параметри: немає.

  Повертає: true — тотожність виконується для всіх 90 двоцифрових чисел;
            false — знайдено контрприклад (теоретично неможливо).

  Локальні змінні:
      a, b     — цифри числа;
      ab, ba   — саме число та число з переставленими цифрами;
      sum      — їх сума;
      checked  — кількість перевірених випадків.
------------------------------------------------------------------------------*/
bool proveForAll()
{
    int checked = 0;

    for (int a = 1; a <= 9; ++a) {
        for (int b = 0; b <= 9; ++b) {
            const int ab = 10 * a + b;
            const int ba = 10 * b + a;
            const int sum = ab + ba;

            if (sum % 11 != 0 || sum / 11 != a + b)
                return false; /* контрприклад */

            ++checked;
        }
    }

    std::cout << "Перевірено випадків: " << checked
              << " — тотожність виконується для всіх двоцифрових чисел.\n";
    return true;
}

/*------------------------------------------------------------------------------
  readTwoDigit — прочитати двоцифрове число з контролем коректності введення.

  Якщо введено не число або число поза межами 10..99, прапорець помилки
  потоку знімається, залишок рядка відкидається і запит повторюється.

  Параметри: n [вихідний] — адреса змінної для введеного числа.
  Повертає : true — число прочитано; false — вхідні дані вичерпано.
------------------------------------------------------------------------------*/
bool readTwoDigit(int *n)
{
    std::cout << "Уведіть двоцифрове число ab (10..99): ";

    while (!(std::cin >> *n) || *n < 10 || *n > 99) {
        if (std::cin.eof())
            return false;

        std::cin.clear();            /* зняти прапорець помилки */
        std::cin.ignore(1024, '\n'); /* очистити буфер клавіатури */
        std::cout << "Помилка: потрібне ціле число від 10 до 99. Повторіть: ";
    }
    return true;
}

/*------------------------------------------------------------------------------
  Головна функція. Читає двоцифрове число, демонструє тотожність на ньому
  та виконує вичерпну перевірку.

  Локальні змінні:
      n      — введене двоцифрове число ab;
      a, b   — його цифри;
      ba     — число з переставленими цифрами;
      sum    — сума ab + ba.
------------------------------------------------------------------------------*/
int main()
{
    std::cout << "Лабораторна робота №1, завдання 2 (варіант 19)\n"
                 "Виконав: студент групи ІПЗ-11 Одарчук Олексій\n"
                 "Доведення: ab + ba ділиться на 11\n"
              << std::endl;

    int n = 0;
    if (!readTwoDigit(&n)) {
        std::cout << "\nВхідні дані вичерпано." << std::endl;
        return 1;
    }

    const int a = n / 10;
    const int b = n % 10;
    const int ba = reverseTwoDigit(n);
    const int sum = n + ba;

    std::cout << "\nЦифри числа: a = " << a << ", b = " << b << std::endl;
    std::cout << "  ab = 10*a + b = 10*" << a << " + " << b << " = " << n << std::endl;
    std::cout << "  ba = 10*b + a = 10*" << b << " + " << a << " = " << ba << std::endl;
    std::cout << "  ab + ba = " << n << " + " << ba << " = " << sum << std::endl;
    std::cout << "  11*(a + b) = 11*(" << a << " + " << b << ") = " << 11 * (a + b)
              << std::endl;
    std::cout << "  " << sum << " / 11 = " << sum / 11 << ", остача = " << sum % 11
              << std::endl;

    if (sum % 11 == 0)
        std::cout << "\nСума ділиться на 11 без остачі." << std::endl;
    else
        std::cout << "\nСума НЕ ділиться на 11." << std::endl;

    std::cout << "\nВичерпна перевірка тотожності ab + ba = 11*(a + b):" << std::endl;
    if (!proveForAll())
        std::cout << "Знайдено контрприклад — тотожність хибна." << std::endl;

    return 0;
}
