Thursday, May 29, 2014

Simple Linked List

class Node implements Cloneable {
    private int val
    private int i
    private Node prev
    private Node next
    
    private static Node head
    private static Node last
    
    Node(int val, int i = 0) {
        if (!head) head = this
        if (!last) last = this
        
        this.i = i
        this.val = val
    }
    
    Integer at(int x, Node node = this) {
        //println "" + x + node.i + node.next
        
        if (x > node.i) {
            if (node.next != null) 
                return this.at(x, node.next)
            else 
                return null
        }

        return node.val
    }
    
    Node add(int val) {
        Node newNode = new Node(val, last.i + 1)
        
        newNode.prev = last
        last.next = newNode
        
        last = newNode
        
        //println "---\nadd done\n---"
        
        return head
    }
    
    Node reverse() {
        Node r = last.clone()
        Node prev = last.prev
        
        while (prev != null) {
            r.add(prev.val)
            prev = prev.prev    
        }
        
        return r
    }
}



Node list = new Node(1)

assert list.at(0) == 1

list.add(4).add(6) // chained adding

assert list.at(0) == 1

assert list.at(1) == 4

assert list.at(2) == 6

assert list.at(3) == null

assert list.reverse().at(0) == list.at(2)

Persistent (Immutable) Collections

@Grapes(
    @Grab(group='org.pcollections', module='pcollections', version='2.1.2')
)
import org.pcollections.*

PSet set = HashTreePSet.empty()
set = set + "something"
println set
println(set + "something else")
println set // immutable

Wednesday, May 28, 2014

GPars Actors

import static groovyx.gpars.actor.Actors.actor

/**
 * A demo showing two cooperating actors. The decryptor decrypts received messages and replies them back.
 * The console actor sends a message to decrypt, prints out the reply and terminates both actors.
 * The main thread waits on both actors to finish using the join() method to prevent premature exit,
 * since both actors use the default actor group, which uses a daemon thread pool.
 * 
 * code derrived from: http://gpars.codehaus.org/Actor
 */

def decryptor = actor {
    loop {
        react {message ->
            Thread.sleep(1000);
            
            if (!(message instanceof String)) {
                stop()
                return
            }
            
            reply message.reverse()
        }
    }
}

def console = actor {
    List strs = ['abc','zyx','Vvv',false];
    int i = -1
    
    loop {
        if (!strs[++i]) stop()
        
        decryptor << strs[i]
        
        println "Sent: ${strs[i]}"
        
        react {msg ->
           println "Decrypted msg: $msg"
        }
    }
}

[decryptor, console]*.join()

Wednesday, April 16, 2014

Spock - BDD

@Grapes([
  @Grab(group='org.spockframework', module='spock-core', version='0.7-groovy-2.0')
])
import spock.lang.*

// see: http://meetspock.appspot.com/
// https://github.com/spockframework/spock

class MyFirstSpec extends Specification {
  def "test min"() {
    given: "min of a&b"

    expect:
    Math.min(a, b) == c

    where:
    a << [1,2]
    b << [4,3]
    c << [1,2]
  }
  
  def "test string length"() {
    given: "length of name"

    expect:
    name.size() == length

    where:
    name << ["Sally","Bill"]
    length << [5,4]
  }
}

Thursday, January 16, 2014

dotPath

int item = Math.random() * 100000

def doCode = { return 'hi' }
Map $_ = [a: 1, b: ['c d': [z: item, doit: doCode]]]

use (UtilCategory) {

    assert $_.dotPath() == [a: 1, b: ['c d': [z: item, doit: doCode]]]
    assert $_.dotPath('') == [a: 1, b: ['c d': [z: item, doit: doCode]]]
    assert $_.dotPath(null) == [a: 1, b: ['c d': [z: item, doit: doCode]]]
    
    assert $_.dotPath('a') == 1
    assert $_.dotPath('b.c d.z') == item
    assert $_.dotPath('b/c d/z', '/') == item
    
    assert $_.dotPath('b.c d.doit')() == 'hi'
    
    assert $_.dotPath('b.c d.y') == null
    assert $_.dotPath('b.c d.z.z') == null
    assert $_.dotPath('b.c d.z.z.') == null
    assert 1.dotPath('toString') == null

}

//========================================

@Category(Object)
class UtilCategory {
    def dotPath(String path = '', String delimiter = /\./) {
        Object self = this
        
        if (!path) return self
    
        try {
            return path.split(/$delimiter/).inject(self) { x, i->
               x = x[i]
            }
        }
        catch (Exception ex) { return null }
    }
}

Wednesday, January 15, 2014

collectEntries - List to Map

List a = (1..50).toList()

Closure remainder = { return (it % 8) }

Map b = a.collectEntries{ i-> [(i.toString()) : remainder(i)]}

assert b['5'] == 5
assert b['7'] == 7
assert b['8'] == 0
assert b['17'] == 1
String last = b.keySet()[-1]
assert b[last] == 2 // [50:2]



a = ('a'..'z').toList()

Closure mult = { return (it * 8) }

b = a.collectEntries{ i-> [(i.toString()) : mult(i)]}

assert b['a'] == 'a'*8
last = b.keySet()[-1]
assert b[last] == 'z'*8 // [z:zzzzzzzz]

csv-2-List for groovycsv

@Grab('com.xlson.groovycsv:groovycsv:1.0')
import com.xlson.groovycsv.CsvParser
 
// a normally parsed csv can only be searched through ONCE
// this is used to create a "re-searchable" object (List of Maps)
List csv2List( String filePath, boolean shouldTrim = true ) {
    new File( filePath ).withReader { r ->
        new CsvParser().parse( r ).with { csv ->
            return csv.collect { line ->
                line.columns.collectEntries { c, v ->
                    [ c, (shouldTrim ? line[ c ].trim() : line[ c ]) ]
                }
            }
        }
    }
}