Domanda

Per una classe Lisp, ci hanno dato un sistema di cifratura compiti fila trasposizione, che ho cercato di risolvere in Haskell, anche. Fondamentalmente, uno solo divide una stringa in file di lunghezza n, e poi traspone il risultato. La concatenazione della lista risultante di liste di caratteri è la stringa crittografata. Decodifica è un po 'più difficile, in quanto vi possono essere elementi dell'ultima fila di ingresso (colonne incomplete del risultato), che devono essere curati mancanti.

Questa è la mia soluzione in 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

Si fa il lavoro, ma non sono sicuro, se questo sarebbe considerato idiomatica Haskell, dato che la mia giocherellare con gli indici non si sente troppo dichiarativo. Questo potrebbe essere migliorato, e se sì, come?

A proposito: C'è qualcosa di simile ad insertAt in Haskell 98? Cioè una funzione inserimento di un elemento o un elenco in un determinato indice in una lista.

Nota. Questo non fa parte del lavoro, che era in scadenza oggi comunque

È stato utile?

Soluzione

Vorrei farlo guardando i problemi encode e decode in modo leggermente diverso. interruzioni encode up i dati in una matrice n colonne, che poi traspone (in una matrice n riga) e concatena per righe. interruzioni decode up i dati nel una matrice fila n, che poi traspone (in una matrice n columm) e concatena per righe.

Così mi piacerebbe iniziare con la definizione di due funzioni - uno a fare una matrice in una matrice colonna n:

chunk:: Int -> [a] -> [[a]]
chunk n as = chunk' n (length as) as
  where chunk' n l as | l <= n    = [as]
                      | otherwise = some : chunk' n (l-n) rest 
                          where (some, rest) = splitAt n as

ed un altro per tagliare una matrice in una matrice riga n:

slice :: Int -> [a] -> [[a]]
slice n as = chunk (q+1) front ++ chunk q back
  where (q,r) = length as `divMod` n
        (front, back) = splitAt (r*(q+1)) as

Ora, codifica e decodifica è abbastanza facile:

encode :: Int -> [a] -> [a]
encode = ((concat . transpose) .). chunk
decode :: Int -> [a] -> [a]
decode = ((concat . transpose) .). slice
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top