Tuesday, February 26, 2013

Haskell tutorial


Important link for tutorial
===================

http://www.haskell.org/haskellwiki/Haskell_in_5_steps#Where_to_go_from_here

http://www.cs.nott.ac.uk/~gmh/book.html

http://rigaux.org/language-study/syntax-across-languages-per-language/Haskell.html

http://learnyouahaskell.com/chapters

You can change prompt by

:set prompt

0. how to run/quit haskell file
===============================
a. ghci  ( it will load Glasgow Haskell Compiler)
b. load file >  :l filename.hs
c. fncInsideFile parameter
d. :quit 


1.  bracket Issues in
=============
fnc(a)  // wrong

fnc a ;// right, parameters are space seperated


Parentesis
a. for tuple  -- let tup = ( 1, "sss")
b. (x:xs) -- x is first element, xs is rest elements

c.   for curry function/section. if you don't use () it will not work

-- correct
useSection
    = (/2)


-- Incorrect
useSection
    = /2


instead of using 1 + 2    use   (+) 1 2 

Square Bracket : for List -- let lst = [1,2]
-----------------------------------------------------------------
x  -- mean anything single/list
[x] -- mean a list with ONLY ONE element


let out = [ x | x  < -  [1..10] , x  < 3 ] -- List comprehension


Arrow issues in haskell
=================

< - means Belongs to set, Each element of list is generated iterratively

let b = [x | x < - [1..10 , x / 2 ==0] -- 4 quotient 2, remainder 0

- > means type conversion in function

testCurry x y
    = x + y

:type testCurry
(Num a) = > a -> a -> a


Tuple () VS list[]
====================

Tuple can combine any type of data

let myTubple = (1,2,"sd")

list combine only specific type of data with coercion
let myList = [1, 2.0 ]



List Concatenation
=========================================

concat two list using ++

 [1,2,3,4] ++ [9,10,11,12]
# [1,2,3,4,9,10,11,12]

 "hello" ++ " " ++ "world"
# "hello world"

concat one element with one list using :

 (x : xs)


list comprehension . Read each element one by one, Generate desired new list
=================================================

[ x | x < - [50..100], x `mod` 7 == 3]

[x*2 | x  < -  [1..10]]

[x*2 | x < -  [1..10], x*2  == 12]

rightAngle x
    = [ (a,b,c) | c < - [1..x], b < - [1..c], a < - [1..b], a ^ 2 + b ^ 2 == c ^ 2]



HASKELL CURRIED FUNCTION
======================

-- call as currySumRange  5 : sum 1 to X
currySumRange    x
    = foldr (+) 0 [1..x]

-- call as currySumList [2,3,9] : sum element of a list x
currySumList   
    = foldr (+) 0

-- call currySumTwo 4 5
currySumTwo x
    =  (+) x


Operation on element  Iteratively
=======================

1. List comprehension
2. Map  : For any function, applied for each elem -- return n result
3. Filter : For logical operation, applied for each elem -- return n result
4. Fold  : Any function, applied for each elem  --  return 1 result
1. List comprehension
--------------------------------------
let b = [x | x <  - [1..10 , x / 2 ==0] -- 1,2, ,,, 10 , select even

let a = [x | x < - "abc"] -- a , b , c

2. MAP
------------
{-
map takes a function and a list and applies that function to every element in the list, producing a new list
-}

-- map (+3) [1,5,3,1,6]
-- map (++ "!") ["BIFF", "BANG", "POW"]
-- map (replicate 3) [3..6]
-- map show [1,2,3]


3. FILTER
-----------------
{-
filter is a function that takes a predicate  and a list and then returns the list of elements that satisfy the predicate.
-}
-- filter (>3) [1,5,3,2,1,6,4,3,2,1]
-- filter (==3) [1,2,3,4,5]
-- filter (`elem` ['a'..'z']) "u LaUgH aT mE BeCaUsE I aM diFfeRent"

fIND ELEMENTS BELOW 10 AND DIVISIBLE BY 2

largest
    = (filter p [10,9..1])
    where
    p x = x `mod` 2 == 0



4. FOLD
===================

A fold takes  3 PAREMETER
  • a binary function, [binary function is applied between the starting value and the head/tail of the list.]
  • a starting value OF accumulator and
  • a list to fold up.

Then, the binary function is called again with the new accumulator and the now new first (or last) element, and so on.

To understand how foldl OR foldr works run them with scanr OR scanl, it will tell you every steps

scanl  (*) 1 [1,2,3,4,5] -- output  [1,1,2,6,24,120]
scanr (*) 1 [1,2,3,4,5] -- output  [120,120,60,20,5,1]

Tuple generation with ZIP
--------------------------------------------

-- (1,2) (2,3) ... (N, N+1)

zip [1..n] [2..n+1]

zip x tail(x)

-- (elem, elemIndex)

zip x [1..n]
      where n = length x


 Operator
========================

 list related
-------------------------

ALWAYS USE SQUARE BRACKET [] TO REPRESENT
list
set of element
conditional list etc

    x = [1..4]
    x = head [1,2,3,4]
    x = tail [1,2,3,4]
    x = init [1,2,3,4]
    x = last [1,2,3,4]
    x !! n -- find nth (0-based index)element of a list 
    length , sum ,  product
    reverse
    minimum    maximum   
    take n list -- take first n
    drop n list -- take last L-n




arithmetic
----------------------
let b = [x | x < - [1..10 , x `div` 2 ==0] -- 4,5 quotient 2, remainder ANY
let b = [x | x < - [1..10 , x / 2 ==0] -- 4 quotient 2, remainder 0

div -- how many times can be divided always return Int
/ -- original division return int/float



boolean
------------------------------

&& - binary and -- True && False
and - list element wise and -- and [True, False, True, True]

Type Checking
=================
If expr is an expression return type t , then it is written as

expr :: t

To check type of a fucniton
:type functionName

Available types: Char, String, int, Integer, Float

List contains single type  element

let lst = [1,2]
:type lst
lst :: [Integer]

Tuple contains multiple type of element

let tup = (1, "ab")
:type tup
tup :: (Integer, [Char])

String related
======================
take 2 ("abcdef") -- ab
drop 2 ("abcdef") - cdef


--Infinite sequence

repeat 5

CHECK EMPTY STRING
--------------------

isNull x
    = if length  x ==0 then True
        else False
myfnc x
    | null x  = []                     
    | otherwise = tail x


Function can be written in 2 different way a. guard b. pattern match
==========================================

1. GUARD
=======

useGuard x y
    | x/y > 1  = "less than"
    | x/y == 1 = "equal"
    | otherwise = "Greater than"



2. PATTERN
=============
usePattern x y
    = if x > y then "Greater"
        else if x == y then "Equal"
            else "Less"



WHERE
=======
useWhere x y
    | tmp < 1  = "less than"
    | tmp == 1 = "equal"
    | otherwise = "Greater than"
    where tmp = x/y

 findPos c x
    = [ b |    (a,b) <- a="=" br="" c="" n="" nbsp="" x="" zip="">        where  n = length x

Indentation under "where" matters like python


PATTERN VS GUARD
================

msumPattern :: Int - > Int
msumPattern n
    = if n ==0 then 0 else ( n + msumPattern (n-1) )


msumGuard :: Int - > Int
msumGuard n
    | n ==0 = 0
    | otherwise = ( n + msumGuard (n-1) )


RECUSION
========

1. To call recursive function, in each line function should be defined seperately
for each type of parameter.

# for qsort parameter type can vary null, or list, so two line

q2Sort []     = []
q2Sort (x:xs) = q2Sort ys ++ [x] ++ q2Sort zs
           where
              ys = [a | a <- a="" br="" x="" xs="">              zs = [b | b <- b="" xs="">  x]

# for replication parameter type always fixed, so one line

myReplicate n x
    | n <= 0    = []
    | otherwise = x: ( myReplicate (n-1) x   )



ANONYMOUS CLASS / LAMDA
========================
Both of these are same

    map (+3) [1,6,3,2]


\ (parameters) ->
           function definition

-- take 1 parameter
    map (\ y -> y+3) [1,6,3,2]
-- take 2 parameter
    map (\(y ,x) -> x+y+3) [ (1, 5) , (7,8) ]




-- sumAllFold [3,7,1]
sumAllFold x
    = foldr (acc curHead -> acc + curHead) 0 x


-- findElemFold 5 [1,3,7,5,6]
findElemFoldl n y
    = foldl (\acc curHead -> if curHead == n then True else acc) False y

findElemFoldr n y
    = foldl (\curHead acc -> if curHead == n then True else acc) False y




if - else
===============
MUST BE 3 PART if - else - then

usePattern x y
    = if x > y then "Greater"
        else if x == y then "Equal"
            else "Less"


For loop
===========

for i=1 to 5
   for j=1 to 3

 [ (x,y) |  x < - [1..4] , y < - [1..3] ]


for i=1 to 5
   for j=i+1 to 3

 [ (x,y) |  x < - [1..4] , y < - [x+1 ..3] ]



    INTERACTIVE Program
====================



getChar   - putChar
getLine    - putStr  - putStrLn

To use multiple action use do , do is indentation sensitive

actMyGetline :: IO String
actMyGetline
    = do   
        a <- getChar
        if a=='\n'   
            then
                return []
            else
                do
                    as <- actMyGetline
                    return (a:as)

show converts anything to string like toString()

actStrLen
    = do
        putStr "enter string:"
        x <- getLine
        putStr x
        putChar '\n'
        putStr ("len is:" ++ show (  length x ) )


Types

1.  RENATE EXISTING TYPE : type
2.  CREATE NEW TYPE LIKE STRUCTURE IN C/C++ : data


data BookInfo = Book Int String [String]        deriving (Show)
data MagazineInfo = Magazine Int String [String]    deriving (Show)

myInfo = Book 9780135072455 "Algebra of Programming"          ["Richard Bird", "Oege de Moor"]

weapons =  Book 173 "Use of Weapons" ["Iain M. Banks"]


IO
=========

() is an empty tuple (pronounced “unit”), indicating that there is no return value from putStrLn

getLine  ,  putStrLn
getChar ,  putChar


name2reply :: String - > String
name2reply name =
    "Pleased to meet you, " ++ name ++ ".\n" ++
    "Your name contains " ++ charcount ++ " characters."
    where charcount = show (length name)

main :: IO ()
main = do
       putStrLn "Greetings once again.  What is your name?"
       inpStr <- getLine
       let outStr = name2reply inpStr
       putStrLn outStr
 
 


Wednesday, February 13, 2013

Ghostscript pdf merge split



1. Cut range of page/ split  pages from pdf
=========================

gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER -dFirstPage=3 -dLastPage=7 -sOutputFile=out.pdf   in.pdf


2. Merge multiple pdfs
================

gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile=out.pdf in1.pdf in2.pdf