Моё решение для СУБД
SQLite
3.47.0 2024-10-21 16:30:22 03a9703e27c44437c39363d0baf82db4ebc94538a0f28411c85dda156f82636e
zlib version 1.3, msvc-1939 (64-bit)
Не использовались никакие расширения SQLite.
Код: Выделить всё
.echo on
.version
.timer on
-- Промежуточное VIEW
DROP VIEW IF EXISTS kaprekar_6174;
CREATE VIEW kaprekar_6174
AS
WITH RECURSIVE t AS (
-- Натуральные числа от 1 до 9999 (9999 штук)
SELECT 1 AS n UNION ALL SELECT n+1 FROM t WHERE n < 9999)
, f AS (-- Нарезка числа по четырём цифрам и их позициям
SELECT n, 1 AS pos, substr(n, 1, 1) AS f FROM t UNION ALL
SELECT n, 2 , substr(n, 2, 1) FROM t UNION ALL
SELECT n, 3 , substr(n, 3, 1) FROM t UNION ALL
SELECT n, 4 , substr(n, 4, 1) FROM t)
--
, nums AS ( -- Генерация всех 24-х возможных чисел перестановкой четырех цифр
SELECT DISTINCT f1.n
, f1.f AS f1, f1.pos AS f1_pos
, f2.f AS f2, f2.pos AS f2_pos
, f3.f AS f3, f3.pos AS f3_pos
, f4.f AS f4, f4.pos AS f4_pos
, CAST(f1.f||f2.f||f3.f||f4.f AS integer) AS num
FROM f f1 JOIN f f2 ON f1.n = f2.n -- Это цифры
JOIN f f3 ON f1.n = f3.n -- одного и того же
JOIN f f4 ON f1.n = f4.n -- числа
WHERE -- Число не состоит из одинаковых цифр
NOT (f1.f = f2.f AND f2.f = f3.f AND f3.f = f4.f)
-- Каждая цифра участвует в перестановке только один раз
AND NOT (f1.pos = f2.pos OR f1.pos = f3.pos OR f1.pos = f4.pos
OR f2.pos = f3.pos OR f2.pos = f4.pos
OR f3.pos = f4.pos) )
--
, res AS (
SELECT n, count(*) AS cnt -- перестановка 4 цифр. Кол-во перестановок = 4! = 1*2*3*4 = 24
, MAX(num) AS max_num, MIN(num) as min_num
, MAX(num)-MIN(num) AS diff
FROM nums group by n)
--
SELECT n, cnt, min_num
-- Наибольшее значение дополняем справо нулём (умножаем на 10), если оно меньше 1000
, IIF(max_num < 1000, max_num*10, max_num) AS max_num
, IIF(max_num < 1000, max_num*10, max_num) - min_num AS diff
FROM res;
-- Результат
WITH recursive KAP AS(
SELECT n AS for_n
, CAST(n AS text) AS tree_path_n
, 0 as steps
, n, diff
-- , cnt, max_num, min_num
FROM kaprekar_6174
WHERE n > 1000
UNION ALL
SELECT EH.for_n
, EH.tree_path_n || ' -> ' || E.n
, EH.steps+1
, E.n, E.diff
-- , E.cnt, E.max_num, E.min_num
FROM kaprekar_6174 E
JOIN KAP EH ON E.n = EH.diff AND EH.n <> EH.diff)
--
SELECT for_n AS "Число"
, tree_path_n AS "Цепочка"
, steps AS "Шагов"
FROM kap
WHERE tree_path_n LIKE '%6174'
ORDER BY for_n
;
Время выполнения 2.08 сек/
Скрипт и листинг его выполнения прилагаются в архиве
Solution_09_SQL-Plus_01.zip
Для запуска использовал команду:
D:\SQLite\3.47\sqlite3.exe -table < Solution_09_SQL-Plus_01.sql > Solution_09_SQL-Plus_01.lst 2>&1
P. S. Это решение я нашел до того, как опубликовал условия задачи.
Нашел я его не мгновенно. Пришлось подумать, попробовать разные пути.
Улучшил познания в Recursive Subquery Factoring.
После того, как началась публикация других решений, я ничего не исправлял и не улучшал.