Здравствуйте, Буравчик, Вы писали:
Б>Здравствуйте, Кодт, Вы писали:
К>>Предложите наиболее быстрый способ.
Б>1. Формируем список десятичных палиндромов
Б>2. Формируем список двоичных палиндромов
Б>3. Мержим оба списка
Б>4. Просматриваем объединенный список на повторы. Каждый повтор — искомый палиндром
Б>Для простоты разделить п.1 (да и п.2):
Б>а) сформировать палиндромы четной длины
Б>б) сформировать палиндромы нечетной длины
Б>в) смержить оба списка
Б>Так получается проще
На Haskell получилось лучше, чем на Python
Скорость в три раза выше. И главное, ближе к описанию алгоритма
type Digits = [Integer]
type Radix = Integer
-- объединяет два отсортированных списка
merge :: Ord a => [a] -> [a] -> [a]
merge xs [] = xs
merge [] xs = xs
merge a@(h:first) b@(c:second)
| h <= c = h : merge first b
| h > c = c : merge a second
-- выбирает из списка элементы, которые совпадают с предыдущим элементом списка
filter_repeat xs = [a | (a,b) <- zip xs (drop 1 xs), a == b]
-- числа представляем как список цифр в системе radix
-- младшая цифра находится в начале списка
-- получение следующего числа (для формирования половинок палиндромов)
increment :: Radix -> Digits -> Digits
increment radix [] = [1]
increment radix (d:ds)
| d < radix-1 = (d+1:) $ ds
| otherwise = (0:) $ increment radix ds
-- на основе половинки палиндрома создаем палиндром четный длины
create_even_palindrome :: Digits -> Digits
create_even_palindrome digits = reverse digits ++ digits
-- на основе половинки палиндрома создаем палиндром нечетный длины
create_odd_palindrome :: Digits -> Digits
create_odd_palindrome digits = reverse (tail digits) ++ digits
-- палиндромы по основанию radix
palindromes :: Radix -> [Integer]
palindromes radix =
let
position_weights = iterate (radix*) 1
to_number digits = sum $ zipWith (*) digits position_weights
hs = iterate (increment radix) [1]
even_palindromes = map to_number $ map create_even_palindrome hs
odd_palindromes = map to_number $ map create_odd_palindrome hs
in
merge even_palindromes odd_palindromes
-- вывод чисел, одновременно являющимися палиндромами в двоичной и десятичной системах
main =
let
ps = filter_repeat $ merge (palindromes 2) (palindromes 10)
in
mapM_ putStrLn [ show idx ++ ": " ++ show p | (idx,p) <- zip [1..] ps ]