Добро пожаловать на еще одну статью в нашей серии о концепциях и идеях SQL Server. Сегодня мы будем обсуждать концепцию алхимического сокращения с использованием SQL Server. Эта тема вдохновлена заданием Advent of Code, где участники решают программные головоломки с использованием различных языков программирования, включая T-SQL.
В задании нам предоставляется полимер, который представляет собой строку, состоящую из единиц, представленных заглавными и строчными буквами. Соседние единицы с одной и той же буквой, но разной полярностью (регистром), уничтожают друг друга. Цель состоит в том, чтобы сократить полимер до его наименьшего возможного размера.
Для достижения этой цели нам необходимо выполнить регистрозависимый поиск и замену для каждой буквы алфавита. Мы можем сделать это с помощью цикла while в SQL Server. Хотя в SQL Server обычно предпочитается множественная рекурсия, она плохо работает в этом сценарии, поэтому цикл while является более подходящим выбором.
Давайте посмотрим на код для выполнения рекурсивных замен:
DECLARE @data VARCHAR(MAX),
@Letters CHAR(26)= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
@Size INTEGER,
@NewSize INTEGER = 0,
@Loop INTEGER = 0;
SELECT @data = FileData
FROM OPENROWSET(BULK 'D:AdventOfCode2018InputDay05.txt', SINGLE_CLOB) dt(FileData);
SET @Size = LEN(@data);
WHILE @Size <> @NewSize
BEGIN
SET @NewSize = @Size;
SELECT @data = REPLACE(@data COLLATE SQL_Latin1_General_CP1_CS_AS, ca.UpperLtr + ca.LowerLtr, '')
FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26)) dt(N)
CROSS APPLY (VALUES (UPPER(SUBSTRING(@Letters, dt.N, 1)), LOWER(SUBSTRING(@Letters, dt.N, 1)))) ca(UpperLtr, LowerLtr)
SELECT @data = REPLACE(@data COLLATE SQL_Latin1_General_CP1_CS_AS, ca.LowerLtr + ca.UpperLtr, '')
FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26)) dt(N)
CROSS APPLY (VALUES (UPPER(SUBSTRING(@Letters, dt.N, 1)), LOWER(SUBSTRING(@Letters, dt.N, 1)))) ca(UpperLtr, LowerLtr)
SET @Size = LEN(@data);
SET @Loop += 1;
END
SELECT @Loop AS Loops, @Size AS Size;
В этом коде мы сначала объявляем и инициализируем необходимые переменные. Затем мы загружаем полимер из файла в переменную. С помощью цикла while мы выполняем регистрозависимые замены, пока размер полимера не перестанет изменяться. Наконец, мы возвращаем количество выполненных циклов и конечный размер полимера.
Во второй части задания нам необходимо определить, какой тип единицы можно удалить из полимера, чтобы сократить его до наименьшего размера. Для этого мы добавляем еще один цикл while, который проходит по каждой букве, удаляя все ее вхождения перед началом рекурсивной замены. В конце цикла мы сохраняем размер полимера. После обработки всех букв мы определяем, какая буква, при удалении которой, производит наименьший полимер.
Вот код для второй части:
DECLARE @data VARCHAR(MAX),
@Letters CHAR(26)= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
@Size INTEGER,
@NewSize INTEGER = 0,
@Loop INTEGER = 0,
@Letter CHAR(1) = 'A',
@data2 VARCHAR(MAX);
SELECT @data2 = FileData
FROM OPENROWSET(BULK 'D:AdventOfCode2018InputDay05.txt', SINGLE_CLOB) dt(FileData);
DECLARE @Results TABLE (Letter CHAR(1) PRIMARY KEY, Size INTEGER);
WHILE ASCII(@Letter) <= ASCII('Z')
BEGIN
SET @data = REPLACE(@data2, @Letter, '');
SET @NewSize = 0;
SET @Size = LEN(@data);
SET @Loop = 0;
WHILE @Size <> @NewSize
BEGIN
SET @NewSize = @Size;
SELECT @data = REPLACE(@data COLLATE SQL_Latin1_General_CP1_CS_AS, ca.UpperLtr + ca.LowerLtr, '')
FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26)) dt(N)
CROSS APPLY (VALUES (UPPER(SUBSTRING(@Letters, dt.N, 1)), LOWER(SUBSTRING(@Letters, dt.N, 1)))) ca(UpperLtr, LowerLtr)
SELECT @data = REPLACE(@data COLLATE SQL_Latin1_General_CP1_CS_AS, ca.LowerLtr + ca.UpperLtr, '')
FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26)) dt(N)
CROSS APPLY (VALUES (UPPER(SUBSTRING(@Letters, dt.N, 1)), LOWER(SUBSTRING(@Letters, dt.N, 1)))) ca(UpperLtr, LowerLtr)
SET @Size = LEN(@data);
SET @Loop += 1;
END
INSERT INTO @Results (Letter, Size)
VALUES (@Letter, @Size);
SET @Letter = CHAR(ASCII(@Letter)+1);
END
SELECT TOP (1) *
FROM @Results
ORDER BY Size;
В заключение, мы исследовали концепцию алхимического сокращения с использованием SQL Server. Мы узнали, как загружать файл, выполнять регистрозависимые и регистронезависимые операции со строками, использовать конструктор таблицы значений и реализовывать циклы while в SQL Server. Эти концепции ценны для решения различных программных задач и могут улучшить ваши навыки работы с SQL Server.
Спасибо за чтение этой статьи. Следите за новыми статьями о концепциях и идеях SQL Server.
Автор: Ваше имя