Re[2]: двоично-десятичные палиндромы
От: Буравчик Россия  
Дата: 17.12.15 21:01
Оценка:
Здравствуйте, Буравчик, Вы писали:

Б>Здравствуйте, Кодт, Вы писали:


К>>Предложите наиболее быстрый способ.


Б>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 ]
Best regards, Буравчик
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.