diff --git a/reverse.hs b/reverse.hs new file mode 100644 index 0000000..d96af11 --- /dev/null +++ b/reverse.hs @@ -0,0 +1,149 @@ +{-# LANGUAGE + UnicodeSyntax +#-} + +module Main where + +import Prelude hiding (iterate, reverse) +import Data.IORef + + + +data LinkedList a + = None + | Node { value ∷ IORef a + , next ∷ IORef (LinkedList a) + } + + +linkedlist ∷ a → IO (LinkedList a) +linkedlist x = + do + v ← newIORef x + n ← newIORef None + pure $ Node { value = v , next = n } + + +get_value ∷ LinkedList a → IO a +get_value n = + case n of + None → error "Empty" + node → (readIORef $ value node) >>= \ x → pure x + + +set_value ∷ a → LinkedList a → IO () +set_value x n = + case n of + None → pure () + node → writeIORef (value node) x + + +get_next ∷ LinkedList a → IO (LinkedList a) +get_next n = + case n of + None → error "Empty" + node → (readIORef $ next node) >>= \x → pure x + + +set_next ∷ LinkedList a → LinkedList a → IO () +set_next n1 n2 = + case n1 of + None → pure () + node → writeIORef (next node) n2 + + +reverse ∷ LinkedList a → IO (LinkedList a) +reverse l = + + let reverse' ∷ LinkedList a → LinkedList a → IO (LinkedList a) + reverse' n1 n2 = + case n2 of + None → pure n1 + _ → do + n3 ← get_next n2 + set_next n2 n1 + reverse' n2 n3 + in + + reverse' None l + + +iterate ∷ (a → IO ()) -> LinkedList a -> IO () +iterate f l = + case l of + None → pure () + _ → + do + v ← get_value l + f v + n ← get_next l + iterate f n + + +print_list ∷ Show a ⇒ LinkedList a → IO () +print_list l = + iterate (\ x → putStr $ show x ++ " ") l + + + +main ∷ IO () +main = + do + l1 ← linkedlist 1 + l2 ← linkedlist 2 + l3 ← linkedlist 3 + l4 ← linkedlist 4 + l5 ← linkedlist 5 + + let lists = [ ("l1", l1) , ("l2", l2) , + ("l3", l3) , ("l4", l4) , + ("l5", l5) + ] + + putStr "\n" + + putStr ">>> Before linking the lists\n" + mapM_ (\ (s, l) → + do + putStr $ s ++ " : " + print_list l + putStr "\n" + ) + lists + + set_next l1 l2 + set_next l2 l3 + set_next l3 l4 + set_next l4 l5 + + putStr "\n" + + putStr ">>> After linking and before reversing the linked list\n" + mapM_ (\ (s, l) → + do + putStr $ s ++ " : " + print_list l + putStr "\n" + ) + lists + + putStr "\n" + + putStr " The evaluation of `reverse l1´ computes the reversed\n\ + \ list of l1 and the final result is equal to l5,\n\ + \ the new head of the linked list.\n\n" + + _ ← reverse l1 + + putStr ">>> After reversing the linked list\n" + mapM_ (\ (s, l) → + do + putStr $ s ++ " : " + print_list l + putStr "\n" + ) + lists + + putStr "\n" + + diff --git a/reverse.ml b/reverse.ml new file mode 100644 index 0000000..3f6d058 --- /dev/null +++ b/reverse.ml @@ -0,0 +1,165 @@ + + +exception Empty +;; + + +type 'a linked_list = + | None + | Node of + { value : 'a ref + ; next : 'a linked_list ref + } +;; + + +let linked_list : 'a -> 'a linked_list = + fun x -> + Node { value = ref x + ; next = ref None + } +;; + + +let get_value : 'a linked_list -> 'a = + fun l -> + match l with + | None -> raise Empty + | Node r -> !(r.value) +;; + + +let set_value : 'a -> 'a linked_list -> unit = + fun value node -> + match node with + | None -> () + | Node r -> r.value := value +;; + + +let get_next : 'a linked_list -> 'a linked_list = + fun l -> + match l with + | None -> raise Empty + | Node r -> !(r.next) +;; + + +let set_next : 'a linked_list -> 'a linked_list -> unit = + fun n1 n2 -> + match n1 with + | None -> () + | Node r -> r.next := n2 +;; + + +let reverse : 'a linked_list -> 'a linked_list = + fun l -> + + let rec reverse' : 'a linked_list -> 'a linked_list -> 'a linked_list = + fun n1 n2 -> + match n2 with + | None -> n1 + | _ -> + let n3 = get_next n2 + in + ( set_next n2 n1 ; reverse' n2 n3 ) + in + + match l with + | None -> None + | _ -> reverse' None l +;; + + +let rec iterate : ('a -> unit) -> 'a linked_list -> unit = + fun f l -> + match l with + | None -> () + | _ -> ( f (get_value l) ; iterate f (get_next l) ) +;; + + +let print_list : ('a -> string) -> 'a linked_list -> unit = + fun to_string l -> + iterate (fun n -> print_string ((to_string n) ^ " ")) l +;; + + +let print_a_list_of_strings : string linked_list -> unit = + fun l -> print_list (fun s -> s) l +;; + + +let print_a_list_of_ints : int linked_list -> unit = + fun l -> print_list (fun i -> string_of_int i) l +;; + + + +let main = + let l1 = linked_list 1 + and l2 = linked_list 2 + and l3 = linked_list 3 + and l4 = linked_list 4 + and l5 = linked_list 5 + in + + let lists = + [ ("l1", l1) ; ("l2", l2) + ; ("l3", l3) ; ("l4", l4) + ; ("l5", l5) + ] + in + + ( print_newline () + + ; print_string ">>> Before linking the lists\n" + ; List.iter (fun (s, l) -> + print_string (s ^ " : " ) + ; print_a_list_of_ints l + ; print_newline () + ) + lists + + ; set_next l1 l2 + ; set_next l2 l3 + ; set_next l3 l4 + ; set_next l4 l5 + + ; print_newline () + + ; print_string ">>> After linking and before reversing the linked list\n" + ; List.iter (fun (s, l) -> + print_string (s ^ " : " ) + ; print_a_list_of_ints l + ; print_newline () + ) + lists + + ; print_newline () + + ; print_string " The evaluation of `reverse l1´ computes the reversed\n\ + \ list of l1 and the final result is equal to l5,\n\ + \ the new head of the linked list.\n\n" + + ; let _ = reverse l1 in () + + ; print_string ">>> After reversing the linked list\n" + ; List.iter (fun (s, l) -> + print_string (s ^ " : " ) + ; print_a_list_of_ints l + ; print_newline () + ) + lists + + ; print_newline () + ) +;; + + + +let () = main +;; + + diff --git a/reverse.py b/reverse.py new file mode 100644 index 0000000..09f1750 --- /dev/null +++ b/reverse.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 + + +class LinkedList: + + def __init__ (self, x) : + self.value = x + self.next = None + + def get_value (self) : + return self.value + + def set_value (self, x) : + self.value = x + + def get_next (self) : + return self.next + + def set_next (self, node) : + self.next = node + + + +def reverse (l) : + + def reverse_aux (n1, n2) : + if n2 == None : + return n1 + else : + n3 = n2.get_next () + n2.set_next (n1) + return reverse_aux (n2, n3) + + return reverse_aux (None, l) + + +def iterate (f, l) : + + if l == None : + return + else : + f (l.get_value ()) + return iterate (f, l.get_next ()) + + +def print_list (l) : + + iterate ((lambda s : print (str (s) + " ", end = '')), l) + print () + + +def main () : + + l1 = LinkedList (1) + l2 = LinkedList (2) + l3 = LinkedList (3) + l4 = LinkedList (4) + l5 = LinkedList (5) + + lists = [ ("l1", l1) , ("l2", l2) + , ("l3", l3) , ("l4", l4) + , ("l5", l5) + ] + + print () + + print (">>> Before linking the lists") + list (map (lambda p : print (p [0] + " : ", end = '') or print_list (p [1]), lists)) + + l1.set_next (l2) + l2.set_next (l3) + l3.set_next (l4) + l4.set_next (l5) + + print () + + print (">>> After linking and before reversing the linked list") + list (map (lambda p : print (p [0] + " : ", end = '') or print_list (p [1]), lists)) + + print () + + print ("\ + The execution of `reverse l1´ computes the reversed\n\ + list of l1 and the returned result is equal to l5,\n\ + the new head of the linked list.\n\ +") + + reverse (l1) + + print (">>> After reversing the linked list") + list (map (lambda p : print (p [0] + " : ", end = '') or print_list (p [1]), lists)) + + print () + + + +if __name__ == "__main__" : + main () + +