pavelfatin/ninety-nine

P01-P07

0 parents commit 15ca9bb7fdf51583d1ed25d3ed4974bbf7c90e07 committed Dec 20, 2011
Showing with 1,543 additions and 0 deletions.
3. +11 −0 clojure/P01.clj
4. +9 −0 clojure/P02.clj
5. +11 −0 clojure/P03.clj
6. +18 −0 clojure/P04.clj
7. +12 −0 clojure/P05.clj
8. +14 −0 clojure/P06.clj
9. +14 −0 clojure/P07.clj
17. +45 −0 java/P01.java
18. +41 −0 java/P02.java
19. +24 −0 java/P03.java
20. +33 −0 java/P04.java
21. +37 −0 java/P05.java
22. +19 −0 java/P06.java
23. +16 −0 java/P07.java
24. +217 −0 java/core/List.java
25. +32 −0 scala/P01.scala
26. +25 −0 scala/P02.scala
27. +19 −0 scala/P03.scala
28. +26 −0 scala/P04.scala
29. +20 −0 scala/P05.scala
30. +24 −0 scala/P06.scala
31. +17 −0 scala/P07.scala
 @@ -0,0 +1,6 @@ +My take on Ninety-Nine Problems in Java, Scala, Clojure and Haskell + +Based on the original Prolog problem list by Werner Hett: +https://sites.google.com/site/prologsite/prolog-problems + +Pavel Fatin, http://pavelfatin.com
11 clojure/P01.clj
 @@ -0,0 +1,11 @@ +; P01 Find the last element of a list. + +; Predefined function +(defn f0 [l] + (last l)) + +; Tail recursion +(defn f1 [l] + (if (next l) + (recur (rest l)) + (first l)))
9 clojure/P02.clj
 @@ -0,0 +1,9 @@ +; P02 Find the last but one element of a list. + +; Built-ins +(defn f1 [l] + (last (butlast l))) + +; Using index +(defn f2 [l] + (nth (reverse l) 1))
11 clojure/P03.clj
 @@ -0,0 +1,11 @@ +; P03 Find the Kth element of a list. + +; Tail recursion +(defn f1 [l, n] + (if (= n 1) + (first l) + (recur (rest l) (dec n)))) + +; Using index +(defn f2 [l, n] + (nth l (dec n)))
18 clojure/P04.clj
 @@ -0,0 +1,18 @@ +; P04 Find the number of elements of a list. + +; Predefined function +(defn f0 [l] + (count l)) + +; Recursion +(defn f1 [l] + (if (seq l) + (inc (f1 (rest l))) + 0)) + +; Tail recursion +(defn f2 [l] + (loop [it l, n 0] + (if (seq it) + (recur (rest it) (inc n)) + n)))
12 clojure/P05.clj
 @@ -0,0 +1,12 @@ +; P05 Reverse a list. + +; Predefined function +(defn f0 [l] + (reverse l)) + +; Tail recursion +(defn f1 [l] + (loop [it l, acc (empty l)] + (if (seq it) + (recur (rest it) (conj acc (first it))) + acc)))
14 clojure/P06.clj
 @@ -0,0 +1,14 @@ +; P06 Find out whether a list is a palindrome. +; A palindrome can be read forward or backward; e.g. (x a m a x). + +; Tail recursion +(defn f1 [l] + (or (empty? l) + (empty? (rest l)) + (and + (= (first l) (last l)) + (f1 (butlast (rest l)))))) + +; Builtin "reverse" +(defn f2 [l] + (= l (reverse l)))
14 clojure/P07.clj
 @@ -0,0 +1,14 @@ +; P07 Flatten a nested list structure. + +; Predefined functions +(defn f0 [l] + (flatten l)) + +; Recursion +(defn f1 [l] + (if (empty? l) + '() + (let [h (first l) t (rest l)] + (if (list? h) + (concat (f1 h) (f1 t)) + (cons h (f1 t))))))
 @@ -0,0 +1,34 @@ +-- P01 Find the last element of a list. + +module P01 where + +-- Predefined function +f0 :: [a] -> a +f0 = last + +-- Recursion +f1 :: [a] -> a +f1 [] = error "empty list" +f1 [x] = x +f1 (_:xs) = f1 xs + +-- Function application +f2 :: [a] -> a +f2 xs = head \$ reverse xs + +-- Function composition +f3 :: [a] -> a +f3 = head . reverse + +-- Folding +f4 :: [a] -> a +f4 = foldl (curry snd) (error "empty list") + +f5 :: [a] -> a +f5 = foldr1 (flip const) + +f6 :: [a] -> a +f6 = foldr1 (const id) + +f7 :: [a] -> a +f7 = foldr1 (\_ y -> y)
 @@ -0,0 +1,26 @@ +-- P02 Find the last but one element of a list. + +module P02 where + +-- Recursion +f1 :: [a] -> a +f1 [] = error "empty list" +f1 [_] = error "singleton list" +f1 [x,_] = x +f1 (_:xs) = f1 xs + +-- Function application +f2 :: [a] -> a +f2 xs = last \$ init xs + +-- Function composition +f3 :: [a] -> a +f3 = last . init + +-- Folding +f4 :: [a] -> a +f4 = foldr1 (const id) . init + +-- Using index +f5 :: [a] -> a +f5 x = reverse x !! 1
 @@ -0,0 +1,23 @@ +-- P03 Find the Kth element of a list. + +module P03 where + +-- Tail recursion +f1 :: [a] -> Int -> a +f1 [] _ = error "Index out of bound" +f1 (x:_) 1 = x +f1 (_:xs) n + | n < 1 = error "Index out of bound" + | otherwise = f1 xs (n - 1) + +-- Function application +f2 :: [a] -> Int -> a +f2 xs n = head \$ drop (n - 1) xs + +-- Function composition +f3 :: [a] -> Int -> a +f3 xs n = last . take n \$ xs + +-- Using index +f4 :: [a] -> Int -> a +f4 xs n = xs !! (n - 1)
 @@ -0,0 +1,31 @@ +-- P04 Find the number of elements of a list. + +module P04 where + +-- Predefined function +f0 :: [a] -> Int +f0 = length + +-- Recursion +f1 :: [a] -> Int +f1 [] = 0 +f1 (_:xs) = 1 + f1 xs + +-- Tail recursion +f2 :: [a] -> Int +f2 = f2' 0 + where f2' :: Int -> [a] -> Int + f2' n [] = n + f2' n (_:xs) = f2' (n + 1) xs + +-- Folding +f3 :: [a] -> Int +f3 xs = foldl (\a _ -> a + 1) 0 xs + +-- Folding with function composition +f4 :: [a] -> Int +f4 = foldr (const (+1)) 0 + +-- Using build-in 'sum' +f5 :: [a] -> Int +f5 = sum . map (const 1)
 @@ -0,0 +1,23 @@ +-- P05 Reverse a list. + +module P05 where + +-- Predefined function +f0 :: [a] -> [a] +f0 = reverse + +-- Recursion (inefficient) +f1 :: [a] -> [a] +f1 [] = [] +f1 (x:xs) = f1 xs ++ [x] + +-- Tail recursion +f2 :: [a] -> [a] +f2 xs = f2' xs [] + where f2' :: [a] -> [a] -> [a] + f2' [] acc = acc + f2' (x:xs) acc = f2' xs (x:acc) + +-- Folding +f3 :: [a] -> [a] +f3 = foldl (flip (:)) []
 @@ -0,0 +1,26 @@ +-- P06 Find out whether a list is a palindrome. +-- A palindrome can be read forward or backward; e.g. (x a m a x). + +module P06 where + +-- Recursion (inefficient) +f1 :: (Eq a) => [a] -> Bool +f1 [] = True +f1 [_] = True +f1 xs = (head xs) == (last xs) && (f1 \$ init \$ tail xs) + +-- Using "reverse" function +f2 :: (Eq a) => [a] -> Bool +f2 xs = xs == reverse xs + +-- Zip +f3 :: (Eq a) => [a] -> Bool +f3 xs = all (uncurry (==)) \$ zip xs (reverse xs) + +-- ZipWith +f4 :: (Eq a) => [a] -> Bool +f4 xs = all id \$ zipWith (==) xs (reverse xs) + +-- ZipWith plus folding +f5 :: (Eq a) => [a] -> Bool +f5 xs = foldr (&&) True \$ zipWith (==) xs (reverse xs)
 @@ -0,0 +1,16 @@ +-- P07 Flatten a nested list structure. + +module P07 where + +data NestedList a = Value a | List [NestedList a] + +-- Recursion +f1 :: NestedList a -> [a] +f1 (Value a) = [a] +f1 (List []) = [] +f1 (List (x:xs)) = (f1 x) ++ f1(List xs) + +-- Using concatMap +f2 :: NestedList a -> [a] +f2 (Value a) = [a] +f2 (List xs) = concatMap f2 xs
45 java/P01.java
 @@ -0,0 +1,45 @@ +// P01 Find the last element of a list. + +import core.List; +import static core.List.*; + +import java.util.NoSuchElementException; + +class P01 { + // "Predefined" function + T f0(List list) { + return list.last(); + } + + // The fastest (but verbose) version + T f1(List list) { + if (list.isEmpty()) throw new NoSuchElementException("List is empty"); + List elements = list.tail(); + List result = list; + while (elements.nonEmpty()) { + result = elements; + elements = elements.tail(); + } + return result.head(); + } + + // Instantiates an iterator to enumerate elements (CPU and GC overhead) + T f2(List list) { + if (list.isEmpty()) throw new NoSuchElementException("List is empty"); + T result = null; + for (T each : list) + result = each; + return result; + } + + // Uses (tail) recursion (can produce stack overflow errors in Java) + T f3(List list) { + if (list.isEmpty()) throw new NoSuchElementException("List is empty"); + return f3_inner(list); + } + + private T f3_inner(List list) { + List tail = list.tail(); + return tail.isEmpty() ? list.head() : f3(tail); + } +}
41 java/P02.java
 @@ -0,0 +1,41 @@ +// P02 Find the last but one element of a list. + +import core.List; + +import java.util.NoSuchElementException; + +import static core.List.*; + +class P02 { + // "Build-in" methods ;) + T f1(List list) { + return list.init().last(); + } + + // Tail-recursive "pattern matching" without pattern matching + T f2(List list) { + if (list.isEmpty()) throw new NoSuchElementException("List is empty"); + List tail = list.tail(); + if (tail.isEmpty()) throw new NoSuchElementException("Singleton list"); + if (tail.tail().isEmpty()) return list.head(); + return f2(tail); + } + + // Imperative approach with two variables + T f3(List list) { + if (list.isEmpty()) throw new NoSuchElementException("List is empty"); + T a = null; + T b = null; + for (T each : list) { + b = a; + a = each; + } + if (b == null) throw new NoSuchElementException("Singleton list"); + return b; + } + + // "Build-in" methods with index + T f4(List list) { + return list.reverse().get(1); + } +}
24 java/P03.java
 @@ -0,0 +1,24 @@ +// P03 Find the Kth element of a list. + +import core.List; + +import static core.List.*; + +class P03 { + // Recursion + T f1(List list, int n) { + if (list.isEmpty()) throw new IndexOutOfBoundsException(); + if (n < 1) throw new IndexOutOfBoundsException(); + return n == 1 ? list.head() : f1(list.tail(), n - 1); + } + + // Calls chain + T f2(List list, int n) { + return list.drop(n - 1).head(); + } + + // Using index + T f3(List list, int n) { + return list.get(n - 1); + } +}
33 java/P04.java
 @@ -0,0 +1,33 @@ +// P04 Find the number of elements of a list. + +import core.List; + +import static core.List.*; + +class P04 { + // "Predefined" function + int f0(List list) { + return list.length(); + } + + // Recursion + int f1(List list) { + return list.isEmpty() ? 0 : 1 + f1(list.tail()); + } + + // Tail recursion + int f2(List list) { + return f2_inner(list, 0); + } + + private int f2_inner(List list, int n) { + return list.isEmpty() ? n : f2_inner(list.tail(), n + 1); + } + + // Iteration + int f3(List list) { + int n = 0; + for (T x : list) n++; + return n; + } +}
37 java/P05.java
 @@ -0,0 +1,37 @@ +// P05 Reverse a list. + +import core.List; + +import static core.List.*; + +class P05 { + // "Predefined" function + List f0(List list) { + return list.reverse(); + } + + // Recursion (inefficient) + List f1(List list) { + return list.isEmpty() + ? List.nil() + : concat(f1(list.tail()), singleton(list.head())); + } + + // Tail recursion + List f2(List list) { + return f2_inner(list, List.nil()); + } + + private List f2_inner(List list, List acc) { + return list.isEmpty() + ? acc + : f2_inner(list.tail(), cons(list.head(), acc)); + } + + // Imperative + List f3(List list) { + List acc = nil(); + for (T each : list) acc = cons(each, acc); + return acc; + } +}
19 java/P06.java
 @@ -0,0 +1,19 @@ +// P06 Find out whether a list is a palindrome. +// A palindrome can be read forward or backward; e.g. (x a m a x). + +import core.List; + +import static core.List.*; + +class P06 { + // Builtin functions + boolean f1(List list) { + return list.equals(list.reverse()); + } + + // Recursion (inefficient) + boolean f2(List list) { + return list.isEmpty() || list.tail().isEmpty() || + (list.head() == list.last() && f2(list.tail().init())); + } +}
16 java/P07.java
 @@ -0,0 +1,16 @@ +// P07 Flatten a nested list structure. + +import core.List; + +import static core.List.*; + +class P07 { + // Recursion, unchecked + @SuppressWarnings("unchecked") + List f1(List list) { + if (list.isEmpty()) return nil(); + Object h = list.head(); + List t = list.tail(); + return h instanceof List ? concat(f1((List) h), f1(t)) : cons(h, f1(t)); + } +}
217 java/core/List.java
 @@ -0,0 +1,217 @@ +package core; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +// A Scala-like immutable List implementation in Java (without higher-order function) +// The performance is not considered in favor of cleaner code (for demo purposes) +public class List implements Iterable { + private static final List NIL = new EmptyList(); + + private final T _head; + + private final List _tail; + + + private List(T head, List tail) { + _head = head; + _tail = tail; + } + + public T head() { + return _head; + } + + public List tail() { + return _tail; + } + + public boolean isEmpty() { + return false; + } + + public boolean nonEmpty() { + return !isEmpty(); + } + + @Override + public Iterator iterator() { + return new ListIterator(this); + } + + @SuppressWarnings("unchecked") + public static List nil() { + return NIL; + } + + public static List list(T... elements) { + List list = nil(); + for (T each : elements) + list = cons(each, list); + return list.reverse(); + } + + public static List singleton(T element) { + return new List(element, List.nil()); + } + + public static List cons(T head, List tail) { + return new List(head, tail); + } + + public static List concat(List prefix, List suffix) { + List result = suffix; + for (T each : prefix.reverse()) + result = cons(each, result); + return result; + } + + public List reverse() { + List list = nil(); + for (T each : this) + list = cons(each, list); + return list; + } + + public int length() { + int c = 0; + for (T each : this) + c++; + return c; + } + + public T get(int i) { + int c = 0; + for (T each : this) + if (c == i) + return each; + else + c++; + throw new IndexOutOfBoundsException(); + } + + public T last() { + if (isEmpty()) throw new NoSuchElementException("List is empty"); + T result = null; + for (T each : this) + result = each; + return result; + } + + public List take(int i) { + return take(i, this).reverse(); + } + + public List takeRight(int i) { + return take(i, this.reverse()); + } + + private static List take(int i, List list) { + List result = nil(); + int c = 0; + for (T each : list) { + if (c == i) break; + result = cons(each, result); + c++; + } + return result; + } + + public List drop(int i) { + return drop(i, this).reverse(); + } + + public List dropRight(int i) { + return drop(i, this.reverse()); + } + + private static List drop(int i, List list) { + List result = nil(); + int c = i; + for (T each : list) { + c--; + if (c >= 0) continue; + result = cons(each, result); + } + return result; + } + + public List init() { + if (isEmpty()) throw new UnsupportedOperationException("List is empty"); + return dropRight(1); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof List)) return false; + + Iterator ours = this.iterator(); + Iterator theirs = ((List) obj).iterator(); + + while (ours.hasNext() && theirs.hasNext()) + if (!ours.next().equals(theirs.next())) + return false; + + return !ours.hasNext() && !theirs.hasNext(); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append('['); + Iterator it = iterator(); + while (it.hasNext()) { + builder.append(it.next()); + if (it.hasNext()) builder.append(", "); + } + builder.append(']'); + return builder.toString(); + } + + + private static class EmptyList extends List
32 scala/P01.scala
 @@ -0,0 +1,32 @@ +// P01 Find the last element of a list. + +// Predefined function +def f0[T](list: List[T]): T = list.last + +// Tail recursion +@annotation.tailrec +def f1[T](list: List[T]): T = list match { + case h :: Nil => h + case _ :: t => f1(t) + case _ => throw new NoSuchElementException("List is empty") +} + +// Chained calls +def f2[T](list: List[T]): T = list.reverse.head + +// Haskell-like function composition, point-free style (looks strange with Scala syntax and OO model) +def f3[T] = ((_: List[T]).head).compose((_: List[T]).reverse) + +// Reversed function composition +def f4[T] = ((_: List[T]).reverse).andThen((_: List[T]).head) + +// Java-like implementation with side effects +def f5[T](list: List[T]): T = { + var result: Option[T] = None + for (each <- list) result = Some(each) + result.getOrElse(throw new NoSuchElementException("List is empty")) +} + +// Folding +def f6[T](list: List[T]): T = if (list.nonEmpty) list.reduce((a, b) => b) else + throw new NoSuchElementException("List is empty")
25 scala/P02.scala
 @@ -0,0 +1,25 @@ +// P02 Find the last but one element of a list. + +// Tail recursion +@annotation.tailrec +def f1[T](list: List[T]): T = list match { + case Nil => throw new NoSuchElementException("List is empty") + case List(_) => throw new NoSuchElementException("Sigleton list") + case List(x, _) => x + case _ :: xs => f1(xs) +} + +// Function application +def f2[T](list: List[T]): T = list.init.last + +// With errors check +def f3[T](list: List[T]): T = list.init.lastOption.getOrElse(throw new NoSuchElementException()) + +// Function composition +def f4[T] = ((_: List[T]).last).compose((_: List[T]).init) + +// Using index +def f5[T](list: List[T]): T = list.reverse(1) + +// With partial function lifting +def f6[T](list: List[T]): T = list.reverse.lift(1).getOrElse(throw new NoSuchElementException())
19 scala/P03.scala
 @@ -0,0 +1,19 @@ +// P03 Find the Kth element of a list. + +// Tail recursion +@annotation.tailrec +def f1[T](list: List[T], n: Int): T = list match { + case Nil => throw new IndexOutOfBoundsException() + case h :: t => + if (n < 1) throw new IndexOutOfBoundsException() + if (n == 1) h else f1(t, n - 1) +} + +// Calls chain +def f2[T](list: List[T], n: Int): T = list.drop(n - 1).head + +// Using index +def f3[T](list: List[T], n: Int): T = list(n - 1) + +// With error reporting +def f4[T](list: List[T], n: Int): T = list.lift(n - 1).getOrElse(throw new IndexOutOfBoundsException())
26 scala/P04.scala
 @@ -0,0 +1,26 @@ +// P04 Find the number of elements of a list. + +// Predefined function +def f0[T](list: List[T]): Int = list.length + +// Recursion +def f1[T](list: List[T]): Int = list match { + case Nil => 0 + case _ :: t => 1 + f1(t) +} + +// Tail recursion +@annotation.tailrec +def f2[T](list: List[T], n: Int = 0): Int = list match { + case Nil => n + case _ :: t => f2(t, n + 1) +} + +// Folding +def f3[T](list: List[T]): Int = list.foldLeft(0)((a, _) => a + 1) + +// Using build-in 'sum' +def f4[T](list: List[T]): Int = list.map(_ => 1).sum + +// With 'view' to avoid the creation of a temporary list +def f5[T](list: List[T]): Int = list.view.map(_ => 1).sum
20 scala/P05.scala
 @@ -0,0 +1,20 @@ +// P05 Reverse a list. + +// Predefined function +def f0[T](list: List[T]): List[T] = list.reverse + +// Recursion (inefficient) +def f1[T](list: List[T]): List[T] = list match { + case Nil => Nil + case h :: t => f1(t) ::: h :: Nil +} + +// Tail recursion +@annotation.tailrec +def f2[T](list: List[T], acc: List[T] = Nil): List[T] = list match { + case Nil => acc + case h :: t => f2(t, h :: acc) +} + +// Folding +def f3[T](list: List[T]): List[T] = list.foldLeft(Nil: List[T])((a, b) => b :: a)
24 scala/P06.scala
 @@ -0,0 +1,24 @@ +// P06 Find out whether a list is a palindrome. +// A palindrome can be read forward or backward; e.g. (x a m a x). + +// Recursion (inefficient) +def f1[T](list: List[T]): Boolean = list match { + case Nil => true + case _ :: Nil => true + case xs => xs.head == xs.last && f1(xs.tail.init) +} + +// Builtin functions +def f2[T](list: List[T]): Boolean = list == list.reverse + +// Zip +def f3[T](list: List[T]): Boolean = list.zip(list.reverse).forall{case (a, b) => a == b} + +// Zip again +def f4[T](list: List[T]): Boolean = list.zip(list.reverse).forall(((_: T) == (_: T)).tupled) + +// Zip with folding +def f5[T](list: List[T]): Boolean = + list.zip(list.reverse) + .map{case (a, b) => a == b} + .foldLeft(true){case (a, b) => a && b}
17 scala/P07.scala
 @@ -0,0 +1,17 @@ +// P07 Flatten a nested list structure. + +// flatMap with recursion, unchecked +def f1(list: List[Any]): List[Any] = list flatMap { + case xs: List[_] => f1(xs) + case v => List(v) +} + +// With custom data +abstract sealed class NestedList[T] +case class Value[T](v: T) extends NestedList[T] +case class Sequence[T](list: List[NestedList[T]]) extends NestedList[T] + +def f2[T](list: NestedList[T]): List[T] = list match { + case Value(v) => List(v) + case Sequence(list) => list.flatMap(f2) +}