Last active
January 31, 2020 03:56
-
-
Save lazamar/746b73049a83bc0be4c4fcd5a8fbbc6a to your computer and use it in GitHub Desktop.
highest value palindrome. https://www.hackerrank.com/challenges/richie-rich/problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Lib where | |
import Data.List (foldr) | |
-- Complete the highestValuePalindrome function below. | |
highestValuePalindrome :: String -> Int -> Int -> String | |
highestValuePalindrome s n changesAllowed = | |
if changesToMakePalindrome > changesAllowed | |
then "-1" | |
else result | |
where | |
changesToMakePalindrome = sum $ fmap (uncurry palindromeCost) $ zip [0..] $ take half allStats | |
-- Cost of transforming a string into a palindrome | |
palindromeCost ix (_, isEqual) = if isEqual || isMiddleChar ix then 0 else 1 | |
-- After making it a palindrome how many more changes can we make? | |
extraChanges = changesAllowed - changesToMakePalindrome | |
result = take firstHalf withNines ++ reverse (take half withNines) | |
half = n `div` 2 | |
firstHalf = half + n - 2 * half | |
-- String with as many characters replaced for '9' as possible | |
withNines = reverse $ snd $ foldr withCosts ((1, 0) , []) $ reverse $ take firstHalf allStats | |
withCosts stat ((ix, totalCost), list) = | |
let | |
cost = nineCost ix stat - palindromeCost ix stat | |
in | |
if extraChanges >= totalCost + cost | |
then ( (ix + 1, totalCost + cost), '9' : list ) | |
else ( (ix + 1, totalCost ), fst stat : list ) | |
-- pair of target letter and whether it is equal on both sides of the string | |
allStats :: [(Char, Bool)] | |
allStats = zipWith (\a b -> (max a b, a == b)) s (reverse s) | |
isMiddleChar ix = odd n && ix == half + 1 | |
-- Number of changes required to convert one character into a nine on both sides of the string | |
nineCost :: Int -> (Char, Bool) -> Int | |
nineCost ix (char, isEqual) = | |
let | |
cost = if char /= '9' | |
then 2 | |
else if isEqual | |
then 0 | |
else 1 | |
in | |
if isMiddleChar ix | |
then max 0 (cost - 1) | |
else cost | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment