|
@@ -0,0 +1,218 @@
|
|
|
|
|
+import tkinter as tk
|
|
|
|
|
+from tkinter import messagebox
|
|
|
|
|
+import sqlite3
|
|
|
|
|
+import math
|
|
|
|
|
+
|
|
|
|
|
+class TaxicabFinder:
|
|
|
|
|
+ def __init__(self, window):
|
|
|
|
|
+ self.window = window
|
|
|
|
|
+ self.window.title("Проверка чисел Такси")
|
|
|
|
|
+ self.window.geometry("500x300")
|
|
|
|
|
+
|
|
|
|
|
+ # Создание элементов интерфейса
|
|
|
|
|
+ self.info_label = tk.Label(
|
|
|
|
|
+ window,
|
|
|
|
|
+ text="Проверить, можно ли представить число как сумму кубов двумя разными способами",
|
|
|
|
|
+ wraplength=400,
|
|
|
|
|
+ justify="center"
|
|
|
|
|
+ )
|
|
|
|
|
+ self.info_label.pack(pady=10)
|
|
|
|
|
+
|
|
|
|
|
+ # Поле для ввода числа
|
|
|
|
|
+ self.input_frame = tk.Frame(window)
|
|
|
|
|
+ self.input_frame.pack(pady=10)
|
|
|
|
|
+
|
|
|
|
|
+ self.input_label = tk.Label(self.input_frame, text="Введите число для проверки:")
|
|
|
|
|
+ self.input_label.pack(side=tk.LEFT, padx=5)
|
|
|
|
|
+
|
|
|
|
|
+ self.number_entry = tk.Entry(self.input_frame, width=15)
|
|
|
|
|
+ self.number_entry.pack(side=tk.LEFT, padx=5)
|
|
|
|
|
+ self.number_entry.bind('<Return>', lambda event: self.check_number()) # Поиск по Enter
|
|
|
|
|
+
|
|
|
|
|
+ # Кнопки
|
|
|
|
|
+ self.button_frame = tk.Frame(window)
|
|
|
|
|
+ self.button_frame.pack(pady=10)
|
|
|
|
|
+
|
|
|
|
|
+ self.check_button = tk.Button(
|
|
|
|
|
+ self.button_frame,
|
|
|
|
|
+ text="Проверить число",
|
|
|
|
|
+ command=self.check_number,
|
|
|
|
|
+ bg="lightblue"
|
|
|
|
|
+ )
|
|
|
|
|
+ self.check_button.pack(side=tk.LEFT, padx=5)
|
|
|
|
|
+
|
|
|
|
|
+ self.find_button = tk.Button(
|
|
|
|
|
+ self.button_frame,
|
|
|
|
|
+ text="Найти следующее число Такси",
|
|
|
|
|
+ command=self.find_next_taxicab,
|
|
|
|
|
+ bg="lightgreen"
|
|
|
|
|
+ )
|
|
|
|
|
+ self.find_button.pack(side=tk.LEFT, padx=5)
|
|
|
|
|
+
|
|
|
|
|
+ # Область вывода результатов
|
|
|
|
|
+ self.output_label = tk.Label(window, text="Результат: ", wraplength=450, justify="left")
|
|
|
|
|
+ self.output_label.pack(pady=10)
|
|
|
|
|
+
|
|
|
|
|
+ # История поиска
|
|
|
|
|
+ self.history_label = tk.Label(window, text="История найденных чисел:", font=("Arial", 10, "bold"))
|
|
|
|
|
+ self.history_label.pack(pady=(20, 5))
|
|
|
|
|
+
|
|
|
|
|
+ self.history_text = tk.Text(window, height=6, width=60)
|
|
|
|
|
+ self.history_text.pack(pady=5)
|
|
|
|
|
+ # Подготовка базы данных
|
|
|
|
|
+ self.setup_database()
|
|
|
|
|
+
|
|
|
|
|
+ # Загрузка истории
|
|
|
|
|
+ self.load_history()
|
|
|
|
|
+
|
|
|
|
|
+ def setup_database(self):
|
|
|
|
|
+ """Настройка базы данных для хранения результатов"""
|
|
|
|
|
+ self.db_connection = sqlite3.connect('taxicab_results.db')
|
|
|
|
|
+ self.db_cursor = self.db_connection.cursor()
|
|
|
|
|
+ self.db_cursor.execute('''
|
|
|
|
|
+ CREATE TABLE IF NOT EXISTS found_numbers (
|
|
|
|
|
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
|
|
|
+ taxicab_number INTEGER,
|
|
|
|
|
+ first_num1 INTEGER, first_num2 INTEGER,
|
|
|
|
|
+ second_num1 INTEGER, second_num2 INTEGER
|
|
|
|
|
+ )
|
|
|
|
|
+ ''')
|
|
|
|
|
+ self.db_connection.commit()
|
|
|
|
|
+
|
|
|
|
|
+ def check_number(self):
|
|
|
|
|
+ """Проверка введенного числа"""
|
|
|
|
|
+ try:
|
|
|
|
|
+ number = int(self.number_entry.get())
|
|
|
|
|
+ if number <= 0:
|
|
|
|
|
+ messagebox.showerror("Ошибка", "Пожалуйста, введите положительное число")
|
|
|
|
|
+ return
|
|
|
|
|
+ except ValueError:
|
|
|
|
|
+ messagebox.showerror("Ошибка", "Пожалуйста, введите целое число")
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ # Поиск представлений числа как суммы двух кубов
|
|
|
|
|
+ representations = self.find_cube_representations(number)
|
|
|
|
|
+
|
|
|
|
|
+ if len(representations) >= 2:
|
|
|
|
|
+ # Нашли число Такси
|
|
|
|
|
+ result_text = f" Число {number} ЯВЛЯЕТСЯ числом Такси!\n\n"
|
|
|
|
|
+ for i, (a, b) in enumerate(representations[:2], 1):
|
|
|
|
|
+ result_text += f" Способ {i}: {a}³ + {b}³ = {a**3} + {b**3} = {a**3 + b**3}\n"
|
|
|
|
|
+
|
|
|
|
|
+ # Сохраняем в базу данных
|
|
|
|
|
+ self.save_result(number, representations[0], representations[1])
|
|
|
|
|
+ self.output_label.config(text=result_text, fg="green")
|
|
|
|
|
+
|
|
|
|
|
+ else:
|
|
|
|
|
+ # Не нашли достаточно представлений
|
|
|
|
|
+ if len(representations) == 1:
|
|
|
|
|
+ result_text = f" Число {number} можно представить как сумму кубов только одним способом:\n"
|
|
|
|
|
+ a, b = representations[0]
|
|
|
|
|
+ result_text += f"{a}³ + {b}³ = {a**3} + {b**3} = {number}"
|
|
|
|
|
+ else:
|
|
|
|
|
+ result_text = f" Число {number} НЕЛЬЗЯ представить как сумму двух кубов"
|
|
|
|
|
+
|
|
|
|
|
+ self.output_label.config(text=result_text, fg="red")
|
|
|
|
|
+
|
|
|
|
|
+ # Обновляем историю
|
|
|
|
|
+ self.load_history()
|
|
|
|
|
+
|
|
|
|
|
+ def find_cube_representations(self, number):
|
|
|
|
|
+ """Найти все представления числа как суммы двух кубов"""
|
|
|
|
|
+ representations = []
|
|
|
|
|
+ max_cube = int(round(number ** (1/3))) + 1
|
|
|
|
|
+
|
|
|
|
|
+ for a in range(1, max_cube + 1):
|
|
|
|
|
+ a_cube = a ** 3
|
|
|
|
|
+ if a_cube > number:
|
|
|
|
|
+ continue
|
|
|
|
|
+
|
|
|
|
|
+ remaining = number - a_cube
|
|
|
|
|
+ b = round(remaining ** (1/3))
|
|
|
|
|
+
|
|
|
|
|
+ if b >= a and b ** 3 == remaining: # b >= a, чтобы избежать дубликатов
|
|
|
|
|
+ representations.append((a, b))
|
|
|
|
|
+
|
|
|
|
|
+ return representations
|
|
|
|
|
+
|
|
|
|
|
+ def find_next_taxicab(self):
|
|
|
|
|
+ """Найти следующее число Такси (автоматический поиск)"""
|
|
|
|
|
+ self.output_label.config(text="Поиск следующего числа Такси...", fg="blue")
|
|
|
|
|
+ self.window.update()
|
|
|
|
|
+
|
|
|
|
|
+ found_numbers = self.get_existing_numbers()
|
|
|
|
|
+ current_number = max(found_numbers) + 1 if found_numbers else 1
|
|
|
|
|
+
|
|
|
|
|
+ while True:
|
|
|
|
|
+ representations = self.find_cube_representations(current_number)
|
|
|
|
|
+
|
|
|
|
|
+ if len(representations) >= 2:
|
|
|
|
|
+ # Нашли число Такси
|
|
|
|
|
+ result_text = f" Найдено число Такси: {current_number}\n\n"
|
|
|
|
|
+ for i, (a, b) in enumerate(representations[:2], 1):
|
|
|
|
|
+ result_text += f" Способ {i}: {a}³ + {b}³ = {a**3} + {b**3} = {a**3 + b**3}\n"
|
|
|
|
|
+
|
|
|
|
|
+ # Сохраняем в базу данных
|
|
|
|
|
+ self.save_result(current_number, representations[0], representations[1])
|
|
|
|
|
+ self.output_label.config(text=result_text, fg="green")
|
|
|
|
|
+ self.number_entry.delete(0, tk.END)
|
|
|
|
|
+ self.number_entry.insert(0, str(current_number))
|
|
|
|
|
+ # Обновляем историю
|
|
|
|
|
+ self.load_history()
|
|
|
|
|
+ break
|
|
|
|
|
+
|
|
|
|
|
+ current_number += 1
|
|
|
|
|
+
|
|
|
|
|
+ # Защита от бесконечного цикла (на всякий случай)
|
|
|
|
|
+ if current_number > 10**7:
|
|
|
|
|
+ messagebox.showwarning("Прервано", "Поиск прерван на большом числе")
|
|
|
|
|
+ self.output_label.config(text="Поиск прерван", fg="orange")
|
|
|
|
|
+ break
|
|
|
|
|
+
|
|
|
|
|
+ def get_existing_numbers(self):
|
|
|
|
|
+ """Получить список уже найденных чисел из базы данных"""
|
|
|
|
|
+ self.db_cursor.execute("SELECT taxicab_number FROM found_numbers")
|
|
|
|
|
+ return [row[0] for row in self.db_cursor.fetchall()]
|
|
|
|
|
+
|
|
|
|
|
+ def save_result(self, number, first_pair, second_pair):
|
|
|
|
|
+ """Сохранение найденного числа в базу данных"""
|
|
|
|
|
+ # Проверяем, нет ли уже этого числа в базе
|
|
|
|
|
+ self.db_cursor.execute("SELECT id FROM found_numbers WHERE taxicab_number = ?", (number,))
|
|
|
|
|
+ if not self.db_cursor.fetchone():
|
|
|
|
|
+ self.db_cursor.execute('''
|
|
|
|
|
+ INSERT INTO found_numbers (taxicab_number, first_num1, first_num2, second_num1, second_num2)
|
|
|
|
|
+ VALUES (?, ?, ?, ?, ?)
|
|
|
|
|
+ ''', (number, first_pair[0], first_pair[1], second_pair[0], second_pair[1]))
|
|
|
|
|
+ self.db_connection.commit()
|
|
|
|
|
+
|
|
|
|
|
+ def load_history(self):
|
|
|
|
|
+ """Загрузка истории найденных чисел"""
|
|
|
|
|
+ self.db_cursor.execute('''
|
|
|
|
|
+ SELECT taxicab_number, first_num1, first_num2, second_num1, second_num2
|
|
|
|
|
+ FROM found_numbers
|
|
|
|
|
+ ORDER BY taxicab_number
|
|
|
|
|
+ ''')
|
|
|
|
|
+ results = self.db_cursor.fetchall()
|
|
|
|
|
+
|
|
|
|
|
+ self.history_text.delete(1.0, tk.END)
|
|
|
|
|
+
|
|
|
|
|
+ if not results:
|
|
|
|
|
+ self.history_text.insert(tk.END, "История пуста")
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ for row in results:
|
|
|
|
|
+ number, a1, b1, a2, b2 = row
|
|
|
|
|
+ history_line = f"{number} = {a1}³ + {b1}³ = {a2}³ + {b2}³\n"
|
|
|
|
|
+ self.history_text.insert(tk.END, history_line)
|
|
|
|
|
+
|
|
|
|
|
+ def close_connection(self):
|
|
|
|
|
+ """Закрытие соединения с базой данных"""
|
|
|
|
|
+ if hasattr(self, 'db_connection'):
|
|
|
|
|
+ self.db_connection.close()
|
|
|
|
|
+
|
|
|
|
|
+if __name__ == "__main__":
|
|
|
|
|
+ main_window = tk.Tk()
|
|
|
|
|
+ app = TaxicabFinder(main_window)
|
|
|
|
|
+ main_window.mainloop()
|
|
|
|
|
+ app.close_connection()
|
|
|
|
|
+
|