заменить цифру на некоторые позиции в количестве


Я пытаюсь написать функцию, которая заменяет цифры на некоторые позиции в количестве.

Например Ф 91521 [3,4] -> [91001,91111,91221,91331,91441,91551,91661,91771,91881,91991]

Это поведение, как 91**1 -> ..., поэтому я назвал его как 'whitemask'.

Вопрос 1: это "whitemask" нормальный и адекватно название для этой функции?

После этого я сформулировал, что функция whitemask'.

sublists :: (Eq a) => [a] -> [[a]]
sublists list = [x | x <- subsequences list, x /= []]

numbers :: [Int]
numbers =  take 10 [0..]

numLength :: Integer -> Int
numLength = length . show

decreaseList :: Num a => [a] -> a -> [a]
decreaseList = (\a b c -> map (a c) b) (flip (-))

listToNum :: [Int] -> Integer
listToNum digits = toInteger $ foldl1 (\x y -> x*10 + y) digits

numToList :: Integer -> [Int]
numToList x = map digitToInt $ show x

remove :: [Int] -> [Int] -> [[Int]]
remove [] x = [x]
remove (x:xs) list = putted : remove (decreaseList xs x) unputted
    where [putted,unputted] = (\(x,y) -> [init x,y]) $ splitAt x list

sew :: [[a]] -> a -> [a]
sew list sewer = foldr1 (\x y -> x ++ [sewer] ++ y) list

whitemask :: Integer -> [Int] -> [Integer]
whitemask num places =  filter (\x -> numLength x == numLength num ) $ map (listToNum . sew (remove places (numToList num))) numbers

Но в контексте всей проблемы, где эта функция может быть использована, я выяснил, что мне нужно только исправить-продолжительность ответы. Для примера, он работает как

> whitemask 75148 [1,3,4]
[15118,25228,35338,45448,55558,65668,75778,85888,95998]

и ответа не содержат '5008' элемент.

Вопрос 2: что исправить-продолжительность фильтрования whitemask функция бизнес? Или было бы лучше вернуть все возможные варианты и их фильтрации, если он действительно нужен?

Когда я начал использовать эту функцию в сложных перебирает пути я понял, что это может сделать некоторые ненужные и лишние расчеты.

Вопрос 3: Как я могу рефакторинг 'whitemask функция' меньше-использование складок карт и рекурсий?

Любая косметика и советы стиль ценятся.

зы: я выберите правильное место, чтобы просить? (вопрос может быть перенесен на так на самом деле)

УПД: Я поняла, что шить можно написать гораздо проще.

sew list sewer = concat $ intersperse [sewer] list


599
1
задан 15 ноября 2011 в 09:11 Источник Поделиться
Комментарии
1 ответ

Я не думал о самом алгоритме, но сократить код немного:

decreaseList :: Num a => [a] -> a -> [a]
decreaseList b c = map (subtract c) b

listToNum :: [Int] -> Integer
listToNum = toInteger . foldl1 ((+).(*10))

numToList :: Integer -> [Int]
numToList = map digitToInt . show

remove :: [Int] -> [Int] -> [[Int]]
remove [] x = [x]
remove (x:xs) list = let (putted, unputted) = splitAt x list
in (init putted) : remove (decreaseList xs x) unputted

sew :: [[a]] -> a -> [a]
sew list sewer = foldr1 ((++).(++[sewer])) list

whitemask :: Integer -> [Int] -> [Integer]
whitemask num places = let list = map (listToNum . sew (remove places (numToList num))) [0..9]
in filter (((==) `on` length . show) num) list

Я думаю, что есть еще возможности для совершенствования...

[Править]

Более короткий вариант:

whitemask :: Integer -> [Int] -> [Integer]
whitemask num places = map (listToNum . replace) [0..9] where
replace digit = foldr ((:).findDigit) [] $ zip (numToList num) [1..] where
findDigit (d,i) | i `elem` places = digit
| otherwise = d

listToNum :: [Int] -> Integer
listToNum = toInteger . foldl1 ((+).(*10))

numToList :: Integer -> [Int]
numToList = map digitToInt . show

[Править]

Укороченная версия, с фиксированной-длина фильтрации:

whitemask :: Integer -> [Int] -> [Integer]
whitemask num places = map replace digits where
digits = if 1 `elem` places then [1..9] else [0..9]
toList = map digitToInt $ show num
replace digit = foldl toNum 0 $ zip toList [1..] where
toNum r (d,i) = 10*r + (fromIntegral $ if i `elem` places then digit else d)

Я не могу обещать, что я в конечном итоге с одной-вкладыш, хотя...

На ваши вопросы:


  1. Зависит от контекста. Если вы не уверены в имени, просто объяснить функцию с комментарием.

  2. Зависит, если вы когда-нибудь понадобится нефильтрованный выход. В данном случае это выглядит довольно сомнительно, поэтому я бы включил фильтрацию.

  3. См. выше.

2
ответ дан 15 ноября 2011 в 11:11 Источник Поделиться