Tuesday, April 12, 2011

99 Problems

I ran across an awesome blog post today titled Programming Problems To Improve Your Language Skills. I never actually wrote anything in Haskell yet, but I thought that solving the Ninety-Nine Lisp Problems was a great way to start. That's the point of this post. There is, however, a goofy Scala snippet that's in order first.

Scala Snippet

It's a funny thing, logical operators. In php and python, if you want to test that this something is true and that something is true, you'd simply write if this and that. Very straight forward. Those of us coming from C understand that && and || represent and and or respectively. I never actually questioned it... that's just the way it was.

My wife is taking a beginner CSC class at university, and when she saw &&, she simply read it as and-and.

What's does "and-and" mean, and I never seen those vertical things before...

A very natural response. In Scala, we can change this!

class BooleanExpression(origin: Boolean) {
  def and (expr: => Boolean) = origin && expr
  def or (expr: => Boolean) = origin || expr
}

implicit def boolean2BooleanX(some: Boolean) =
  new BooleanExpression(some)

Now your conditional sound very natural:

if (file.exists and something)
  println("Yeeeeee")

val x = 5
if(x > 4 and (x < 10 or x > 100))
  println("We got it anyway")

It is important to note that this is less efficient. It is, however, cool.

Haskell Problems

And here's the first 20 problems, almost. I skipped a couple, but I plan on going back to it. I tried not to use Prelude with all the pre-defined list functions, but it still doesn't hurt when the goal is to learn a language.

-- problem 1
my_last :: [a] -> a
my_last (x:[]) = x
my_last (x:xs) = my_last xs

-- problem 2
my_but_last :: [a] -> [a]
my_but_last (x:y:[]) = [x, y]
my_but_last (x:rest) = my_but_last rest

-- problem 3
element_at :: [a] -> Int -> a
element_at xs i = head [y | (x, y) <- zip [0..] xs, x == i]

-- problem 4
count :: [a] -> Int
count xs = foldl (\acc x -> acc + 1) 0 xs

-- problem 5
rev :: [a] -> [a]
rev [] = []
rev (x:xs) = rev xs ++ [x]

-- problem 6
palindrome :: (Eq a) => [a] -> Bool
palindrome xs = if(rev xs == xs) then True else False

-- problem 7

-- problem 8
compress :: (Eq a) => [a] -> [a]
compress [] = []
compress (x:xs) = [x] ++ compress(dropWhile(== x) xs)

-- problem 9
pack :: (Eq a) => [a] -> [[a]]
pack [] = []
pack (x:xs) = [[x] ++ takeWhile (== x) xs] ++ pack(dropWhile(== x) xs)

-- problem 10
encode :: (Eq a) => [a] -> [(Int,a)]
encode xs = [(count ls, head ls) | ls <- pack xs]

-- problem 11

-- problem 12
decode :: (Eq a) => [(Int, a)] -> [a]
decode xs = concat . map (\el -> let (times, i) = el in repl i times) xs

-- problem 13

-- problem 14
dupe :: [a] -> [a]
dupe [] = []
dupe (x:xs) = x : x : dupe xs

-- problem 15
repl :: [a] -> Int -> [a]
repl [] _ = []
repl (x:xs) n = map (\_ -> x) [1..n] ++ repl xs n

-- problem 16
dropr :: [a] -> Int ->[a]
dropr xs i 
  | count xs < i = xs
  | otherwise = let (headr, (_:rest)) = splitAt (i - 1) xs in headr ++ dropr rest i

-- problem 17
split :: [a] -> Int -> ([a], [a])
split xs n
  | n == 0 = ([], xs)
  | count xs < n = (xs, [])
  | otherwise = (take n xs, drop n xs)

-- problem 18
slice :: [a] -> Int -> Int -> [a]
slice xs from to
  | from == 1 && to == count xs = xs
  | from > to = []
  | otherwise = [x | (index, x) <- zip [1..] xs, index >= from && index <= to]

-- problem 19
rotate :: [a] -> Int -> [a]
rotate xs n = let index = if n < 0 then count xs + n else n
                  (first, second) = split xs index 
              in second ++ first

-- problem 20
remove :: [a] -> Int -> [a]
remove xs n = [x | (i, x) <- zip [1..] xs, i /= n]

No comments:

Post a Comment