import Data.List (group, insertBy, sort, sortBy)
import Control.Arrow ((&&&), second)
import Data.Ord (comparing)

data HTree a
  = Leaf a
  | Branch (HTree a)
           (HTree a)
  deriving (Show, Eq, Ord)

test :: String -> IO ()
test =
  mapM_ (\(a, b) -> putStrLn ('\'' : a : ("' : " ++ b))) .
  serialize . huffmanTree . freq

serialize :: HTree a -> [(a, String)]
serialize (Branch l r) =
  (second ('0' :) <$> serialize l) ++ (second ('1' :) <$> serialize r)
serialize (Leaf x) = [(x, "")]

huffmanTree
  :: (Ord w, Num w)
  => [(w, a)] -> HTree a
huffmanTree =
  snd .
  head . until (null . tail) hstep . sortBy (comparing fst) . fmap (second Leaf)

hstep
  :: (Ord a, Num a)
  => [(a, HTree b)] -> [(a, HTree b)]
hstep ((w1, t1):(w2, t2):wts) =
  insertBy (comparing fst) (w1 + w2, Branch t1 t2) wts

freq
  :: Ord a
  => [a] -> [(Int, a)]
freq = fmap (length &&& head) . group . sort

main :: IO ()
main = test "this is an example for huffman encoding"

The code generates Huffman encoding for each character in a given string. It first creates a priority queue with a leaf node for each character symbol. Then, it constructs a binary tree by continuously removing the two nodes with the highest priority (lowest probability) and creating a new internal node with these two nodes as children. The process continues until only one node (the root node) remains in the queue. The code then traverses the binary tree from root to leaves, assigning and accumulating '0' for one branch and '1' for the other at each node. The accumulated zeros and ones at each leaf constitute the Huffman encoding for the corresponding character symbol.


Library: Gtk from HackageDB
import Graphics.UI.Gtk
import Data.IORef

main :: IO ()
main = do
  initGUI
  window <- windowNew
  window `onDestroy` mainQuit
  windowSetTitle window "Simple Windowed App"
  set window [ containerBorderWidth := 10 ]

  hbox <- hBoxNew True 5

  set window [ containerChild := hbox ]

  lab <- labelNew (Just "There have been no clicks yet")
  button <- buttonNewWithLabel "Click me"
  set hbox [ containerChild := lab ]
  set hbox [ containerChild := button ]

  m <- newIORef 0

  onClicked button $ do
    v <- readIORef m
    writeIORef m (v+1)
    set lab [ labelText := "There have been " ++ show (v+1) ++ " clicks" ]

  widgetShowAll window

  mainGUI

Implement a windowed application with a label and a button. The label initially displays "There have been no clicks yet". The button, labelled "click me", updates the label to show the number of times it has been clicked when interacted with.


Library: SQLite
Library: sqlite-simple
{-# LANGUAGE OverloadedStrings #-}

import Database.SQLite.Simple

main = do
     db <- open "postal.db"
     execute_ db "\
     \CREATE TABLE address (\
        \addrID     INTEGER PRIMARY KEY AUTOINCREMENT, \
        \addrStreet TEXT NOT NULL, \
        \addrCity   TEXT NOT NULL, \
        \addrState  TEXT NOT NULL, \
        \addrZIP    TEXT NOT NULL  \
     \)"
     close db

create a table in a database to store US postal addresses, including fields for a unique identifier, street address, city, state code, and zipcode. The codes also demonstrate how to establish a database connection in non-database languages.


import Control.Monad

main :: IO ()
main = forM_ [10,9 .. 0] print

The code performs a countdown from 10 to 0 using a downward for loop.


import Data.Char
import Text.Printf

-- Perform encryption or decryption, depending on f.
crypt f key = map toLetter . zipWith f (cycle key)
  where toLetter = chr . (+) (ord 'A')

-- Encrypt or decrypt one letter.
enc k c = (ord k + ord c) `mod` 26
dec k c = (ord c - ord k) `mod` 26

-- Given a key, encrypt or decrypt an input string.
encrypt = crypt enc
decrypt = crypt dec

-- Convert a string to have only upper case letters.
convert = map toUpper . filter isLetter

main :: IO ()
main = do
  let key  = "VIGENERECIPHER"
      text = "Beware the Jabberwock, my son! The jaws that bite, "
             ++ "the claws that catch!"
      encr = encrypt key $ convert text
      decr = decrypt key encr
  printf "    Input: %s\n      Key: %s\nEncrypted: %s\nDecrypted: %s\n"
    text key encr decr

Implement both encryption and decryption of a Vigenère cipher. The codes handle keys and text of unequal length, capitalize all characters, and discard non-alphabetic characters. If non-alphabetic characters are handled differently, it is noted.


import Control.Monad (forM_)
main = do forM_ [2,4..8] (\x -> putStr (show x ++ ", "))
          putStrLn "who do we appreciate?"

demonstrate a for-loop with a step-value greater than one.


import Control.Monad.ST
import Data.STRef

sum_ :: STRef s Double -> Double -> Double
     -> ST s Double -> ST s Double
sum_ ref lo hi term =
   do
     vs <- forM [lo .. hi]
            (\k -> do { writeSTRef ref k
                      ; term } )
     return $ sum vs

foo :: Double
foo =
  runST $
  do ref <- newSTRef undefined
          -- initial value doesn't matter
     sum_ ref 1 100 $
       do
         k <- readSTRef ref
         return $ recip k

main :: IO ()
main = print foo

implement Jensen's Device, a programming technique devised by Jørn Jensen. The technique is an exercise in call by name, where it computes the 100th harmonic number. The program uses a sum procedure that takes in four parameters, with the first and the last parameter being passed by name. This allows the expression passed as an actual parameter to be re-evaluated in the caller's context every time the corresponding formal parameter's value is required. The program also demonstrates the importance of passing the first parameter by name or by reference, as changes to it within the sum procedure need to be visible in the caller's context when computing each of the values to be added.


import qualified Data.ByteString as BY (writeFile, pack)

import Data.Bits (xor)

main :: IO ()
main =
  BY.writeFile
    "out.pgm"
    (BY.pack
       (fmap (fromIntegral . fromEnum) "P5\n256 256\n256\n" ++
        [ x `xor` y
        | x <- [0 .. 255]
        , y <- [0 .. 255] ]))

generates a graphical pattern by coloring each pixel based on the 'x xor y' value from a given color table, implementing the Munching Squares algorithm.


{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}

import Data.Array.ST
       (STArray, freeze, newArray, readArray, writeArray)
import Data.STRef (STRef, newSTRef, readSTRef, writeSTRef)
import System.Random (Random(..), getStdGen, StdGen)
import Control.Monad (forM_, unless)
import Control.Monad.ST (ST, stToIO)
import Data.Array (Array, (!), bounds)
import Data.Bool (bool)

rand
  :: Random a
  => (a, a) -> STRef s StdGen -> ST s a
rand range gen = do
  (a, g) <- randomR range <$> readSTRef gen
  gen `writeSTRef` g
  return a

data Maze = Maze
  { rightWalls, belowWalls :: Array (Int, Int) Bool
  }

maze :: Int -> Int -> StdGen -> ST s Maze
maze width height gen = do
  visited <- mazeArray False
  rWalls <- mazeArray True
  bWalls <- mazeArray True
  gen <- newSTRef gen
  (,) <$> rand (0, maxX) gen <*> rand (0, maxY) gen >>=
    visit gen visited rWalls bWalls
  Maze <$> freeze rWalls <*> freeze bWalls
  where
    visit gen visited rWalls bWalls here = do
      writeArray visited here True
      let ns = neighbors here
      i <- rand (0, length ns - 1) gen
      forM_ (ns !! i : take i ns ++ drop (i + 1) ns) $
        \there -> do
          seen <- readArray visited there
          unless seen $
            do removeWall here there
               visit gen visited rWalls bWalls there
      where
        removeWall (x1, y1) (x2, y2) =
          writeArray (bool rWalls bWalls (x1 == x2)) (min x1 x2, min y1 y2) False
    neighbors (x, y) =
      bool [(x - 1, y)] [] (0 == x) ++
      bool [(x + 1, y)] [] (maxX == x) ++
      bool [(x, y - 1)] [] (0 == y) ++ bool [(x, y + 1)] [] (maxY == y)
    maxX = width - 1
    maxY = height - 1
    mazeArray =
      newArray ((0, 0), (maxX, maxY)) :: Bool -> ST s (STArray s (Int, Int) Bool)

printMaze :: Maze -> IO ()
printMaze (Maze rWalls bWalls) = do
  putStrLn $ '+' : concat (replicate (maxX + 1) "---+")
  forM_ [0 .. maxY] $
    \y -> do
      putStr "|"
      forM_ [0 .. maxX] $
        \x -> do
          putStr "   "
          putStr $ bool " " "|" (rWalls ! (x, y))
      putStrLn ""
      forM_ [0 .. maxX] $
        \x -> do
          putStr "+"
          putStr $ bool "   " "---" (bWalls ! (x, y))
      putStrLn "+"
  where
    maxX = fst (snd $ bounds rWalls)
    maxY = snd (snd $ bounds rWalls)

main :: IO ()
main = getStdGen >>= stToIO . maze 11 8 >>= printMaze

Sample output:
 +---+---+---+---+---+---+---+---+---+---+---+
 |               |                           |
 +   +---+---+---+   +---+---+---+---+---+   +
 |               |           |   |       |   |
 +   +---+---+   +---+---+   +   +   +   +   +
 |   |   |       |           |       |   |   |
 +   +   +   +---+---+---+---+   +---+   +   +
 |       |   |                   |   |       |
 +---+---+   +   +---+---+---+---+   +---+---+
 |       |   |   |                       |   |
 +   +   +   +   +---+---+---+   +---+   +   +
 |   |       |   |               |       |   |
 +   +---+---+   +   +---+---+---+   +---+   +
 |               |       |           |       |
 +   +---+---+---+---+   +   +---+---+   +   +
 |                       |               |   |
 +---+---+---+---+---+---+---+---+---+---+---+

generate and display a maze using the Depth-first search algorithm. It starts from a random cell, marks it as visited, and gets a list of its neighbors. For each unvisited neighbor, it removes the wall between the current cell and the neighbor, and then recursively continues the process with the neighbor as the current cell.


pi_ = g (1, 0, 1, 1, 3, 3)
  where
    g (q, r, t, k, n, l) =
      if 4 * q + r - t < n * t
        then n :
             g
               ( 10 * q
               , 10 * (r - n * t)
               , t
               , k
               , div (10 * (3 * q + r)) t - 10 * n
               , l)
        else g
               ( q * k
               , (2 * q + r) * l
               , t * l
               , k + 1
               , div (q * (7 * k + 2) + r * l) (t * l)
               , l + 2)

Works with: GHC version 7.4.1
#!/usr/bin/runhaskell

import Control.Monad
import System.IO

pi_ = g(1,0,1,1,3,3) where
  g (q,r,t,k,n,l) =
   if 4*q+r-t < n*t
    then n : g (10*q, 10*(r-n*t), t, k, div (10*(3*q+r)) t - 10*n, l)
    else g (q*k, (2*q+r)*l, t*l, k+1, div (q*(7*k+2)+r*l) (t*l), l+2)

digs = insertPoint digs'
  where insertPoint (x:xs) = x:'.':xs
        digs' = map (head . show) pi_

main = do
  hSetBuffering stdout $ BlockBuffering $ Just 80
  forM_ digs putChar

The code continually calculates and outputs the next decimal digit of Pi. It runs indefinitely until manually stopped by the user. The output starts from the decimal sequence 3.14159265. The code is efficient as each term converges in less than one step, with a slight chance of incorrect digit if checked enough digits. The task is about calculating Pi, not using built-in constants.


"Function to compare and order two numerical lists based on lexicographic order, returning true if the first list should be ordered before the second, and false otherwise."


ack :: Int -> Int -> Int
ack 0 n = succ n
ack m 0 = ack (pred m) 1
ack m n = ack (pred m) (ack m (pred n))

main :: IO ()
main = mapM_ print $ uncurry ack <$> [(0, 0), (3, 4)]

implement the Ackermann function, which is a non-primitive recursive function that takes two non-negative integers as arguments and returns a value based on the provided conditions. The function should ideally have arbitrary precision due to its rapid growth.


implement one or more algorithms to compute the Gamma function in the real field. The implementation's results are compared with the built-in/library function results. The Gamma function is computed through numerical integration, Lanczos approximation, or Stirling's approximation. The code also includes a point-free applicative expression.


import Control.Monad
import Data.List

-- given n, "queens n" solves the n-queens problem, returning a list of all the
-- safe arrangements. each solution is a list of the columns where the queens are
-- located for each row
queens :: Int -> [[Int]]
queens n = map fst $ foldM oneMoreQueen ([],[1..n]) [1..n]  where

  -- foldM :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
  -- foldM folds (from left to right) in the list monad, which is convenient for
  -- "nondeterminstically" finding "all possible solutions" of something. the
  -- initial value [] corresponds to the only safe arrangement of queens in 0 rows

  -- given a safe arrangement y of queens in the first i rows, and a list of
  -- possible choices, "oneMoreQueen y _" returns a list of all the safe
  -- arrangements of queens in the first (i+1) rows along with remaining choices
  oneMoreQueen (y,d) _ = [(x:y, delete x d) | x <- d, safe x]  where

    -- "safe x" tests whether a queen at column x is safe from previous queens
    safe x = and [x /= c + n && x /= c - n | (n,c) <- zip [1..] y]

-- prints what the board looks like for a solution; with an extra newline
printSolution y = do
     let n = length y
     mapM_ (\x -> putStrLn [if z == x then 'Q' else '.' | z <- [1..n]]) y
     putStrLn ""

-- prints all the solutions for 6 queens
main = mapM_ printSolution $ queens 6

import Control.Monad (foldM)
import Data.List ((\\))

main :: IO ()
main = mapM_ print $ queens 8

queens :: Int -> [[Int]]
queens n = foldM f [] [1..n]
    where
      f qs _ = [q:qs | q <- [1..n] \\ qs, q `notDiag` qs]
      q `notDiag` qs = and [abs (q - qi) /= i | (qi,i) <- qs `zip` [1..]]

import Data.List (nub, permutations)

-- checks if queens are on the same diagonal
-- with [0..] we place each queen on her own row
check f = length . nub . zipWith f [0..]

-- filters out results where 2 or more queens are on the same diagonal
-- with [0..n-1] we place each queeen on her own column
generate n = filter (\x -> check (+) x == n && check (-) x == n) $ permutations [0..n-1]

-- 8 is for "8 queens"
main = print $ generate 8

import Data.List (intercalate, transpose)

--------------------- N QUEENS PROBLEM -------------------

queenPuzzle :: Int -> Int -> [[Int]]
queenPuzzle nRows nCols
  | nRows <= 0 = [[]]
  | otherwise =
      foldr
        (\x y -> y <> foldr (go x) [] [1 .. nCols])
        []
        $ queenPuzzle (pred nRows) nCols
  where
    go qs iCol b
      | safe (nRows - 1) iCol qs = b <> [qs <> [iCol]]
      | otherwise = b

safe :: Int -> Int -> [Int] -> Bool
safe iRow iCol qs =
  (not . or) $
    zipWith
      ( \sc sr ->
          (iCol == sc) || (sc + sr == (iCol + iRow))
            || (sc - sr == (iCol - iRow))
      )
      qs
      [0 .. iRow - 1]

--------------------------- TEST -------------------------
-- 10 columns of solutions for the 7*7 board:
showSolutions :: Int -> Int -> [String]
showSolutions nCols nSize =
  unlines
    . fmap (intercalate "   ")
    . transpose
    . map boardLines
    <$> chunksOf nCols (queenPuzzle nSize nSize)
  where
    go r x
      | r == x = '♛'
      | otherwise = '.'
    boardLines rows =
      [ go r <$> [1 .. (length rows)]
        | r <- rows
      ]

chunksOf :: Int -> [a] -> [[a]]
chunksOf i = splits
  where
    splits [] = []
    splits l = take i l : splits (drop i l)

main :: IO ()
main = (putStrLn . unlines) $ showSolutions 10 7

"Code solves the N-queens problem, including the eight queens puzzle, by generating unique horizontal and vertical positions for each queen using permutations. It checks only diagonals for conflicts and includes a backtracking variant using Prelude's plain foldr. The code can also return just one solution by taking the head of the result, leveraging Haskell's laziness."


demonstrate how to concatenate two arrays in Haskell, using either explicit recursion or folding. The '++' operator is used for this task. If the first list is infinite, the output will be the first list.


inv = [("map",9,150), ("compass",13,35), ("water",153,200), ("sandwich",50,160),
	("glucose",15,60), ("tin",68,45), ("banana",27,60), ("apple",39,40),
	("cheese",23,30), ("beer",52,10), ("cream",11,70), ("camera",32,30),
	("tshirt",24,15), ("trousers",48,10), ("umbrella",73,40), ("trousers",42,70),
	("overclothes",43,75), ("notecase",22,80), ("sunglasses",7,20), ("towel",18,12),
	("socks",4,50), ("book",30,10)]

-- get all combos of items under total weight sum; returns value sum and list
combs [] _ = [ (0, []) ]
combs ((name,w,v):rest) cap = combs rest cap ++
		      if w > cap then [] else map (prepend (name,w,v)) (combs rest (cap - w))
		      	where prepend (name,w,v) (v2, lst) = (v2 + v, (name,w,v):lst)

main = do
	putStr "Total value: "; print value
	mapM_ print items
		where (value, items) = maximum $ combs inv 400

The code implements a solution for the 0-1 Knapsack problem. It helps a tourist to determine the combination of items he can carry in his knapsack, with a weight limit of 4kg, in such a way that the total value of the items is maximized. The code considers a list of items with their respective weights and values, and uses a dynamic programming approach with a list for caching to find the optimal combination of items. The solution does not allow for cutting or diminishing the items, meaning only whole units of any item can be taken.


{-# LANGUAGE TemplateHaskell #-}
import Lens.Micro
import Lens.Micro.TH
import Data.List (union, delete)

type Preferences a = (a, [a])
type Couple a = (a,a)
data State a = State { _freeGuys :: [a]
                     , _guys :: [Preferences a]
                     , _girls :: [Preferences a]}

makeLenses ''State

name n = lens get set
  where get = head . dropWhile ((/= n).fst)
        set assoc (_,v) = let (prev, _:post) = break ((== n).fst) assoc
                      in prev ++ (n, v):post

fianceesOf n = guys.name n._2
fiancesOf n = girls.name n._2

 ^.  -- access to a field
 %~  -- modification of a field
 .~  -- setting a field the value

stableMatching :: Eq a => State a -> [Couple a]
stableMatching = getPairs . until (null._freeGuys) step
  where
    getPairs s = map (_2 %~ head) $ s^.guys

step :: Eq a => State a -> State a
step s = foldl propose s (s^.freeGuys)
  where
    propose s guy =
      let girl                = s^.fianceesOf guy & head
          bestGuy : otherGuys = s^.fiancesOf girl
          modify
            | guy == bestGuy       = freeGuys %~ delete guy
            | guy `elem` otherGuys = (fiancesOf girl %~ dropWhile (/= guy)) .
                                     (freeGuys %~ guy `replaceBy` bestGuy)
            | otherwise            = fianceesOf guy %~ tail
      in modify s

    replaceBy x y [] = []
    replaceBy x y (h:t) | h == x = y:t
                        | otherwise = h:replaceBy x y t

unstablePairs :: Eq a => State a -> [Couple a] -> [(Couple a, Couple a)]
unstablePairs s pairs =
  [ ((m1, w1), (m2,w2)) | (m1, w1) <- pairs
                        , (m2,w2) <- pairs
                        , m1 /= m2
                        , let fm = s^.fianceesOf m1
                        , elemIndex w2 fm < elemIndex w1 fm
                        , let fw = s^.fiancesOf w2
                        , elemIndex m2 fw < elemIndex m1 fw ]

guys0 =
  [("abe", ["abi", "eve", "cath", "ivy", "jan", "dee", "fay", "bea", "hope", "gay"]),
   ("bob", ["cath", "hope", "abi", "dee", "eve", "fay", "bea", "jan", "ivy", "gay"]),
   ("col", ["hope", "eve", "abi", "dee", "bea", "fay", "ivy", "gay", "cath", "jan"]),
   ("dan", ["ivy", "fay", "dee", "gay", "hope", "eve", "jan", "bea", "cath", "abi"]),
   ("ed",  ["jan", "dee", "bea", "cath", "fay", "eve", "abi", "ivy", "hope", "gay"]),
   ("fred",["bea", "abi", "dee", "gay", "eve", "ivy", "cath", "jan", "hope", "fay"]),
   ("gav", ["gay", "eve", "ivy", "bea", "cath", "abi", "dee", "hope", "jan", "fay"]),
   ("hal", ["abi", "eve", "hope", "fay", "ivy", "cath", "jan", "bea", "gay", "dee"]),
   ("ian", ["hope", "cath", "dee", "gay", "bea", "abi", "fay", "ivy", "jan", "eve"]),
   ("jon", ["abi", "fay", "jan", "gay", "eve", "bea", "dee", "cath", "ivy", "hope"])]

girls0 =
  [("abi",  ["bob", "fred", "jon", "gav", "ian", "abe", "dan", "ed", "col", "hal"]),
   ("bea",  ["bob", "abe", "col", "fred", "gav", "dan", "ian", "ed", "jon", "hal"]),
   ("cath", ["fred", "bob", "ed", "gav", "hal", "col", "ian", "abe", "dan", "jon"]),
   ("dee",  ["fred", "jon", "col", "abe", "ian", "hal", "gav", "dan", "bob", "ed"]),
   ("eve",  ["jon", "hal", "fred", "dan", "abe", "gav", "col", "ed", "ian", "bob"]),
   ("fay",  ["bob", "abe", "ed", "ian", "jon", "dan", "fred", "gav", "col", "hal"]),
   ("gay",  ["jon", "gav", "hal", "fred", "bob", "abe", "col", "ed", "dan", "ian"]),
   ("hope", ["gav", "jon", "bob", "abe", "ian", "dan", "hal", "ed", "col", "fred"]),
   ("ivy",  ["ian", "col", "hal", "gav", "fred", "bob", "abe", "ed", "jon", "dan"]),
   ("jan",  ["ed", "hal", "gav", "abe", "bob", "jon", "col", "ian", "fred", "dan"])]

s0 = State (fst <$> guys0) guys0 ((_2 %~ reverse) <$> girls0)

λ> let pairs = stableMatching s0
λ> mapM_ print pairs
("abe","ivy")
("bob","cath")
("col","dee")
("dan","fay")
("ed","jan")
("fred","bea")
("gav","gay")
("hal","eve")
("ian","hope")
("jon","abi")
λ> unstablePairs s0 pairs
[]

λ> let fiance n = name n._2
λ> let pairs' = pairs & (fiance "abe" .~ "cath") & (fiance "bob" .~ "ivy")
λ> mapM_ print $ unstablePairs s0 pairs'
(("bob","ivy"),("abe","cath"))
(("bob","ivy"),("dan","fay"))
(("bob","ivy"),("fred","bea"))
(("bob","ivy"),("ian","hope"))
(("bob","ivy"),("jon","abi"))

The code implements the Gale/Shapley algorithm to solve the Stable Marriage Problem. It takes as input a list of ten males and ten females, along with their ranked preferences for each other. The algorithm iteratively pairs the individuals in a way that no man prefers a woman over his current partner, and vice versa. The code also includes a functionality to perturb the stable set of engagements to form an unstable set, and then checks this new set for stability. The code uses lenses for easy access to elements of the state, which consists of the list of free individuals and their preference lists.


module ShortCircuit where

import Prelude hiding ((&&), (||))
import Debug.Trace

False && _     = False
True  && False = False
_     && _     = True

True  || _     = True
False || True  = True
_     || _     = False

a p = trace ("<a " ++ show p ++ ">") p
b p = trace ("<b " ++ show p ++ ">") p

main = mapM_ print (    [ a p || b q | p <- [False, True], q <- [False, True] ]
                     ++ [ a p && b q | p <- [False, True], q <- [False, True] ])

The code defines two functions, a and b, which both take and return the same boolean value while also printing their name when called. The code then calculates and assigns the values of two equations, x = a(i) and b(j) and y = a(i) or b(j), ensuring that function b is only called when necessary. This is achieved through short-circuit evaluation or, if not available, through nested if statements. The code also demonstrates the use of lazy evaluation and pattern matching to control the order of function execution.


import System.IO
import MorseCode
import MorsePlaySox

-- Read standard input, converting text to Morse code, then playing the result.
-- We turn off buffering on stdin so it will play as you type.
main = do
  hSetBuffering stdin NoBuffering
  text <- getContents
  play $ toMorse text

module MorseCode (Morse, MSym(..), toMorse) where

import Data.List
import Data.Maybe
import qualified Data.Map as M

type Morse = [MSym]
data MSym = Dot | Dash | SGap | CGap | WGap deriving (Show)

-- Based on the table of International Morse Code letters and numerals at
-- http://en.wikipedia.org/wiki/Morse_code.
dict = M.fromList
       [('a', m ".-"   ), ('b', m "-..." ), ('c', m "-.-." ), ('d', m "-.."  ),
        ('e', m "."    ), ('f', m "..-." ), ('g', m "--."  ), ('h', m "...." ),
        ('i', m ".."   ), ('j', m ".---" ), ('k', m "-.-"  ), ('l', m ".-.." ),
        ('m', m "--"   ), ('n', m "-."   ), ('o', m "---"  ), ('p', m ".--." ),
        ('q', m "--.-" ), ('r', m ".-."  ), ('s', m "..."  ), ('t', m "-"    ),
        ('u', m "..-"  ), ('v', m "...-" ), ('w', m ".--"  ), ('x', m "-..-" ),
        ('y', m "-.--" ), ('z', m "--.." ), ('1', m ".----"), ('2', m "..---"),
        ('3', m "...--"), ('4', m "....-"), ('5', m "....."), ('6', m "-...."),
        ('7', m "--..."), ('8', m "---.."), ('9', m "----."), ('0', m "-----")]
    where m = intersperse SGap . map toSym
          toSym '.' = Dot
          toSym '-' = Dash

-- Convert a string to a stream of Morse symbols.  We enhance the usual dots
-- and dashes with special "gap" symbols, which indicate the border between
-- symbols, characters and words.  This allows a player to easily adjust its
-- timing by simply looking at the current symbol, rather than trying to keep
-- track of state.
toMorse :: String -> Morse
toMorse = fromWords . words . weed
    where fromWords = intercalate [WGap] . map fromWord
          fromWord  = intercalate [CGap] . map fromChar
          fromChar  = fromJust . flip M.lookup dict
          weed      = filter (\c -> c == ' ' || M.member c dict)

module MorsePlaySox (play) where

import Sound.Sox.Play
import Sound.Sox.Option.Format
import Sound.Sox.Signal.List
import Data.Int
import System.Exit
import MorseCode

samps = 15           -- samples/cycle
freq  = 700          -- cycles/second (frequency)
rate  = samps * freq -- samples/second (sampling rate)

type Samples = [Int16]

-- One cycle of silence and a sine wave.
mute, sine :: Samples
mute = replicate samps 0
sine = let n = fromIntegral samps
           f k = 8000.0 * sin (2*pi*k/n)
       in map (round . f . fromIntegral) [0..samps-1]

-- Repeat samples until we have the specified duration in seconds.
rep :: Float -> Samples -> Samples
rep dur = take n . cycle
    where n = round (dur * fromIntegral rate)

-- Convert Morse symbols to samples.  Durations are in seconds, based on
-- http://en.wikipedia.org/wiki/Morse_code#Representation.2C_timing_and_speeds.
toSamples :: MSym -> Samples
toSamples Dot  = rep 0.1 sine
toSamples Dash = rep 0.3 sine
toSamples SGap = rep 0.1 mute
toSamples CGap = rep 0.3 mute
toSamples WGap = rep 0.7 mute

-- Interpret the stream of Morse symbols as sound.
play :: Morse -> IO ExitCode
play = simple put none rate . concatMap toSamples

The code converts a given string into Morse code and outputs it as audible sound through an audio device. It handles unknown characters by either ignoring them or indicating them with a different pitch. The implementation relies on the "play" program of the SoX package. It includes modules for text-to-Morse code conversion and for interpreting Morse code symbols as sound.


import Data.List (delete)
import Data.Char (toUpper)

-- returns list of all solutions, each solution being a list of blocks
abc :: (Eq a) => [[a]] -> [a] -> [[[a]]]
abc _ [] = [[]]
abc blocks (c:cs) = [b:ans | b <- blocks, c `elem` b,
                             ans <- abc (delete b blocks) cs]

blocks = ["BO", "XK", "DQ", "CP", "NA", "GT", "RE", "TG", "QD", "FS",
          "JW", "HU", "VI", "AN", "OB", "ER", "FS", "LY", "PC", "ZM"]

main :: IO ()
main = mapM_ (\w -> print (w, not . null $ abc blocks (map toUpper w)))
         ["", "A", "BARK", "BoOK", "TrEAT", "COmMoN", "SQUAD", "conFUsE"]

The code is a function that checks if a given word can be spelled using a specific set of ABC blocks. Each block contains two letters and can only be used once. The function is case-insensitive and returns a boolean value indicating whether the word can be formed or not. The function also tests this functionality with seven example words.


import Data.Digest.OpenSSL.MD5 (md5sum)
import Data.ByteString (pack)
import Data.Char (ord)

main = do
  let message = "The quick brown fox jumped over the lazy dog's back"
      digest  = (md5sum . pack . map (fromIntegral . ord)) message
  putStrLn digest

*Main> main
e38ca1d920c4b8b8d3946b2c72f01680

Library: Cryptonite
#!/usr/bin/env runhaskell

import Data.ByteString.Char8 (pack)
import System.Environment (getArgs)
import Crypto.Hash

main :: IO ()
main = print . md5 . pack . unwords =<< getArgs
         where md5 x = hash x :: Digest MD5

The code implements the MD5 algorithm to encode a given string. It uses the nano-MD5 and ByteString modules from HackageDB and the Cryptonite package. The code also includes an optional validation feature by running test values from IETF RFC 1321. However, due to known weaknesses of MD5 such as collisions and forged signatures, it is recommended to consider stronger alternatives like SHA-256 or SHA-3 for production-grade cryptography.


import Data.List ( sort , intercalate )

splitString :: Eq a => (a) -> [a] -> [[a]]
splitString c [] = []
splitString c s = let ( item , rest ) = break ( == c ) s
                      ( _ , next ) = break ( /= c ) rest
		  in item : splitString c next

convertIntListToString :: [Int] -> String
convertIntListToString = intercalate "." . map show

orderOID :: [String] -> [String]
orderOID = map convertIntListToString . sort . map ( map read . splitString '.' )

oid :: [String]
oid = ["1.3.6.1.4.1.11.2.17.19.3.4.0.10" ,
    "1.3.6.1.4.1.11.2.17.5.2.0.79" ,
    "1.3.6.1.4.1.11.2.17.19.3.4.0.4" ,
    "1.3.6.1.4.1.11150.3.4.0.1" ,
    "1.3.6.1.4.1.11.2.17.19.3.4.0.1" ,
    "1.3.6.1.4.1.11150.3.4.0"]

main :: IO ( )
main = do
   mapM_ putStrLn $ orderOID oid

The code sorts a list of Object Identifiers (OIDs). OIDs are strings used to identify objects in network data, consisting of one or more non-negative integers in base 10, separated by dots. The sorting is done lexicographically with regard to the dot-separated fields, using numeric comparison between fields. The code uses the split function from the Data.List.Split library.


import Network

main = withSocketsDo $ sendTo "localhost" (PortNumber $ toEnum 256) "hello socket world"

opens a socket to localhost on port 256, sends the message "hello socket world", and then closes the socket.


{-# LANGUAGE OverloadedStrings #-}

module Main (main) where

import           Network.Mail.SMTP
                    ( Address(..)
                    , htmlPart
                    , plainTextPart
                    , sendMailWithLogin'
                    , simpleMail
                    )

main :: IO ()
main =
    sendMailWithLogin' "smtp.example.com" 25 "user" "password" $
        simpleMail
            (Address (Just "From Example") "from@example.com")
            [Address (Just "To Example") "to@example.com"]
            [] -- CC
            [] -- BCC
            "Subject"
            [ plainTextPart "This is plain text."
            , htmlPart "
Title

This is HTML.
"
            ]

implement a function to send an email with parameters for From, To, Cc addresses, Subject, message text, and optional server name and login details. The solution uses smtp-mail package and provides notifications for success or problems. It is portable across different operating systems.


import Numeric (showOct)

main :: IO ()
main =
  mapM_
    (putStrLn . flip showOct "")
    [1 .. maxBound :: Int]

generate a sequential count in octal, starting from zero and incrementing by one on each line until the program is terminated or the maximum numeric type value is reached.


swap :: (a, b) -> (b, a)
swap (x, y) = (y, x)

import Control.Monad.Ref
swap :: MonadRef r m => r a -> r a -> m ()
swap xRef yRef = do
   x<-readRef xRef
   y<-readRef yRef
   writeRef xRef y
   writeRef yRef x

implement a generic swap function or operator that can interchange the values of two variables or storage places, irrespective of their types. This function works with both statically and dynamically typed languages, with certain constraints for type compatibility. The function also handles issues related to programming language semantics, including difficulties with generic programming in some static languages and the need for indirection in dynamically typed languages. In functional languages, the function does not perform a destructive operation. The code also includes a function that swaps the contents of two mutable references.


is_palindrome x = x == reverse x

import Data.Bifunctor (second)
import Data.Char (toLower)

------------------- PALINDROME DETECTION -----------------

isPalindrome :: Eq a => [a] -> Bool
isPalindrome = (==) <*> reverse

-- Or, comparing just the leftward characters with
-- with a reflection of just the rightward characters.

isPal :: String -> Bool
isPal s =
  let (q, r) = quotRem (length s) 2
   in uncurry (==) $
        second (reverse . drop r) $ splitAt q s

--------------------------- TEST -------------------------
main :: IO ()
main =
  mapM_ putStrLn $
    (showResult <$> [isPalindrome, isPal])
      <*> fmap
        prepared
        [ "",
          "a",
          "ab",
          "aba",
          "abba",
          "In girum imus nocte et consumimur igni"
        ]

prepared :: String -> String
prepared cs = [toLower c | c <- cs, ' ' /= c]

showResult f s = (show s) <> " -> " <> show (f s)

The code includes a function to check if a given sequence of characters is a palindrome. It supports Unicode characters and also has a second function to detect inexact palindromes, ignoring white-space, punctuation, and case differences. The palindrome detection is done both recursively and non-recursively. The non-recursive method involves reversing the string and comparing it with the original, while the recursive method is explained with reference to the C palindrome_r code.


import System.Environment
main = do getEnv "HOME" >>= print  -- get env var
          getEnvironment >>= print -- get the entire environment as a list of (key, value) pairs

"Demonstrates how to retrieve a process's environment variables such as PATH, HOME, or USER in a Unix system."


import Control.Monad.Memo (Memo, memo, startEvalMemo)
import Data.List.Split (chunksOf)
import System.Environment (getArgs)
import Text.Tabular (Header(..), Properties(..), Table(..))
import Text.Tabular.AsciiArt (render)

type SudanArgs = (Int, Integer, Integer)

-- Given argument (n, x, y) calculate Fₙ(x, y).  For performance reasons we do
-- the calculation in a memoization monad.
sudan :: SudanArgs -> Memo SudanArgs Integer Integer
sudan (0, x, y) = return $ x + y
sudan (_, x, 0) = return x
sudan (n, x, y) = memo sudan (n, x, y-1) >>= \x2 -> sudan (n-1, x2, x2 + y)

-- A table of Fₙ(x, y) values, where the rows are y values and the columns are
-- x values.
sudanTable :: Int -> [Integer] -> [Integer] -> String
sudanTable n xs ys = render show show show
                   $ Table (Group NoLine $ map Header ys)
                           (Group NoLine $ map Header xs)
                   $ chunksOf (length xs)
                   $ startEvalMemo
                   $ sequence
                   $ [sudan (n, x, y) | y <- ys, x <- xs]

main :: IO ()
main = do
  args <- getArgs
  case args of
    [n, xlo, xhi, ylo, yhi] -> do
      putStrLn $ "Fₙ(x, y), where the rows are y values " ++
                 "and the columns are x values.\n"
      putStr $ sudanTable (read n)
                          [read xlo .. read xhi]
                          [read ylo .. read yhi]
    _ -> error "Usage: sudan n xmin xmax ymin ymax"

Implement the Sudan function, a non-primitive recursive function. The function takes two arguments, x and y, and returns a value based on the defined recursive rules.


def stack = []
assert stack.empty

stack.push(55)
stack.push(21)
stack.push('kittens')
assert stack.last() == 'kittens'
assert stack.size() == 3
assert ! stack.empty

println stack

assert stack.pop() == "kittens"
assert stack.size() == 2

println stack

stack.push(-20)

println stack

stack.push( stack.pop() * stack.pop() )
assert stack.last() == -420
assert stack.size() == 2

println stack

stack.push(stack.pop() / stack.pop())
assert stack.size() == 1

println stack

println stack.pop()
assert stack.size() == 0
assert stack.empty

try { stack.pop() } catch (NoSuchElementException e) { println e.message }

implement a stack data structure with basic operations such as push, pop, and empty. The stack follows a last in, first out (LIFO) access policy and allows access to the last pushed element without modifying the stack. It also includes functionality to check if the stack is empty.


def rFib
rFib = {
    it == 0   ? 0
    : it == 1 ? 1
    : it > 1  ? rFib(it-1) + rFib(it-2)
    /*it < 0*/: rFib(it+2) - rFib(it+1)

}
def iFib = {
    it == 0   ? 0
    : it == 1 ? 1
    : it > 1  ? (2..it).inject([0,1]){i, j -> [i[1], i[0]+i[1]]}[1]
    /*it < 0*/: (-1..it).inject([0,1]){i, j -> [i[1]-i[0], i[0]]}[0]
}
final φ = (1 + 5**(1/2))/2
def aFib = { (φ**it - (-φ)**(-it))/(5**(1/2)) as BigInteger }

def time = { Closure c ->
    def start = System.currentTimeMillis()
    def result = c()
    def elapsedMS = (System.currentTimeMillis() - start)/1000
    printf '(%6.4fs elapsed)', elapsedMS
    result
}

print "  F(n)      elapsed time   "; (-10..10).each { printf ' %3d', it }; println()
print "--------- -----------------"; (-10..10).each { print ' ---' }; println()
[recursive:rFib, iterative:iFib, analytic:aFib].each { name, fib ->
    printf "%9s ", name
    def fibList = time { (-10..10).collect {fib(it)} }
    fibList.each { printf ' %3d', it }
    println()
}

The code implements a function to generate the nth Fibonacci number. It uses either an iterative or recursive approach, with the recursive method being potentially slower. The function also optionally supports negative n values by inversely applying the Fibonacci sequence formula. A recursive closure is pre-declared for full solutions.


select certain elements from an array into a new array in a generic way. Specifically, it selects all even numbers from an array. Optionally, it can also filter destructively by modifying the original array instead of creating a new one.


def str = 'abcdefgh'
def n = 2
def m = 3
// #1
println str[n..n+m-1]
/* or */
println str[n..<(n+m)]
// #2
println str[n..-1]
// #3
println str[0..-2]
// #4
def index1 = str.indexOf('d')
println str[index1..index1+m-1]
/* or */
println str[index1..<(index1+m)]
// #5
def index2 = str.indexOf('de')
println str[index2..index2+m-1]
/* or */
println str[index2..<(index2+m)]

- Display a substring starting from a specified character index and of a specified length.
- Display a substring starting from a specified character index to the end of the string.
- Display the entire string except the last character.
- Display a substring starting from a known character within the string and of a specified length.
- Display a substring starting from a known substring within the string and of a specified length.
- The code supports any valid Unicode code point in UTF-8 or UTF-16 encoding.
- The code references logical characters, not 8-bit code units for UTF-8 or 16-bit code units for UTF-16.
- The code does not necessarily support all Unicode characters for other encodings like 8-bit ASCII, or EUC-JP.
- Strings in the code are 0-indexed.


println "Able was I, 'ere I saw Elba.".reverse()

Reverses a given string while preserving Unicode combining characters. For instance, it transforms "asdf" to "fdsa" and "as⃝df̅" to "f̅ds⃝a".


class Circles {
    private static class Point {
        private final double x, y

        Point(Double x, Double y) {
            this.x = x
            this.y = y
        }

        double distanceFrom(Point other) {
            double dx = x - other.x
            double dy = y - other.y
            return Math.sqrt(dx * dx + dy * dy)
        }

        @Override
        boolean equals(Object other) {
            //if (this == other) return true
            if (other == null || getClass() != other.getClass()) return false
            Point point = (Point) other
            return x == point.x && y == point.y
        }

        @Override
        String toString() {
            return String.format("(%.4f, %.4f)", x, y)
        }
    }

    private static Point[] findCircles(Point p1, Point p2, double r) {
        if (r < 0.0) throw new IllegalArgumentException("the radius can't be negative")
        if (r == 0.0.toDouble() && p1 != p2) throw new IllegalArgumentException("no circles can ever be drawn")
        if (r == 0.0.toDouble()) return [p1, p1]
        if (Objects.equals(p1, p2)) throw new IllegalArgumentException("an infinite number of circles can be drawn")
        double distance = p1.distanceFrom(p2)
        double diameter = 2.0 * r
        if (distance > diameter) throw new IllegalArgumentException("the points are too far apart to draw a circle")
        Point center = new Point((p1.x + p2.x) / 2.0, (p1.y + p2.y) / 2.0)
        if (distance == diameter) return [center, center]
        double mirrorDistance = Math.sqrt(r * r - distance * distance / 4.0)
        double dx = (p2.x - p1.x) * mirrorDistance / distance
        double dy = (p2.y - p1.y) * mirrorDistance / distance
        return [
            new Point(center.x - dy, center.y + dx),
            new Point(center.x + dy, center.y - dx)
        ]
    }

    static void main(String[] args) {
        Point[] p = [
            new Point(0.1234, 0.9876),
            new Point(0.8765, 0.2345),
            new Point(0.0000, 2.0000),
            new Point(0.0000, 0.0000)
        ]
        Point[][] points = [
            [p[0], p[1]],
            [p[2], p[3]],
            [p[0], p[0]],
            [p[0], p[1]],
            [p[0], p[0]],
        ]
        double[] radii = [2.0, 1.0, 2.0, 0.5, 0.0]
        for (int i = 0; i < radii.length; ++i) {
            Point p1 = points[i][0]
            Point p2 = points[i][1]
            double r = radii[i]
            printf("For points %s and %s with radius %f\n", p1, p2, r)
            try {
                Point[] circles = findCircles(p1, p2, r)
                Point c1 = circles[0]
                Point c2 = circles[1]
                if (Objects.equals(c1, c2)) {
                    printf("there is just one circle with center at %s\n", c1)
                } else {
                    printf("there are two circles with centers at %s and %s\n", c1, c2)
                }
            } catch (IllegalArgumentException ex) {
                println(ex.getMessage())
            }
            println()
        }
    }
}

"Function to calculate two possible circles given two points and a radius in 2D space. The function handles special cases such as when radius is zero, points are coincident, points form a diameter, or points are too distant. The function returns the circles or a special indication when two equal or distinct circles cannot be returned."


final random = new Random()

while (true) {
    def random1 = random.nextInt(20)
    print random1
    if (random1 == 10) break
    print '     '
    println random.nextInt(20)
}

generate and print random numbers from 0 to 19. If the generated number is 10, the loop stops. If the number is not 10, a second random number is generated and printed before the loop restarts. If 10 is never generated, the loop runs indefinitely.


def inventory = new XmlSlurper().parseText("<inventory...")    //optionally parseText(new File("inv.xml").text)
def firstItem = inventory.section.item[0]                      //1. first item
inventory.section.item.price.each { println it }               //2. print each price
def allNamesArray = inventory.section.item.name.collect {it}   //3. collect item names into an array

1. Retrieves the first "item" element from the XML document.
2. Prints out each "price" element from the XML document.
3. Gets an array of all the "name" elements from the XML document.


def s1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as Set
def m1 = 6
def m2 = 7
def s2 = [0, 2, 4, 6, 8] as Set
assert m1 in s1                                        : 'member'
assert ! (m2 in s2)                                    : 'not a member'
def su = s1 + s2
assert su == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as Set : 'union'
def si = s1.intersect(s2)
assert si == [8, 6, 4, 2] as Set                       : 'intersection'
def sd = s1 - s2
assert sd == [1, 3, 5, 7, 9, 10] as Set                : 'difference'
assert s1.containsAll(si)                              : 'subset'
assert ! s1.containsAll(s2)                            : 'not a subset'
assert (si + sd) == s1                                 : 'equality'
assert (s2 + sd) != s1                                 : 'inequality'
assert s1 != su && su.containsAll(s1)                  : 'proper subset'
s1 << 0
assert s1 == su                                        : 'added element 0 to s1'

demonstrate various set operations such as creation, checking if an element is present in a set, union, intersection, difference, subset and equality of sets. The code also optionally shows other set operations and methods to modify a mutable set. It may implement a set using an associative array, binary search tree, hash table, or an ordered array of binary bits. The code also discusses the time complexity of the basic test operation in different scenarios.


def yuletide = { start, stop -> (start..stop).findAll { Date.parse("yyyy-MM-dd", "${it}-12-25").format("EEE") == "Sun" } }

println yuletide(2008, 2121)

The code determines the years between 2008 and 2121 where Christmas day falls on a Sunday, using standard date handling libraries. It also compares the results with outputs from other languages to identify any discrepancies due to issues like overflow in date/time representation.


def list = [1, 2, 3, 'a', 'b', 'c', 2, 3, 4, 'b', 'c', 'd']
assert list.size() == 12
println "             Original List: ${list}"

// Filtering the List (non-mutating)
def list2 = list.unique(false)
assert list2.size() == 8
assert list.size() == 12
println "             Filtered List: ${list2}"

// Filtering the List (in place)
list.unique()
assert list.size() == 8
println "   Original List, filtered: ${list}"

def list3 = [1, 2, 3, 'a', 'b', 'c', 2, 3, 4, 'b', 'c', 'd']
assert list3.size() == 12

// Converting to Set
def set = list as Set
assert set.size() == 8
println "                       Set: ${set}"

implement three methods to remove duplicate elements from an array: 1) Using a hash table, 2) Sorting the array and removing consecutive duplicates, and 3) Iterating through the list and discarding any repeated elements.


def isoFormat = { date -> date.format("yyyy-MM-dd") }
def longFormat = { date -> date.format("EEEE, MMMM dd, yyyy") }

def now = new Date()
println isoFormat(now)
println longFormat(now)

display the current date in two formats: "2007-11-23" and "Friday, November 23, 2007".


def powerSetRec(head, tail) {
    if (!tail) return [head]
    powerSetRec(head, tail.tail()) + powerSetRec(head + [tail.head()], tail.tail())
}

def powerSet(set) { powerSetRec([], set as List) as Set}

def vocalists = [ 'C', 'S', 'N', 'Y' ] as Set
println vocalists
println powerSet(vocalists)

The code is a function that takes a set S as input and returns the power set of S. The power set includes all possible subsets of S, including the empty set and the set itself. The function can handle edge cases such as the power set of an empty set and the power set of a set containing only the empty set. The code is written in Groovy and uses a combination of Set and List data structures for its implementation.


symbols = [ 1:'I', 4:'IV', 5:'V', 9:'IX', 10:'X', 40:'XL', 50:'L', 90:'XC', 100:'C', 400:'CD', 500:'D', 900:'CM', 1000:'M' ]

def roman(arabic) {
    def result = ""
    symbols.keySet().sort().reverse().each {
        while (arabic >= it) {
            arabic-=it
            result+=symbols[it]
        }
    }
    return result
}
assert roman(1) == 'I'
assert roman(2) == 'II'
assert roman(4) == 'IV'
assert roman(8) == 'VIII'
assert roman(16) == 'XVI'
assert roman(32) == 'XXXII'
assert roman(25) == 'XXV'
assert roman(64) == 'LXIV'
assert roman(128) == 'CXXVIII'
assert roman(256) == 'CCLVI'
assert roman(512) == 'DXII'
assert roman(954) == 'CMLIV'
assert roman(1024) == 'MXXIV'
assert roman(1666) == 'MDCLXVI'
assert roman(1990) == 'MCMXC'
assert roman(2008) == 'MMVIII'

create a function that converts a positive integer into its equivalent Roman numeral representation.


def aa = [ 1, 25, 31, -3 ]           // list
def a = [0] * 100                    // list of 100 zeroes
def b = 1..9                         // range notation
def c = (1..10).collect { 2.0**it }  // each output element is 2**(corresponding invoking list element)

// There are no true "multi-dimensional" arrays in Groovy (as in most C-derived languages).
// Use lists of lists in natural ("row major") order as a stand in.
def d = (0..1).collect { i -> (1..5).collect { j -> 2**(5*i+j) as double } }
def e = [ [  1.0,  2.0,  3.0,  4.0 ],
          [  5.0,  6.0,  7.0,  8.0 ],
          [  9.0, 10.0, 11.0, 12.0 ],
          [ 13.0, 14.0, 15.0, 16.0 ] ]

println aa
println b
println c
println()
d.each { print "["; it.each { elt -> printf "%7.1f ", elt }; println "]" }
println()
e.each { print "["; it.each { elt -> printf "%7.1f ", elt }; println "]" }

demonstrate the basic syntax of arrays in Groovy, including creating an array, assigning a value, and retrieving an element. Both fixed-length and dynamic arrays are shown, with an example of pushing a value into an array. The code also includes a function that creates and returns a square identity matrix of order N. It highlights the use of zero-based array/list indexing, the validity of negative indices, and the ability to resequence and subsequence Groovy lists by providing lists or ranges of indices.


content = new File('input.txt').text
new File('output.txt').write(content)

new AntBuilder().copy(file:'input.txt', toFile:'output.txt', overwrite:true)

new File('output.txt').withWriter( w ->
  new File('input.txt').withReader( r -> w << r }
}

demonstrate how to read the contents of "input.txt" file into an intermediate variable and then write those contents into a new file called "output.txt". It also shows how to use File, Ant, and Buffered methods. The code does not include oneliners that skip the intermediate variable.


def str = 'alphaBETA'

println str.toUpperCase()
println str.toLowerCase()

ALPHABETA
alphabeta

demonstrate the conversion of the string "alphaBETA" to both upper-case and lower-case using the default string literal or ASCII encoding. The code also showcases additional case conversion functions such as swapping case or capitalizing the first letter, if available in the language's library. Note that in some languages, the conversion between lower and upper case may not be reversible.


class Point {
    final Number x, y
    Point(Number x = 0, Number y = 0) { this.x = x; this.y = y }
    Number distance(Point that) { ((this.x - that.x)**2 + (this.y - that.y)**2)**0.5 }
    String toString() { "{x:${x}, y:${y}}" }
}

def bruteClosest(Collection pointCol) {
    assert pointCol
    List l = pointCol
    int n = l.size()
    assert n > 1
    if (n == 2) return [distance:l[0].distance(l[1]), points:[l[0],l[1]]]
    def answer = [distance: Double.POSITIVE_INFINITY]
    (0..<(n-1)).each { i ->
        ((i+1)..<n).findAll { j ->
            (l[i].x - l[j].x).abs() < answer.distance &&
            (l[i].y - l[j].y).abs() < answer.distance
        }.each { j ->
            if ((l[i].x - l[j].x).abs() < answer.distance &&
                (l[i].y - l[j].y).abs() < answer.distance) {
                def dist = l[i].distance(l[j])
                if (dist < answer.distance) {
                    answer = [distance:dist, points:[l[i],l[j]]]
                }
            }
        }
    }
    answer
}

def elegantClosest(Collection pointCol) {
    assert pointCol
    List xList = (pointCol as List).sort { it.x }
    List yList = xList.clone().sort { it.y }
    reductionClosest(xList, xList)
}

def reductionClosest(List xPoints, List yPoints) {
//    assert xPoints && yPoints
//    assert (xPoints as Set) == (yPoints as Set)
    int n = xPoints.size()
    if (n < 10) return bruteClosest(xPoints)

    int nMid = Math.ceil(n/2)
    List xLeft = xPoints[0..<nMid]
    List xRight = xPoints[nMid..<n]
    Number xMid = xLeft[-1].x
    List yLeft = yPoints.findAll { it.x <= xMid }
    List yRight = yPoints.findAll { it.x > xMid }
    if (xRight[0].x == xMid) {
        yLeft = xLeft.collect{ it }.sort { it.y }
        yRight = xRight.collect{ it }.sort { it.y }
    }

    Map aLeft = reductionClosest(xLeft, yLeft)
    Map aRight = reductionClosest(xRight, yRight)
    Map aMin = aRight.distance < aLeft.distance ? aRight : aLeft
    List yMid = yPoints.findAll { (xMid - it.x).abs() < aMin.distance }
    int nyMid = yMid.size()
    if (nyMid < 2) return aMin

    Map answer = aMin
    (0..<(nyMid-1)).each { i ->
        ((i+1)..<nyMid).findAll { j ->
            (yMid[j].x - yMid[i].x).abs() < aMin.distance &&
            (yMid[j].y - yMid[i].y).abs() < aMin.distance &&
            yMid[j].distance(yMid[i]) < aMin.distance
        }.each { k ->
            if ((yMid[k].x - yMid[i].x).abs() < answer.distance && (yMid[k].y - yMid[i].y).abs() < answer.distance) {
                def ikDist = yMid[i].distance(yMid[k])
                if ( ikDist < answer.distance) {
                    answer = [distance:ikDist, points:[yMid[i],yMid[k]]]
                }
            }
        }
    }
    answer
}

def random = new Random()

(1..4).each {
def point10 = (0..<(10**it)).collect { new Point(random.nextInt(1000001) - 500000,random.nextInt(1000001) - 500000) }

def startE = System.currentTimeMillis()
def closestE = elegantClosest(point10)
def elapsedE = System.currentTimeMillis() - startE
println """
${10**it} POINTS
-----------------------------------------
Elegant reduction:
elapsed: ${elapsedE/1000} s
closest: ${closestE}
"""

def startB = System.currentTimeMillis()
def closestB = bruteClosest(point10)
def elapsedB = System.currentTimeMillis() - startB
println """Brute force:
elapsed: ${elapsedB/1000} s
closest: ${closestB}

Speedup ratio (B/E): ${elapsedB/elapsedE}
=========================================
"""
}

10 POINTS
-----------------------------------------
Elegant reduction:
elapsed: 0.019 s
closest: [distance:85758.5249173515, points:[{x:310073, y:-27339}, {x:382387, y:18761}]]

Brute force:
elapsed: 0.001 s
closest: [distance:85758.5249173515, points:[{x:310073, y:-27339}, {x:382387, y:18761}]]

Speedup ratio (B/E): 0.0526315789
=========================================

100 POINTS
-----------------------------------------
Elegant reduction:
elapsed: 0.019 s
closest: [distance:3166.229934796271, points:[{x:-343735, y:-244394}, {x:-341099, y:-246148}]]

Brute force:
elapsed: 0.027 s
closest: [distance:3166.229934796271, points:[{x:-343735, y:-244394}, {x:-341099, y:-246148}]]

Speedup ratio (B/E): 1.4210526316
=========================================

1000 POINTS
-----------------------------------------
Elegant reduction:
elapsed: 0.241 s
closest: [distance:374.22586762542215, points:[{x:411817, y:-83016}, {x:412038, y:-82714}]]

Brute force:
elapsed: 0.618 s
closest: [distance:374.22586762542215, points:[{x:411817, y:-83016}, {x:412038, y:-82714}]]

Speedup ratio (B/E): 2.5643153527
=========================================

10000 POINTS
-----------------------------------------
Elegant reduction:
elapsed: 1.957 s
closest: [distance:79.00632886041473, points:[{x:187928, y:-452338}, {x:187929, y:-452259}]]

Brute force:
elapsed: 51.567 s
closest: [distance:79.00632886041473, points:[{x:187928, y:-452338}, {x:187929, y:-452259}]]

Speedup ratio (B/E): 26.3500255493
=========================================

The code provides two solutions to solve the Closest Pair of Points problem in a two-dimensional plane. The first solution uses a brute force approach with a time complexity of O(n^2), which calculates the minimum distance between any two points. The second solution uses a divide-and-conquer strategy with a time complexity of O(n log n), which sorts the points based on x and y coordinates, divides them into two halves, and recursively finds the closest pairs. Both solutions incorporate X-only and Y-only pre-checks to optimize the square root calculations.


def emptyList = []
assert emptyList.isEmpty() : "These are not the items you're looking for"
assert emptyList.size() == 0 : "Empty list has size 0"
assert ! emptyList : "Empty list evaluates as boolean 'false'"

def initializedList = [ 1, "b", java.awt.Color.BLUE ]
assert initializedList.size() == 3
assert initializedList : "Non-empty list evaluates as boolean 'true'"
assert initializedList[2] == java.awt.Color.BLUE : "referencing a single element (zero-based indexing)"
assert initializedList[-1] == java.awt.Color.BLUE : "referencing a single element (reverse indexing of last element)"

def combinedList = initializedList + [ "more stuff", "even more stuff" ]
assert combinedList.size() == 5
assert combinedList[1..3] == ["b", java.awt.Color.BLUE, "more stuff"] : "referencing a range of elements"

combinedList << "even more stuff"
assert combinedList.size() == 6
assert combinedList[-1..-3] == \
        ["even more stuff", "even more stuff", "more stuff"] \
                : "reverse referencing last 3 elements"
println ([combinedList: combinedList])

The code creates a collection and adds a few values to it. It utilizes the concept of collections, which are abstractions to represent sets of values, typically of a common data type in statically-typed languages. The code might also involve operations with Lists, Maps, and Sets.


def totalWeight = { list -> list.collect{ it.item.weight * it.count }.sum() }
def totalVolume = { list -> list.collect{ it.item.volume * it.count }.sum() }
def totalValue = { list -> list.collect{ it.item.value * it.count }.sum() }

def knapsackUnbounded = { possibleItems, BigDecimal weightMax, BigDecimal volumeMax ->
    def n = possibleItems.size()
    def wm = weightMax.unscaledValue()
    def vm = volumeMax.unscaledValue()
    def m = (0..n).collect{ i -> (0..wm).collect{ w -> (0..vm).collect{ v -> [] } } }
    (1..wm).each { w ->
        (1..vm).each { v ->
            (1..n).each { i ->
                def item = possibleItems[i-1]
                def wi = item.weight.unscaledValue()
                def vi = item.volume.unscaledValue()
                def bi = [w.intdiv(wi),v.intdiv(vi)].min()
                m[i][w][v] = (0..bi).collect{ count ->
                    m[i-1][w - wi * count][v - vi * count] + [[item:item, count:count]]
                }.max(totalValue).findAll{ it.count }
            }
        }
    }
    m[n][wm][vm]
}

Set solutions = []
items.eachPermutation { itemList ->
    def start = System.currentTimeMillis()
    def packingList = knapsackUnbounded(itemList, 25.0, 0.250)
    def elapsed = System.currentTimeMillis() - start

    println "\n  Item Order: ${itemList.collect{ it.name.split()[0] }}"
    println "Elapsed Time: ${elapsed/1000.0} s"

    solutions << (packingList as Set)
}

solutions.each { packingList ->
    println "\nTotal Weight: ${totalWeight(packingList)}"
    println "Total Volume: ${totalVolume(packingList)}"
    println " Total Value: ${totalValue(packingList)}"
    packingList.each {
        printf ('  item: %-22s  count:%2d  weight:%4.1f  Volume:%5.3f\n',
                it.item.name, it.count, it.item.weight * it.count, it.item.volume * it.count)
    }
}

  Item Order: [panacea, ichor, gold]
Elapsed Time: 26.883 s

  Item Order: [panacea, gold, ichor]
Elapsed Time: 27.17 s

  Item Order: [ichor, panacea, gold]
Elapsed Time: 25.884 s

  Item Order: [ichor, gold, panacea]
Elapsed Time: 26.126 s

  Item Order: [gold, panacea, ichor]
Elapsed Time: 26.596 s

  Item Order: [gold, ichor, panacea]
Elapsed Time: 26.47 s

Total Weight: 25.0
Total Volume: 0.247
 Total Value: 54500
  item: gold (bars)             count:11  weight:22.0  Volume:0.022
  item: ichor (ampules of)      count:15  weight: 3.0  Volume:0.225

Total Weight: 24.7
Total Volume: 0.247
 Total Value: 54500
  item: gold (bars)             count:11  weight:22.0  Volume:0.022
  item: panacea (vials of)      count: 9  weight: 2.7  Volume:0.225

Total Weight: 24.9
Total Volume: 0.247
 Total Value: 54500
  item: gold (bars)             count:11  weight:22.0  Volume:0.022
  item: ichor (ampules of)      count:10  weight: 2.0  Volume:0.150
  item: panacea (vials of)      count: 3  weight: 0.9  Volume:0.075

Total Weight: 24.8
Total Volume: 0.247
 Total Value: 54500
  item: gold (bars)             count:11  weight:22.0  Volume:0.022
  item: ichor (ampules of)      count: 5  weight: 1.0  Volume:0.075
  item: panacea (vials of)      count: 6  weight: 1.8  Volume:0.150

implement a dynamic programming solution for the unbounded Knapsack problem. The task is to determine the maximum value of items a traveler can carry from Shangri La, given the weight and volume constraints of his knapsack and the weight, volume, and value of each available item. The solution also considers the possibility of multiple optimal solutions due to items with the same value and volume but different weights.


generates a comma-separated list of numbers from 1 to 10, using separate output statements for the number and the comma within the loop body.


assert "abcd".startsWith("ab")
assert ! "abcd".startsWith("zn")
assert "abcd".endsWith("cd")
assert ! "abcd".endsWith("zn")
assert "abab".contains("ba")
assert ! "abab".contains("bb")

assert "abab".indexOf("bb") == -1 // not found flag
assert "abab".indexOf("ab") == 0

def indicesOf = { string, substring ->
    if (!string) { return [] }
    def indices = [-1]
    while (true) {
        indices << string.indexOf(substring, indices.last()+1)
        if (indices.last() == -1) break
    }
    indices[1..<(indices.size()-1)]
}
assert indicesOf("abab", "ab") == [0, 2]
assert indicesOf("abab", "ba") == [1]
assert indicesOf("abab", "xy") == []

The code performs three types of string matching operations: checks if the first string starts with the second string, checks if the first string contains the second string at any location, and checks if the first string ends with the second string. Optionally, it can print the location of the match and handle multiple occurrences of a string.


class FourRings {
    static void main(String[] args) {
        fourSquare(1, 7, true, true)
        fourSquare(3, 9, true, true)
        fourSquare(0, 9, false, false)
    }

    private static void fourSquare(int low, int high, boolean unique, boolean print) {
        int count = 0

        if (print) {
            println("a b c d e f g")
        }
        for (int a = low; a <= high; ++a) {
            for (int b = low; b <= high; ++b) {
                if (notValid(unique, a, b)) continue

                int fp = a + b
                for (int c = low; c <= high; ++c) {
                    if (notValid(unique, c, a, b)) continue
                    for (int d = low; d <= high; ++d) {
                        if (notValid(unique, d, a, b, c)) continue
                        if (fp != b + c + d) continue

                        for (int e = low; e <= high; ++e) {
                            if (notValid(unique, e, a, b, c, d)) continue
                            for (int f = low; f <= high; ++f) {
                                if (notValid(unique, f, a, b, c, d, e)) continue
                                if (fp != d + e + f) continue

                                for (int g = low; g <= high; ++g) {
                                    if (notValid(unique, g, a, b, c, d, e, f)) continue
                                    if (fp != f + g) continue

                                    ++count
                                    if (print) {
                                        printf("%d %d %d %d %d %d %d%n", a, b, c, d, e, f, g)
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        if (unique) {
            printf("There are %d unique solutions in [%d, %d]%n", count, low, high)
        } else {
            printf("There are %d non-unique solutions in [%d, %d]%n", count, low, high)
        }
    }

    private static boolean notValid(boolean unique, int needle, int ... haystack) {
        return unique && Arrays.stream(haystack).anyMatch({ p -> p == needle })
    }
}

The code finds all possible solutions for a 4-squares puzzle where each square sums up to the same total. It operates under two conditions: each letter representing a unique value between 1-7 and 3-9, and each letter representing a non-unique value between 0-9. The code also counts the number of non-unique solutions.


class Triple {
    BigInteger a, b, c
    def getPerimeter() { this.with { a + b + c } }
    boolean isValid() { this.with { a*a + b*b == c*c } }
}

def initCounts (def n = 10) {
    (n..1).collect { 10g**it }.inject ([:]) { Map map, BigInteger perimeterLimit ->
        map << [(perimeterLimit): [primative: 0g, total: 0g]]
    }
}

def findPythagTriples, findChildTriples

findPythagTriples = {Triple t = new Triple(a:3, b:4, c:5), Map counts = initCounts() ->
    def p = t.perimeter
    def currentCounts = counts.findAll { pLimit, tripleCounts -> p <= pLimit }
    if (! currentCounts || ! t.valid) { return }
    currentCounts.each { pLimit, tripleCounts ->
        tripleCounts.with { primative ++; total += pLimit.intdiv(p) }
    }
    findChildTriples(t, currentCounts)
    counts
}

findChildTriples = { Triple t, Map counts ->
    t.with {
        [
            [ a - 2*b + 2*c,  2*a - b + 2*c,  2*a - 2*b + 3*c],
            [ a + 2*b + 2*c,  2*a + b + 2*c,  2*a + 2*b + 3*c],
            [-a + 2*b + 2*c, -2*a + b + 2*c, -2*a + 2*b + 3*c]
        ]*.sort().each { aa, bb, cc ->
            findPythagTriples(new Triple(a:aa, b:bb, c:cc), counts)
        }
    }
}

printf ('    LIMIT       PRIMATIVE          ALL\n')
findPythagTriples().sort().each { perimeterLimit, result ->
    def exponent = perimeterLimit.toString().size() - 1
    printf ('a+b+c <= 10E%2d  %9d %12d\n', exponent, result.primative, result.total)
}

    LIMIT       PRIMATIVE          ALL
a+b+c <= 10E 1          0            0
a+b+c <= 10E 2          7           17
a+b+c <= 10E 3         70          325
a+b+c <= 10E 4        703         4858
a+b+c <= 10E 5       7026        64741
a+b+c <= 10E 6      70229       808950
a+b+c <= 10E 7     702309      9706567
a+b+c <= 10E 8    7023027    113236940
a+b+c <= 10E 9   70230484   1294080089
a+b+c <= 10E10  702304875  14557915466

determine the number of Pythagorean triples with a perimeter not exceeding 100, as well as the number of these triples that are primitive. The code also includes an extra feature to handle large perimeter values up to 100,000,000 efficiently.


 import groovy.swing.SwingBuilder

 new SwingBuilder().frame(title:'My Window', size:[200,100]).show()

"Creates an empty GUI window that can respond to close requests."


def frequency = { it.inject([:]) { map, value -> map[value] = (map[value] ?: 0) + 1; map } }

frequency(new File('frequency.groovy').text).each { key, value ->
    println "'$key': $value"
}

Open a text file, count the frequency of each letter, and differentiate between counting all characters or only letters A to Z.


class ListNode {
    Object payload
    ListNode next
    String toString() { "${payload} -> ${next}" }
}

def n1 = new ListNode(payload:25)
n1.next = new ListNode(payload:88)

println n1

25 -> 88 -> null

define the data structure for a singly-linked list element, which includes a numeric data member and a mutable link to the next element.


def factorize = { long target ->

    if (target == 1) return [1L]

    if (target < 4) return [1L, target]

    def targetSqrt = Math.sqrt(target)
    def lowfactors = (2L..targetSqrt).grep { (target % it) == 0 }
    if (lowfactors == []) return [1L, target]
    def nhalf = lowfactors.size() - ((lowfactors[-1] == targetSqrt) ? 1 : 0)

    [1] + lowfactors + (0..<nhalf).collect { target.intdiv(lowfactors[it]) }.reverse() + [target]
}

((1..30) + [333333]).each { println ([number:it, factors:factorize(it)]) }

Calculate the factors of a positive integer using a brute force approach up to the square root of the input number. The code does not handle cases of zero or negative integers. For prime numbers, the factors will be 1 and the number itself.


def alignColumns = { align, rawText ->
    def lines = rawText.tokenize('\n')
    def words = lines.collect { it.tokenize(/\$/) }
    def maxLineWords = words.collect {it.size()}.max()
    words = words.collect { line -> line + [''] * (maxLineWords - line.size()) }
    def columnWidths = words.transpose().collect{ column -> column.collect { it.size() }.max() }

    def justify = [   Right  : { width, string -> string.padLeft(width) },
                            Left   : { width, string -> string.padRight(width) },
                            Center : { width, string -> string.center(width) }      ]
    def padAll = { pad, colWidths, lineWords -> [colWidths, lineWords].transpose().collect { pad(it) + ' ' } }

    words.each { padAll(justify[align], columnWidths, it).each { print it }; println() }
}

def rawTextInput = '''Given$a$text$file$of$many$lines,$where$fields$within$a$line$
are$delineated$by$a$single$'dollar'$character,$write$a$program
that$aligns$each$column$of$fields$by$ensuring$that$words$in$each$
column$are$separated$by$at$least$one$space.
Further,$allow$for$each$word$in$a$column$to$be$either$left$
justified,$right$justified,$or$center$justified$within$its$column.'''

['Left', 'Center', 'Right'].each { align ->
    println "${align} Justified:"
    alignColumns(align, rawTextInput)
    println()
}

The code reads a text file with multiple lines, where fields within a line are separated by a dollar character. It aligns each column of fields by ensuring at least one space between words in each column. The code also allows for each word in a column to be left justified, right justified, or center justified. The minimum space between columns is computed from the text, not hard-coded. The code handles trailing dollar characters and insignificant consecutive spaces at the end of lines. The output is suitable for viewing in a mono-spaced font on a plain text editor or basic terminal.


def rot13 = { String s ->
    (s as List).collect { ch ->
        switch (ch) {
            case ('a'..'m') + ('A'..'M'):
                return (((ch as char) + 13) as char)
            case ('n'..'z') + ('N'..'Z'):
                return (((ch as char) - 13) as char)
            default:
                return ch
        }
    }.inject ("") { string, ch -> string += ch}
}

println rot13("Noyr jnf V, 'rer V fnj Ryon.")

Able was I, 'ere I saw Elba.

implement a rot-13 encoding function that can be optionally wrapped in a utility program. This function replaces every letter of the ASCII alphabet with the letter which is "rotated" 13 characters "around" the 26 letter alphabet. It should work on both upper and lower case letters, preserve case, and pass all non-alphabetic characters without alteration.


class Holiday {
    def date
    def name
    Holiday(dateStr, name) { this.name = name; this.date = format.parse(dateStr) }
    String toString() { "${format.format date}: ${name}" }
    static format = new java.text.SimpleDateFormat("yyyy-MM-dd")
}

def holidays = [ new Holiday("2009-12-25", "Christmas Day"),
                 new Holiday("2009-04-22", "Earth Day"),
                 new Holiday("2009-09-07", "Labor Day"),
                 new Holiday("2009-07-04", "Independence Day"),
                 new Holiday("2009-10-31", "Halloween"),
                 new Holiday("2009-05-25", "Memorial Day"),
                 new Holiday("2009-03-14", "PI Day"),
                 new Holiday("2009-01-01", "New Year's Day"),
                 new Holiday("2009-12-31", "New Year's Eve"),
                 new Holiday("2009-11-26", "Thanksgiving"),
                 new Holiday("2009-02-14", "St. Valentine's Day"),
                 new Holiday("2009-03-17", "St. Patrick's Day"),
                 new Holiday("2009-01-19", "Martin Luther King Day"),
                 new Holiday("2009-02-16", "President's Day") ]

holidays.sort { x, y -> x.date <=> y.date }
holidays.each { println it }

2009-01-01: New Year's Day
2009-01-19: Martin Luther King Day
2009-02-14: St. Valentine's Day
2009-02-16: President's Day
2009-03-14: PI Day
2009-03-17: St. Patrick's Day
2009-04-22: Earth Day
2009-05-25: Memorial Day
2009-07-04: Independence Day
2009-09-07: Labor Day
2009-10-31: Halloween
2009-11-26: Thanksgiving
2009-12-25: Christmas Day
2009-12-31: New Year's Eve

sort an array of composite structures, specifically name-value pairs, by the key 'name' using a custom comparator.


for(i in (1..6)) {
    for(j in (1..i)) {
        print '*'
    }
    println ()
}

demonstrate how to nest two "for" loops, where the number of iterations of the inner loop is controlled by the outer loop. The code prints a pattern of asterisks, with each line containing one more asterisk than the previous line.


map = [:]
map[7] = 7
map['foo'] = 'foovalue'
map.put('bar', 'barvalue')
map.moo = 'moovalue'

assert 7 == map[7]
assert 'foovalue' == map.foo
assert 'barvalue' == map['bar']
assert 'moovalue' == map.get('moo')

map = [7:7, foo:'foovalue', bar:'barvalue', moo:'moovalue']

assert 7 == map[7]
assert 'foovalue' == map.foo
assert 'barvalue' == map['bar']
assert 'moovalue' == map.get('moo')

Create and populate an associative array, verify its values, and add new values to an empty map.


class NodeList {
    private enum Flag { FRONT }
    private ListNode head
    void insert(value, insertionPoint=Flag.FRONT) {
        if (insertionPoint == Flag.FRONT) {
            head = new ListNode(payload: value, next: head)
        } else {
            def node = head
            while (node.payload != insertionPoint) {
                node = node.next
                if (node == null) {
                    throw new IllegalArgumentException(
                        "Insertion point ${afterValue} not already contained in list")
                }
            }
            node.next = new ListNode(payload:value, next:node.next)
        }
    }
    String toString() { "${head}" }
}

def list = new NodeList()
list.insert('B')
list.insert('A')
println list

list.insert('C', 'A')
println list

A -> B -> null
A -> C -> B -> null

define a method to insert an element into a singly-linked list after a specified element. The method is then used to insert element C into a list containing elements A and B, following element A.


def rFact
rFact = { (it > 1) ? it * rFact(it - 1) : 1 as BigInteger }
def iFact = { (it > 1) ? (2..it).inject(1 as BigInteger) { i, j -> i*j } : 1 }

def time = { Closure c ->
    def start = System.currentTimeMillis()
    def result = c()
    def elapsedMS = (System.currentTimeMillis() - start)/1000
    printf '(%6.4fs elapsed)', elapsedMS
    result
}

def dashes = '---------------------'
print "   n!       elapsed time   "; (0..15).each { def length = Math.max(it - 3, 3); printf " %${length}d", it }; println()
print "--------- -----------------"; (0..15).each { def length = Math.max(it - 3, 3); print " ${dashes[0..<length]}" }; println()
[recursive:rFact, iterative:iFact].each { name, fact ->
    printf "%9s ", name
    def factList = time { (0..15).collect {fact(it)} }
    factList.each { printf ' %3d', it }
    println()
}

The code calculates the factorial of a given number either iteratively or recursively. It optionally handles errors for negative input values. A recursive closure is pre-declared for this purpose. The code is also related to the task of generating primorial numbers.


class BullsAndCows {
    static void main(args) {
        def inputReader = System.in.newReader()
        def numberGenerator = new Random()
        def targetValue
        while (targetValueIsInvalid(targetValue = numberGenerator.nextInt(9000) + 1000)) continue
        def targetStr = targetValue.toString()
        def guessed = false
        def guesses = 0
        while (!guessed) {
            def bulls = 0, cows = 0
            print 'Guess a 4-digit number with no duplicate digits: '
            def guess = inputReader.readLine()
            if (guess.length() != 4 || !guess.isInteger() || targetValueIsInvalid(guess.toInteger())) {
                continue
            }
            guesses++
            4.times {
                if (targetStr[it] == guess[it]) {
                    bulls++
                } else if (targetStr.contains(guess[it])) {
                    cows++
                }
            }
            if (bulls == 4) {
                guessed = true
            } else {
                println "$cows Cows and $bulls Bulls."
            }
        }
        println "You won after $guesses guesses!"
    }

    static targetValueIsInvalid(value) {
        def digitList = []
        while (value > 0) {
            if (digitList[value % 10] == 0 || digitList[value % 10]) {
                return true
            }
            digitList[value % 10] = true
            value = value.intdiv(10)
        }
        false
    }
}

generate a unique four-digit number, accept and validate user guesses, calculate and print scores based on matching digits and their positions, and end the program when the user guess matches the generated number.


rnd = new Random()
result = (1..1000).inject([]) { r, i -> r << rnd.nextGaussian() }

generate a collection of 1000 normally distributed pseudo-random numbers with a mean of 1.0 and a standard deviation of 0.5.


def dotProduct = { x, y ->
    assert x && y && x.size() == y.size()
    [x, y].transpose().collect{ xx, yy -> xx * yy }.sum()
}

println dotProduct([1, 3, -5], [4, -2, -1])

implement a function that calculates the dot product of two vectors of arbitrary length. The vectors must be of the same length, and the function works by multiplying corresponding terms from each vector and summing the products.


def lineMap = [:]
System.in.eachLine { line, i ->
    lineMap[i] = line
}
lineMap.each { println it }

Test:
$ groovy -e 'def lineMap = [:]
> System.in.eachLine { line, i ->
>     lineMap[i] = line
> }
> lineMap.each { println it }' <<EOF
>
> Whose woods these are I think I know
> His house is in the village tho'
> He will not see me stopping here
> To watch his woods fill up with snow
> EOF

continuously read data from a text stream either word-by-word or line-by-line until there is no more data available in the stream.


import groovy.xml.MarkupBuilder
def writer = new StringWriter() << '<?xml version="1.0" ?>\n'
def xml = new MarkupBuilder(writer)
xml.root() {
    element('Some text here' )
}
println writer

Create a simple DOM and serialize it into the specified XML format.


Solution (based on Java solution).def nowMillis = new Date().time
println 'Milliseconds since the start of the UNIX Epoch (Jan 1, 1970) == ' + nowMillis

the system time in a specified unit. This can be used for debugging, network information, random number seeds, or program performance. The time is retrieved either by a system command or a built-in language function. It is related to the task of date formatting and retrieving system time.


def checksum(text) {
    assert text.size() == 6 && !text.toUpperCase().find(/[AEIOU]+/) : "Invalid SEDOL text: $text"

    def sum = 0
    (0..5).each { index ->
        sum +=  Character.digit(text.charAt(index), 36) * [1, 3, 1, 7, 3, 9][index]
    }
    text + (10 - (sum % 10)) % 10
}
String.metaClass.sedol = { this.&checksum(delegate) }

[ '710889': '7108899', 'B0YBKJ': 'B0YBKJ7', '406566': '4065663', 'B0YBLH': 'B0YBLH2',
  '228276': '2282765', 'B0YBKL': 'B0YBKL9', '557910': '5579107', 'B0YBKR': 'B0YBKR5',
  '585284': '5852842', 'B0YBKT': 'B0YBKT7', 'B00030': 'B000300'].each { text, expected ->
    println "Checking $text -> $expected"
    assert expected == text.sedol()
}

Checking 710889 -> 7108899
Checking B0YBKJ -> B0YBKJ7
Checking 406566 -> 4065663
Checking B0YBLH -> B0YBLH2
Checking 228276 -> 2282765
Checking B0YBKL -> B0YBKL9
Checking 557910 -> 5579107
Checking B0YBKR -> B0YBKR5
Checking 585284 -> 5852842
Checking B0YBKT -> B0YBKT7
Checking B00030 -> B000300

The code takes a list of 6-digit SEDOLs as input, calculates the checksum digit for each SEDOL, and appends it to the respective SEDOL. It also validates the input to ensure it consists of valid characters allowed in a SEDOL string.


def stripChars = { string, stripChars ->
    def list = string as List
    list.removeAll(stripChars as List)
    list.join()
}

println (stripChars('She was a soul stripper. She took my heart!', 'aei'))

"Function to remove specified characters from a given string."


def log = ''
(1..40).each {Integer value -> log +=(value %3 == 0) ? (value %5 == 0)? 'FIZZBUZZ\n':(value %7 == 0)? 'FIZZBAXX\n':'FIZZ\n'
                                    :(value %5 == 0) ? (value %7 == 0)? 'BUZBAXX\n':'BUZZ\n'
                                    :(value %7 == 0) ?'BAXX\n'
                                    :(value+'\n')}
println log

1
2
FIZZ
4
BUZZ
FIZZ
BAXX
8
FIZZ
BUZZ
11
FIZZ
13
BAXX
FIZZBUZZ
16
17
FIZZ
19
BUZZ
FIZZBAXX
22
23
FIZZ
BUZZ
26
FIZZ
BAXX
29
FIZZBUZZ
31
32
FIZZ
34
BUZBAXX
FIZZ
37
38
FIZZ
BUZZ

def fizzBuzz = { i -> [[3,'Fizz'],[5,'Buzz'],[7,'Baxx']].collect{i%it[0]?'':it[1]}.join()?:i}
1.upto(100){println fizzBuzz(it)}

generates a custom FizzBuzz sequence based on user-defined parameters. The user inputs a maximum number and three pairs of factors and corresponding words. The program then prints numbers from 1 to the maximum number, replacing multiples of the factors with the associated words. In cases where a number is a multiple of multiple factors, all corresponding words are printed in the order of the factors.


def random = new Random()
def keyboard = new Scanner(System.in)
def number = random.nextInt(10) + 1
println "Guess the number which is between 1 and 10: "
def guess = keyboard.nextInt()
while (number != guess) {
    println "Guess again: "
    guess = keyboard.nextInt()
}
println "Hurray! You guessed correctly!"

"Implement a number guessing game where the computer selects a number between 1 and 10. The player is repeatedly prompted to guess the number until the correct number is guessed, upon which a 'Well guessed!' message is displayed and the program terminates. A conditional loop is used to facilitate repeated guessing."


def lower = ('a'..'z')

assert 'abcdefghijklmnopqrstuvwxyz' == lower.join('')

generate a sequence of all lower case ASCII characters from 'a' to 'z' using a reliable coding style and strong typing if available. The code avoids manually enumerating all the lowercase characters to prevent bugs. It also demonstrates how to access such a sequence if it exists in the standard library.


"Generate and display the binary representation of a given non-negative integer without leading zeros, whitespace, radix or sign markers. The output for each number is followed by a newline."


def config = [:]
def loadConfig = { File file ->
    String regex = /^(;{0,1})\s*(\S+)\s*(.*)$/
    file.eachLine { line ->
        (line =~ regex).each { matcher, invert, key, value ->
            if (key == '' || key.startsWith("#")) return
            parts = value ? value.split(/\s*,\s*/) : (invert ? [false] : [true])
            if (parts.size() > 1) {
                parts.eachWithIndex{ part, int i -> config["$key(${i + 1})"] = part}
            } else {
                config[key] = parts[0]
            }
        }
    }
}

loadConfig new File('config.ini')
config.each { println it }

The code reads a standard configuration file, ignores lines starting with a hash or semicolon, and blank lines. It sets variables based on the configuration parameters, preserving case sensitivity for parameter data. It also handles optional equals signs, and multiple parameters separated by commas. The variables set include fullname, favouritefruit, needspeeling, seedsremoved, and otherfamily which is stored in an array. The boolean variables are set to true if present and false if commented out.


def haversine(lat1, lon1, lat2, lon2) {
  def R = 6372.8
  // In kilometers
  def dLat = Math.toRadians(lat2 - lat1)
  def dLon = Math.toRadians(lon2 - lon1)
  lat1 = Math.toRadians(lat1)
  lat2 = Math.toRadians(lat2)

  def a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2)
  def c = 2 * Math.asin(Math.sqrt(a))
  R * c
}

haversine(36.12, -86.67, 33.94, -118.40)

> 2887.25995060711

Implement a function to calculate the great-circle distance between two points on a sphere using the Haversine formula. The function takes the coordinates of Nashville International Airport (BNA) and Los Angeles International Airport (LAX) as input and returns the distance between them. The calculation uses the recommended earth radius of 6372.8 km or 6371 km, depending on the level of precision required.


new URL("http://www.rosettacode.org").eachLine { println it }

Print the content of a specified URL to the console using HTTP request.


def checkLuhn(number) {
    int total
    (number as String).reverse().eachWithIndex { ch, index ->
        def digit = Integer.parseInt(ch)
        total += (index % 2 ==0) ? digit : [0, 2, 4, 6, 8, 1, 3, 5, 7, 9][digit]
    }
    total % 10 == 0
}

def verifyLuhn(number, expected) {
    println "Checking: $number (${checkLuhn(number)})"
    assert expected == checkLuhn(number)
}

[49927398716: true, 49927398717: false, 1234567812345678: false, 1234567812345670: true].each { number, expected ->
    verifyLuhn number, expected
}

The code implements the Luhn test for validating credit card numbers. It first reverses the order of the digits in the number. Then, it calculates the sum of every other odd digit (s1) and the sum of the doubled even digits (s2). If the sum of s1 and s2 ends in zero, the number is a valid credit card number. The code validates the numbers 49927398716, 49927398717, 1234567812345678, and 1234567812345670 using this method.


int[] Josephus (int size, int kill, int survivors) {
    // init user pool
    def users = new int[size];

    // give initial values such that [0] = 1 (first person) [1] = 2 (second person) etc
    users.eachWithIndex() {obj, i -> users[i] = i + 1};

    // keep track of which person we are on (ranging from 1 to kill)
    def person = 1;

    // keep going until we have the desired number of survivors
    while (users.size() > survivors)
    {
        // for each person, if they are the kill'th person, set them to -1 to show eliminated
        users.eachWithIndex() {obj, i ->
            if (person++ % kill == 0) {
                users[i] = -1;
            }

            // if person overflowed kill then reset back to 1
            if (person > kill) {person = 1;}
        }

        // clear out all eliminated persons
        users = users.findAll{w -> w >= 0};
    }

    // resulting set is the safe positions
    return users;
}

// Run some test cases

println "Final survivor for n = 10201 and k = 17: " + Josephus(10201,17,1)[0];

println "4 safe spots for n = 10201 and k = 17: " + Josephus(10201,17,4);

- Determine the final survivor in the Josephus problem given any number of prisoners (n) and a step count (k).
- Calculate the position of any prisoner in the killing sequence.
- Provide an option to save a certain number of prisoners (m).
- The numbering of prisoners can start from either 0 or 1.
- The complexity of the solution is O(kn) for the complete killing sequence and O(m) for finding the m-th prisoner to die.


The code takes a string or a character as input and repeats it a specified number of times. For example, if the input is "ha" and 5, the output will be "hahahahaha". Similarly, if the input is "*" and 5, the output will be "*****".


import java.util.regex.*;

def woodchuck = "How much wood would a woodchuck chuck if a woodchuck could chuck wood?"
def pepper = "Peter Piper picked a peck of pickled peppers"

println "=== Regular-expression String syntax (/string/) ==="
def woodRE = /[Ww]o\w+d/
def piperRE = /[Pp]\w+r/
assert woodRE instanceof String && piperRE instanceof String
assert (/[Ww]o\w+d/ == "[Ww]o\\w+d") && (/[Pp]\w+r/ == "[Pp]\\w+r")
println ([woodRE: woodRE, piperRE: piperRE])
println ()

println "=== Pattern (~) operator ==="
def woodPat = ~/[Ww]o\w+d/
def piperPat = ~piperRE
assert woodPat instanceof Pattern && piperPat instanceof Pattern

def woodList = woodchuck.split().grep(woodPat)
println ([exactTokenMatches: woodList])
println ([exactTokenMatches: pepper.split().grep(piperPat)])
println ()

println "=== Matcher (=~) operator ==="
def wwMatcher = (woodchuck =~ woodRE)
def ppMatcher = (pepper =~ /[Pp]\w+r/)
def wpMatcher = (woodchuck =~ /[Pp]\w+r/)
assert wwMatcher instanceof Matcher && ppMatcher instanceof Matcher
assert wwMatcher.toString() == woodPat.matcher(woodchuck).toString()
assert ppMatcher.toString() == piperPat.matcher(pepper).toString()
assert wpMatcher.toString() == piperPat.matcher(woodchuck).toString()

println ([ substringMatches: wwMatcher.collect { it }])
println ([ substringMatches: ppMatcher.collect { it }])
println ([ substringMatches: wpMatcher.collect { it }])
println ()

println "=== Exact Match (==~) operator ==="
def containsWoodRE = /.*/ + woodRE + /.*/
def containsPiperRE = /.*/ + piperRE + /.*/
def wwMatches = (woodchuck ==~ containsWoodRE)
assert wwMatches instanceof Boolean
def wwNotMatches = ! (woodchuck ==~ woodRE)
def ppMatches = (pepper ==~ containsPiperRE)
def pwNotMatches = ! (pepper ==~ containsWoodRE)
def wpNotMatches = ! (woodchuck ==~ containsPiperRE)
assert wwMatches && wwNotMatches && ppMatches && pwNotMatches && pwNotMatches

println ("'${woodchuck}' ${wwNotMatches ? 'does not' : 'does'} match '${woodRE}' exactly")
println ("'${woodchuck}' ${wwMatches ? 'does' : 'does not'} match '${containsWoodRE}' exactly")

1. Matches a string with a specified regular expression.
2. Replaces a certain part of a string using a specified regular expression.
3. Provides a reusable solution for replacing parts of a string using a regular expression.


def arithmetic = { a, b ->
    println """
       a + b =        ${a} + ${b} = ${a + b}
       a - b =        ${a} - ${b} = ${a - b}
       a * b =        ${a} * ${b} = ${a * b}
       a / b =        ${a} / ${b} = ${a / b}   !!! Converts to floating point!
(int)(a / b) = (int)(${a} / ${b}) = ${(int)(a / b)}              !!! Truncates downward after the fact
 a.intdiv(b) =  ${a}.intdiv(${b}) = ${a.intdiv(b)}              !!! Behaves as if truncating downward, actual implementation varies
       a % b =        ${a} % ${b} = ${a % b}

Exponentiation is also a base arithmetic operation in Groovy, so:
      a ** b =       ${a} ** ${b} = ${a ** b}
"""
}

arithmetic(5,3)

take two integers as input from the user and calculate their sum, difference, product, integer quotient, remainder and exponentiation. The code does not include error handling. It also indicates the rounding method for the quotient and the sign of the remainder. Additionally, it includes an example of the integer 'divmod' operator.


println (('the three truths' =~ /th/).count)
println (('ababababab' =~ /abab/).count)
println (('abaabba*bbaba*bbab' =~ /a*b/).count)
println (('abaabba*bbaba*bbab' =~ /a\*b/).count)

The code defines a function to count the number of non-overlapping occurrences of a specific substring within a given string. The function takes two arguments, the main string and the substring to search for. It returns an integer representing the count of non-overlapping matches. The function does not count overlapping substrings and matches from either left-to-right or right-to-left for the highest number of matches. The solution utilizes Groovy's "find" operator and "count" property.


def tail = { list, n ->  def m = list.size(); list.subList([m - n, 0].max(),m) }

final STACK = [A:[],B:[],C:[]].asImmutable()

def report = { it -> }
def check = { it -> }

def moveRing = { from, to ->  to << from.pop(); report(); check(to) }

def moveStack
moveStack = { from, to, using = STACK.values().find { !(it.is(from) || it.is(to)) } ->
    if (!from) return
    def n = from.size()
    moveStack(tail(from, n-1), using, to)
    moveRing(from, to)
    moveStack(tail(using, n-1), to, from)
}

enum Ring {
    S('°'), M('o'), L('O'), XL('( )');
    private sym
    private Ring(sym) { this.sym=sym }
    String toString() { sym }
}

report = { STACK.each { k, v ->  println "${k}: ${v}" }; println() }
check = { to -> assert to == ([] + to).sort().reverse() }

Ring.values().reverseEach { STACK.A << it }
report()
check(STACK.A)
moveStack(STACK.A, STACK.C)

"Implement a recursive solution for the Towers of Hanoi problem, manipulating actual stacks of rings."


def factorial = { x ->
    assert x > -1
    x == 0 ? 1 : (1..x).inject(1G) { BigInteger product, BigInteger factor -> product *= factor }
}

def combinations = { n, k ->
    assert k >= 0
    assert n >= k
    factorial(n).intdiv(factorial(k)*factorial(n-k))
}

assert combinations(20, 0) == combinations(20, 20)
assert combinations(20, 10) == (combinations(19, 9) + combinations(19, 10))
assert combinations(5, 3) == 10
println combinations(5, 3)

"Calculate any binomial coefficient using the given formula, with specific capability to output the binomial coefficient of 5 and 3. The code also handles tasks related to combinations and permutations, both with and without replacement."


def i = 0
do {
    i++
    println i
} while (i % 6 != 0)

def i = 0
while (true) {
    i++
    println i
    if (i % 6 == 0) break
}

Initializes a value at 0 and increments it by 1 in each iteration of a loop. The loop continues as long as the incremented value modulo 6 is not equal to 0. The value is printed in each iteration. The loop is guaranteed to run at least once. This is implemented in Groovy 3.0.0 and later versions. In previous versions, an infinite while loop with a conditional break at the end is used as a workaround due to the absence of a bottom-checking loop construct.


println "Hello World!".size()
println "møøse".size()
println "𝔘𝔫𝔦𝔠𝔬𝔡𝔢".size()
println "J̲o̲s̲é̲".size()

12
5
14
8

calculates the character and byte length of a string, considering the UTF-8 and UTF-16 encodings. It accurately counts the Unicode code points, not user-visible graphemes or code unit counts. The code also handles non-BMP code points correctly. It provides the string length in graphemes if the language supports it. However, it does not calculate the in-memory storage size in bytes. The code uses the Java "String.length()" method or "size()" for Groovy extensions to java.lang.String for calculating the character length.


def rng = new java.security.SecureRandom()

(0..4).each { println rng.nextInt() }

"Generate a 32-bit random number using the system's built-in random number generator, not just a software algorithm like /dev/urandom devices in Unix."


def top  = { it.size() > 1 ? it[0..-2] : '' }
def tail = { it.size() > 1 ? it[1..-1] : '' }

def testVal = 'upraisers'
println """
original: ${testVal}
top:      ${top(testVal)}
tail:     ${tail(testVal)}
top&tail: ${tail(top(testVal))}
"""

original: upraisers
top:      upraiser
tail:     praisers
top&tail: praiser

demonstrate the removal of the first character, the last character, and both the first and last characters from a string. The codes also ensure compatibility with any valid Unicode code point in UTF-8 or UTF-16, referencing logical characters rather than 8-bit or 16-bit code units. Handling all Unicode characters for other encodings is not required.


def window = java.awt.GraphicsEnvironment.localGraphicsEnvironment.maximumWindowBounds

println "width: $window.width, height: $window.height"

calculate the maximum height and width of a window that can fit within the physical display area of the screen, considering window decorations, menubars, multiple monitors, and tiling window managers.