Dla klasy Lisp dostaliśmy zadanie domowe z prostym rzędem transpozycji wierszy, które próbowałem rozwiązać również w Haskell. Zasadniczo, jeden po prostu dzieli ciąg znaków na wiersze o długości n
, a następnie transponuje wynik. Konkatenacja wynikowej listy list znaków jest zaszyfrowanym łańcuchem. Dekodowanie jest nieco trudniejsze, ponieważ w ostatnim wierszu wejścia mogą wystąpić brakujące elementy (niekompletne kolumny w wyniku), którymi należy się zająć.Szyfrowanie z prostym rzędem
To jest moje rozwiązanie w Haskell:
import Data.List
import Data.Ratio
import Data.List.Split
encode :: String -> Int -> String
encode s n = concat . transpose $ chunk n s
decode :: String -> Int -> String
decode s n = take len $ encode s' rows
where s' = foldr (insertAt " ") s idxs
rows = ceiling (len % n)
idxs = take (n-filled) [n*rows-1,(n-1)*rows-1..]
filled = len - n * (rows - 1)
len = length s
insertAt :: [a] -> Int -> [a] -> [a]
insertAt xs i ys = pre ++ xs ++ post
where (pre,post) = splitAt i ys
spełnia swoje zadanie, ale nie jestem pewien, czy byłoby to uznać za idiomatyczne Haskell, ponieważ mój błahy z indeksów nie czuje się zbyt deklaratywny. Czy można to poprawić, a jeśli tak, to w jaki sposób?
Przy okazji: Czy w Haskell 98 jest coś podobnego do insertAt
? To znaczy. funkcja wstawiająca element lub listę z danego indeksu do listy.
Uwaga: NIE jest to częścią zadania domowego, które i tak było dzisiaj należne.
Mała uwaga: możesz pisać 'idxs = [n * rows-1, (n-1) * rows-1 .. (filled + 1) * rows-1]'. – HaskellElephant
@HaskellElephant: Wygląda ładniej, dzięki! – danlei