Haskell
Meine Version ist ziemlich lang, weil ich mich auf die Lesbarkeit konzentriert habe. Ich dachte, es wäre interessant, Ihren Algorithmus in Code zu formalisieren. Wenn ich die Anzahl der Zeichen in einer linken Falte zusammenfasse , werden sie im Grunde genommen zusammengeschneit, und die Reihenfolge ist in der Reihenfolge ihres Auftretens in der Zeichenfolge. Ich habe es auch geschafft, den Teil des Algorithmus, der normalerweise eine Array-Indizierung erfordert, durch List Bending zu ersetzen . Es stellt sich heraus, dass Ihr Algorithmus im Wesentlichen darin besteht, eine Liste von Zahlen in zwei Hälften zu falten und ausgerichtete Zahlen zu addieren. Es gibt zwei Fälle für das Biegen, gerade Listen, die schön in der Mitte geteilt sind, ungerade Listen, die um ein zentrales Element gebogen sind und dieses Element nicht zusätzlich beteiligt ist. Fission nimmt die Liste und teilt Zahlen auf, die keine einzelnen Ziffern mehr sind, wie> = 10 . Ich musste mein eigenes entfalten schreiben , ich bin nicht sicher, ob es tatsächlich ein entfalten ist , aber es scheint zu tun, was ich brauche. Genießen.
import qualified Data.Char as Char
import qualified System.Environment as Env
-- | Takes a seed value and builds a list using a function starting
-- from the last element
unfoldl :: (t -> Maybe (t, a)) -> t -> [a]
unfoldl f b =
case f b of
Just (new_b, a) -> (unfoldl f new_b) ++ [a]
Nothing -> []
-- | Builds a list from integer digits
number_to_digits :: Integral a => a -> [a]
number_to_digits n = unfoldl (\x -> if x == 0
then Nothing
else Just (div x 10, mod x 10)) n
-- | Builds a number from a list of digits
digits_to_number :: Integral t => [t] -> t
digits_to_number ds = number
where (number, _) = foldr (\d (n, p) -> (n+d*10^p, p+1)) (0,0) ds
-- | Bends a list at n and returns a tuple containing both parts
-- aligned at the bend
bend_at :: Int -> [a] -> ([a], [a])
bend_at n xs = let
(left, right) = splitAt n xs
in ((reverse left), right)
-- | Takes a list and bends it around a pivot at n, returns a tuple containing
-- left fold and right fold aligned at the bend and a pivot element in between
bend_pivoted_at :: Int -> [t] -> ([t], t, [t])
bend_pivoted_at n xs
| n > 1 = let
(left, pivot:right) = splitAt (n-1) xs
in ((reverse left), pivot, right)
-- | Split elements of a list that satisfy a predicate using a fission function
fission_by :: (a -> Bool) -> (a -> [a]) -> [a] -> [a]
fission_by _ _ [] = []
fission_by p f (x:xs)
| (p x) = (f x) ++ (fission_by p f xs)
| otherwise = x : (fission_by p f xs)
-- | Bend list in the middle and zip resulting folds with a combining function.
-- Automatically uses pivot bend for odd lists and normal bend for even lists
-- to align ends precisely one to one
fold_in_half :: (b -> b -> b) -> [b] -> [b]
fold_in_half f xs
| odd l = let
middle = (l-1) `div` 2 + 1
(left, pivot, right) = bend_pivoted_at middle xs
in pivot:(zipWith f left right)
| otherwise = let
middle = l `div` 2
(left, right) = bend_at middle xs
in zipWith f left right
where
l = length xs
-- | Takes a list of character counts ordered by their first occurrence
-- and keeps folding it in half with addition as combining function
-- until digits in a list form into any number less or equal to 100
-- and returns that number
foldup :: Integral a => [a] -> a
foldup xs
| n > 100 = foldup $ fission $ reverse $ (fold_in_half (+) xs)
| otherwise = n
where
n = (digits_to_number xs)
fission = fission_by (>= 10) number_to_digits
-- | Accumulate counts of keys in an associative array
count_update :: (Eq a, Integral t) => [(a, t)] -> a -> [(a, t)]
count_update [] x = [(x,1)]
count_update (p:ps) a
| a == b = (b,c+1) : ps
| otherwise = p : (count_update ps a)
where
(b,c) = p
-- | Takes a string and produces a list of character counts in order
-- of their first occurrence
ordered_counts :: Integral b => [Char] -> [b]
ordered_counts s = snd $ unzip $ foldl count_any_alpha [] s
where
count_any_alpha m c
| Char.isAlpha c = count_update m (Char.toLower c)
| otherwise = m
-- | Take two names and perform the calculation
love_chances n1 n2 = foldup $ ordered_counts (n1 ++ " loves " ++ n2)
main = do
args <- Env.getArgs
if (null args) || (length args < 2)
then do
putStrLn "\nUSAGE:\n"
putStrLn "Enter two names separated by space\n"
else let
n1:n2:_ = args
in putStrLn $ show (love_chances n1 n2) ++ "%"
Einige Ergebnisse:
"Romeo" "Juliet" 97% - Empirische Tests sind wichtig
"Romeo" "Julier" 88% - Moderne Kurzfassung ...
"Horst Draper" "Jane" 20%
"Horst Draper" "Jane (Pferd)" 70% - Es gab eine Entwicklung ...
"Bender Bender Rodriguez" "Fenny Wenchworth" 41% - Bender sagt "Falten ist für Frauen!"
"Philip Fry" "Turanga Leela" 53% - Nun, Sie können sehen, warum sie 7 Saisons gebraucht haben, um "Maria" "Abraham" zu heiraten
- 98%
"John" "Jane" 76%