Next round of 4clojure.com solutions

After the third round, five more 4clojure.com solutions:

```(ns com.icyrock.clojure.a4clojure_com.core
(:use clojure.test))

;;; Problem 40 - Interpose a Seq
(deftest test-problem-40
(let [v1 #(rest (interleave (repeat %) %2))
__ v1]
(is (= (__ 0 [1 2 3]) [1 0 2 0 3]))
(is (= (apply str (__ ", " ["one" "two" "three"])) "one, two, three"))
(is (= (__ :z [:a :b :c :d]) [:a :z :b :z :c :z :d]))))

;;; Problem 39 - Interleave Two Seqs
(deftest test-problem-39
(let [v1 #(mapcat list % %2)
__ v1]
(is (= (__ [1 2 3] [:a :b :c]) '(1 :a 2 :b 3 :c)))
(is (= (__ [1 2] [3 4 5 6]) '(1 3 2 4)))
(is (= (__ [1 2 3 4] [5]) [1 5]))
(is (= (__ [30 20] [25 15]) [30 25 20 15]))))

;;; Problem 38 - Maximum value
(deftest test-problem-38
(let [v1 #(first (sort > %&))
__ v1]
(is (= (__ 1 8 3 4) 8))
(is (= (__ 30 20) 30))
(is (= (__ 45 67 11) 67))))

;;; Problem 37 - Regular Expressions
(deftest test-problem-37
(let [v1 "ABC"
__ v1]
(is (= __ (apply str (re-seq #"[A-Z]+" "bA1B3Ce "))))))

;;; Problem 36 - Let it Be
(deftest test-problem-36
(do
(is (= 10 (let [x 7 y 3 z 1] (+ x y))))
(is (= 4 (let [x 7 y 3 z 1] (+ y z))))
(is (= 1 (let [x 7 y 3 z 1] z)))))

(run-tests)
```
Be Sociable, Share!

One Response to “Next round of 4clojure.com solutions”

Next round of 4clojure.com solutions « Blog Archive « icyrock.com on August 18th, 2014 21:42:

[…] the fourth round, five more 4clojure.com […]

(required)

(required)

Next round of 4clojure.com solutions

After the second round, five more 4clojure.com solutions:

```(ns com.icyrock.clojure.a4clojure_com.core
(:use clojure.test))

;;; Problem 35 - Local bindings
(deftest test-problem-35
(let [v1 7
__ v1]
(is (= __ (let [x 5] (+ 2 x))))
(is (= __ (let [x 3, y 10] (- y x))))
(is (= __ (let [x 21] (let [y 3] (/ x y)))))))

;;; Problem 34 - Implement range
(deftest test-problem-34
(let [v1 #(take (- %2 %) (iterate inc %))
__ v1]
(is (= (__ 1 4) '(1 2 3)))
(is (= (__ -2 2) '(-2 -1 0 1)))
(is (= (__ 5 8) '(5 6 7)))))

;;; Problem 33 - Replicate a Sequence
(deftest test-problem-33
(let [v1 #(mapcat (fn [e] (repeat %2 e)) %)
v2 #(apply interleave (repeat %2 %))
__ v2]
(is (= (__ [1 2 3] 2) '(1 1 2 2 3 3)))
(is (= (__ [:a :b] 4) '(:a :a :a :a :b :b :b :b)))
(is (= (__ [4 5 6] 1) '(4 5 6)))
(is (= (__ [[1 2] [3 4]] 2) '([1 2] [1 2] [3 4] [3 4])))
(is (= (__ [44 33] 2) [44 44 33 33]))))

;;; Problem 32 - Duplicate a Sequence
(deftest test-problem-32
(let [v1 #(mapcat (fn [x] [x x]) %)
v2 #(mapcat list % %)
v3 #(interleave % %)
__ v3]
(is (= (__ [1 2 3]) '(1 1 2 2 3 3)))
(is (= (__ [:a :a :b :b]) '(:a :a :a :a :b :b :b :b)))
(is (= (__ [[1 2] [3 4]]) '([1 2] [1 2] [3 4] [3 4])))
(is (= (__ [[1 2] [3 4]]) '([1 2] [1 2] [3 4] [3 4])))))

;;; Problem 31 - Pack a Sequence
(deftest test-problem-31
(let [v1 #(partition-by identity %)
__ v1]
(is (= (__ [1 1 2 1 1 1 3 3]) '((1 1) (2) (1 1 1) (3 3))))
(is (= (__ [:a :a :b :b :c]) '((:a :a) (:b :b) (:c))))
(is (= (__ [[1 2] [1 2] [3 4]]) '(([1 2] [1 2]) ([3 4]))))))

(run-tests)
```
Be Sociable, Share!

One Response to “Next round of 4clojure.com solutions”

Next round of 4clojure.com solutions « Blog Archive « icyrock.com on June 3rd, 2014 06:54:

[…] the third round, five more 4clojure.com […]

(required)

(required)

three.js clock

Following the three.js charts post, here’s the clock using three.js:

```class ThreeJsClock
initCSR: ->
width = 800
height = 600
viewAngle = 45
aspect = width / height
near = 1
far = 1000

@camera = new THREE.PerspectiveCamera viewAngle, aspect, near, far
@camera.position.z = 500

@scene = new THREE.Scene

@renderer = new THREE.WebGLRenderer
antialias: true
premultipliedAlpha: false
alpha: true
@renderer.setSize width, height

canvas = \$(@renderer.domElement)
.attr('id', 'canvas')

\$('<div>')
.append(canvas)
.appendTo(document.body)

draw: =>
@render()
setTimeout(() =>
requestAnimationFrame @draw
, 1000 / @fps)

setHands: =>
time = new Date()

@handsSep.second.rotation.z = -time.getSeconds() / 60 * 2 * Math.PI
@handsSep.minute.rotation.z = -time.getMinutes() / 60 * 2 * Math.PI
@handsSep.hour.rotation.z = -time.getHours() / 12 * 2 * Math.PI

render: =>
if Math.abs(@group.rotation.y) > Math.PI / 2
@rot *= -1
@group.rotation.y += @rot

@setHands()
@renderer.render @scene, @camera

makeScene: ->
@group = new THREE.Object3D

@clock = new THREE.Object3D

backGeom = new THREE.CylinderGeometry(
height = 10,
heightSegments = 70,
openEnded = false,
)

backMat = new THREE.MeshLambertMaterial
color: 0x80b2ff

backMesh = new THREE.Mesh backGeom, backMat
backMesh.rotation.x = Math.PI / 2

@ticks = new THREE.Object3D

tickGeom = new THREE.SphereGeometry(
widthSegments = 70,
heightSegments = 70)

tickMat = new THREE.MeshLambertMaterial
color: 0xcfcf53

for x in [0..12]
tickMesh = new THREE.Mesh tickGeom, tickMat
tickMesh.position.y = 180

dummy = new THREE.Object3D
dummy.rotation.z = x * Math.PI / 6

@hands = new THREE.Object3D

handCentGeom = new THREE.SphereGeometry(
widthSegments = 70,
heightSegments = 70)

handCentMat = new THREE.MeshLambertMaterial
color: 0xffc0c0

handCentMesh = new THREE.Mesh handCentGeom, handCentMat

makeHand = (hands, len, rad, z) ->
handGeom = new THREE.CylinderGeometry(
height = len,
heightSegments = 70,
openEnded = false,
)
handMat = new THREE.MeshLambertMaterial
color: 0xffc0c0

handMesh = new THREE.Mesh handGeom, handMat
handMesh.position.y = len / 2
handMesh.position.z = z

dummy = new THREE.Object3D

dummy

@handsSep =
second: makeHand @hands, 170, 3, 20
minute: makeHand @hands, 150, 4, 15
hour: makeHand @hands, 130, 5, 10

@rot = 0.01

directionalLight = new THREE.SpotLight 0xffffff
directionalLight.position.set 0, 0, 3000

run: ->
@initCSR()
@makeScene()

@fps = 15
@draw()

module.exports = ThreeJsClock
```

Here’s a screenshot:

Be Sociable, Share!

(required)

(required)

Java SynchronizedRandomAccessList vs CopyOnWriteArrayList

Here’s a microbenchmark of SynchronizedRandomAccessList and CopyOnWriteArrayList. I wanted to see how well one or another performed with little number of changed, where CopyOnWriteArrayList could potentially be better.

```package com.icyrock.java.collection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;

public class SpeedPrb {
private static interface ListCreator<I> {
List<Integer> create(List<Integer> seed);
}

public static void main(String[] args) {
new SpeedPrb().run();
}

private void run() {
try {
runUnsafe();
} catch (Exception e) {
e.printStackTrace();
}
}

private void runUnsafe() throws InterruptedException {
for (String runType : new String[] { "warm-up", "test" }) {
System.out.println("Run type: " + runType);

withList(new ListCreator<List<Integer>>() {
public List<Integer> create(List<Integer> seed) {
return Collections.synchronizedList(new ArrayList<Integer>(seed));
}
});

withList(new ListCreator<List<Integer>>() {
public List<Integer> create(List<Integer> seed) {
return new CopyOnWriteArrayList<Integer>(seed);
}
});
}
}

private void withList(ListCreator<List<Integer>> listCreator) throws InterruptedException {
}

throws InterruptedException {
}

private void withDataSize(ListCreator<List<Integer>> listCreator, int threadCount, int dataSize)
throws InterruptedException {
}

private void withDataModSize(final ListCreator<List<Integer>> listCreator,
final int threadCount, final int dataSize, final int dataModSize) throws InterruptedException {
List<Integer> seed = new ArrayList<>();
for (int i = 0; i < dataSize; i++) {
}

List<Integer> list = listCreator.create(seed);

long start = System.nanoTime();

long sum = doSum(list, threadCount, dataSize);

long end = System.nanoTime();
double elapsed = (end - start) / 1e6;

System.out.println("End"
+ ": list.class: " + list.getClass().getSimpleName()
+ ", dataSize: " + dataSize
+ ", dataModSize: " + dataModSize
+ ", elapsed: " + elapsed
+ ", sum: " + sum);
}

private void doMods(final List<Integer> list, final int threadCount, final int dataSize,
final int dataModSize) throws InterruptedException {
final int count = dataSize / threadCount;
for (int i = 0; i < threadCount; i++) {
final int modId = i * count;

public void run() {
int modCnt = 0;
for (int i = 0; i < count; i++) {
if (modCnt < dataModSize) {
int pos = list.get(modId + i);
list.set(pos, list.get(pos) + 1);
modCnt++;
}
if (modCnt == dataModSize) {
break;
}
}
}
});

}

for (int i = 0; i < threadCount; i++) {
}

for (int i = 0; i < threadCount; i++) {
}
}
}
}

private long doSum(final List<Integer> list, final int threadCount, final int dataSize)
throws InterruptedException {
final AtomicLong sum = new AtomicLong();

final int count = dataSize / threadCount;
for (int i = 0; i < threadCount; i++) {
final int modId = i * count;

public void run() {
for (int i = 0; i < count; i++) {
int pos = list.get(modId + i);
long delta = list.get(pos);
}
}
});

}

for (int i = 0; i < threadCount; i++) {
}

for (int i = 0; i < threadCount; i++) {
}
}
}

return sum.get();
}
}
```

Results:

```Run type: warm-up
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 0, elapsed: 34.447801, sum: 49995000
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 1, elapsed: 8.95851, sum: 49995001
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 5, elapsed: 9.545876, sum: 49995009
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 10, elapsed: 1.744018, sum: 49995019
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 50, elapsed: 1.887545, sum: 49995099
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 0, elapsed: 10.752156, sum: 4999950000
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 1, elapsed: 13.370241, sum: 4999950001
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 5, elapsed: 15.297022, sum: 4999950009
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 10, elapsed: 10.267383, sum: 4999950019
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 50, elapsed: 16.844115, sum: 4999950099
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 0, elapsed: 74.83112, sum: 499999500000
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 1, elapsed: 82.226897, sum: 499999500001
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 5, elapsed: 74.646764, sum: 499999500009
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 10, elapsed: 71.52722, sum: 499999500019
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 50, elapsed: 73.328613, sum: 499999500099
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 0, elapsed: 7.449299, sum: 49995000
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 1, elapsed: 7.883584, sum: 49995005
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 5, elapsed: 7.536815, sum: 49995045
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 10, elapsed: 7.7768, sum: 49995095
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 50, elapsed: 9.246285, sum: 49995495
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 0, elapsed: 67.314426, sum: 4999950000
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 1, elapsed: 70.664588, sum: 4999950005
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 5, elapsed: 68.318753, sum: 4999950045
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 10, elapsed: 71.206388, sum: 4999950095
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 50, elapsed: 65.248959, sum: 4999950495
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 0, elapsed: 461.098965, sum: 499999500000
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 1, elapsed: 406.9108, sum: 499999500005
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 5, elapsed: 513.206703, sum: 499999500045
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 10, elapsed: 473.542246, sum: 499999500095
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 50, elapsed: 570.581461, sum: 499999500495
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 0, elapsed: 12.406631, sum: 49995000
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 1, elapsed: 14.833395, sum: 49995010
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 5, elapsed: 11.98533, sum: 49995090
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 10, elapsed: 11.679525, sum: 49995190
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 50, elapsed: 13.218288, sum: 49995990
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 0, elapsed: 69.624681, sum: 4999950000
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 1, elapsed: 69.140069, sum: 4999950010
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 5, elapsed: 77.640096, sum: 4999950090
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 10, elapsed: 71.927987, sum: 4999950190
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 50, elapsed: 66.570783, sum: 4999950990
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 0, elapsed: 378.502667, sum: 499999500000
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 1, elapsed: 419.156151, sum: 499999500010
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 5, elapsed: 339.901594, sum: 499999500090
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 10, elapsed: 426.555234, sum: 499999500190
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 50, elapsed: 395.766989, sum: 499999500990
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 0, elapsed: 11.901218, sum: 49995000
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 1, elapsed: 3.829014, sum: 49995001
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 5, elapsed: 10.980387, sum: 49995009
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 10, elapsed: 1.90118, sum: 49995019
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 50, elapsed: 5.033604, sum: 49995099
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 0, elapsed: 4.303462, sum: 4999950000
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 1, elapsed: 6.433356, sum: 4999950001
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 5, elapsed: 8.015953, sum: 4999950009
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 10, elapsed: 10.697569, sum: 4999950019
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 50, elapsed: 20.900689, sum: 4999950099
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 0, elapsed: 22.107373, sum: 499999500000
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 1, elapsed: 26.153887, sum: 499999500001
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 5, elapsed: 34.408805, sum: 499999500009
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 10, elapsed: 51.090004, sum: 499999500019
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 50, elapsed: 153.929584, sum: 499999500099
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 0, elapsed: 3.918603, sum: 49995000
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 1, elapsed: 5.118304, sum: 49995005
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 5, elapsed: 8.821934, sum: 49995045
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 10, elapsed: 12.317311, sum: 49995095
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 50, elapsed: 21.752215, sum: 49995495
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 0, elapsed: 40.760553, sum: 4999950000
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 1, elapsed: 27.017787, sum: 4999950005
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 5, elapsed: 24.395766, sum: 4999950045
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 10, elapsed: 39.489004, sum: 4999950095
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 50, elapsed: 113.153861, sum: 4999950495
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 0, elapsed: 353.752201, sum: 499999500000
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 1, elapsed: 282.50961, sum: 499999500005
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 5, elapsed: 423.664369, sum: 499999500045
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 10, elapsed: 501.767616, sum: 499999500095
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 50, elapsed: 1458.115879, sum: 499999500495
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 0, elapsed: 6.227392, sum: 49995000
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 1, elapsed: 27.889835, sum: 49995010
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 5, elapsed: 5.488267, sum: 49995090
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 10, elapsed: 9.8526, sum: 49995190
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 50, elapsed: 34.633951, sum: 49995990
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 0, elapsed: 44.695707, sum: 4999950000
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 1, elapsed: 21.955976, sum: 4999950010
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 5, elapsed: 54.120305, sum: 4999950090
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 10, elapsed: 78.413631, sum: 4999950190
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 50, elapsed: 239.205075, sum: 4999950990
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 0, elapsed: 362.92385, sum: 499999500000
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 1, elapsed: 320.027424, sum: 499999500010
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 5, elapsed: 505.38798, sum: 499999500090
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 10, elapsed: 1165.81135, sum: 499999500190
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 50, elapsed: 1869.912839, sum: 499999500990
Run type: test
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 0, elapsed: 0.97632, sum: 49995000
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 1, elapsed: 0.95858, sum: 49995001
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 5, elapsed: 0.979087, sum: 49995009
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 10, elapsed: 1.088347, sum: 49995019
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 50, elapsed: 1.278052, sum: 49995099
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 0, elapsed: 5.128055, sum: 4999950000
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 1, elapsed: 5.959685, sum: 4999950001
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 5, elapsed: 6.951121, sum: 4999950009
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 10, elapsed: 8.605555, sum: 4999950019
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 100000, dataModSize: 50, elapsed: 3.878474, sum: 4999950099
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 0, elapsed: 34.628495, sum: 499999500000
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 1, elapsed: 33.505706, sum: 499999500001
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 5, elapsed: 34.152629, sum: 499999500009
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 10, elapsed: 34.661612, sum: 499999500019
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 1000000, dataModSize: 50, elapsed: 33.869828, sum: 499999500099
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 0, elapsed: 7.829228, sum: 49995000
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 1, elapsed: 7.338248, sum: 49995005
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 5, elapsed: 6.597094, sum: 49995045
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 10, elapsed: 9.179939, sum: 49995095
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 10000, dataModSize: 50, elapsed: 12.672502, sum: 49995495
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 0, elapsed: 57.167164, sum: 4999950000
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 1, elapsed: 57.412349, sum: 4999950005
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 5, elapsed: 67.656372, sum: 4999950045
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 10, elapsed: 63.353544, sum: 4999950095
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 100000, dataModSize: 50, elapsed: 66.889391, sum: 4999950495
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 0, elapsed: 521.963095, sum: 499999500000
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 1, elapsed: 517.867147, sum: 499999500005
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 5, elapsed: 542.079316, sum: 499999500045
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 10, elapsed: 386.976245, sum: 499999500095
End: list.class: SynchronizedRandomAccessList, threadCount: 5, dataSize: 1000000, dataModSize: 50, elapsed: 405.384225, sum: 499999500495
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 0, elapsed: 8.967124, sum: 49995000
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 1, elapsed: 7.918772, sum: 49995010
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 5, elapsed: 4.081412, sum: 49995090
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 10, elapsed: 4.461432, sum: 49995190
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 50, elapsed: 6.415205, sum: 49995990
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 0, elapsed: 45.251236, sum: 4999950000
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 1, elapsed: 47.764752, sum: 4999950010
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 5, elapsed: 60.124809, sum: 4999950090
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 10, elapsed: 48.346995, sum: 4999950190
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 100000, dataModSize: 50, elapsed: 39.349112, sum: 4999950990
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 0, elapsed: 340.371111, sum: 499999500000
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 1, elapsed: 481.969672, sum: 499999500010
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 5, elapsed: 535.011974, sum: 499999500090
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 10, elapsed: 540.011967, sum: 499999500190
End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 50, elapsed: 531.670146, sum: 499999500990
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 0, elapsed: 1.149342, sum: 49995000
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 1, elapsed: 1.239204, sum: 49995001
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 5, elapsed: 1.352173, sum: 49995009
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 10, elapsed: 1.7898, sum: 49995019
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 10000, dataModSize: 50, elapsed: 3.165936, sum: 49995099
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 0, elapsed: 5.357431, sum: 4999950000
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 1, elapsed: 6.688772, sum: 4999950001
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 5, elapsed: 8.353105, sum: 4999950009
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 10, elapsed: 10.515936, sum: 4999950019
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 100000, dataModSize: 50, elapsed: 20.277377, sum: 4999950099
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 0, elapsed: 23.185615, sum: 499999500000
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 1, elapsed: 27.466323, sum: 499999500001
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 5, elapsed: 33.748808, sum: 499999500009
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 10, elapsed: 48.301544, sum: 499999500019
End: list.class: CopyOnWriteArrayList, threadCount: 1, dataSize: 1000000, dataModSize: 50, elapsed: 198.997429, sum: 499999500099
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 0, elapsed: 5.603725, sum: 49995000
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 1, elapsed: 6.166289, sum: 49995005
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 5, elapsed: 7.827472, sum: 49995045
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 10, elapsed: 9.659996, sum: 49995095
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 10000, dataModSize: 50, elapsed: 20.942762, sum: 49995495
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 0, elapsed: 40.315674, sum: 4999950000
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 1, elapsed: 42.313047, sum: 4999950005
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 5, elapsed: 38.214826, sum: 4999950045
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 10, elapsed: 42.748483, sum: 4999950095
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 100000, dataModSize: 50, elapsed: 111.678623, sum: 4999950495
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 0, elapsed: 271.684979, sum: 499999500000
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 1, elapsed: 285.626939, sum: 499999500005
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 5, elapsed: 382.996082, sum: 499999500045
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 10, elapsed: 469.095528, sum: 499999500095
End: list.class: CopyOnWriteArrayList, threadCount: 5, dataSize: 1000000, dataModSize: 50, elapsed: 1126.529645, sum: 499999500495
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 0, elapsed: 5.903503, sum: 49995000
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 1, elapsed: 5.537715, sum: 49995010
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 5, elapsed: 8.679113, sum: 49995090
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 10, elapsed: 13.175054, sum: 49995190
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 50, elapsed: 27.420182, sum: 49995990
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 0, elapsed: 37.46934, sum: 4999950000
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 1, elapsed: 21.53966, sum: 4999950010
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 5, elapsed: 54.847308, sum: 4999950090
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 10, elapsed: 56.360711, sum: 4999950190
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 100000, dataModSize: 50, elapsed: 191.754104, sum: 4999950990
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 0, elapsed: 333.820706, sum: 499999500000
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 1, elapsed: 398.443131, sum: 499999500010
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 5, elapsed: 547.40548, sum: 499999500090
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 10, elapsed: 757.341745, sum: 499999500190
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 50, elapsed: 2268.404341, sum: 499999500990
```

This was done on AMD Phenom II X4 Mobile N950, 2.1 GHz, which has 4 cores.

• Modifications hurt CopyOnWriteArrayList, especially with big data sizes – even only 50 modifications make it 4 times slower
```End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 1000000, dataModSize: 50, elapsed: 531.670146, sum: 499999500990
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 1000000, dataModSize: 50, elapsed: 2268.404341, sum: 499999500990
```
• Without modifications, SynchronizedRandomAccessList pays the price for having to do synchronization being 70%-80% slower:
```End: list.class: SynchronizedRandomAccessList, threadCount: 10, dataSize: 10000, dataModSize: 0, elapsed: 8.967124, sum: 49995000
End: list.class: CopyOnWriteArrayList, threadCount: 10, dataSize: 10000, dataModSize: 0, elapsed: 5.903503, sum: 49995000
```
• Warm-up is really important when measuring – here we see a 35 times slower run:
```Run type: warm-up
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 0, elapsed: 34.447801, sum: 49995000
...
Run type: test
End: list.class: SynchronizedRandomAccessList, threadCount: 1, dataSize: 10000, dataModSize: 0, elapsed: 0.97632, sum: 49995000
```
Be Sociable, Share!

(required)

(required)

Matplotlib – plotting stock prices

I was playing the other day with Matplotlib. I was amazed how easy it is to plot graphs, all with the builtin browser.

Say you want to plot some stock data. You can download a sample provided by EOD data site. They give a sample for AAPL prices, which can be downloaded from here. If you unzip, you’ll get a `NASDAQ_AAPL.txt` file, which actually is a csv.

Installation

Installing matplotlib is simple with pip:

```\$ pip install matplotlib
```

Plotting

Here’s a very short python code to read and plot it:

```import matplotlib
matplotlib.use('webagg')

import matplotlib.pyplot as plt
import csv

with open('etc/NASDAQ_AAPL.txt') as inf:
csvr.next()
prices = [float(row[2]) for row in csvr]

plt.title('AAPL prices')
plt.xlabel('Time')
plt.ylabel('Price')

plt.plot(prices)
plt.grid(True)
plt.show()
```

Walkthrough:

```import matplotlib
matplotlib.use('webagg')
```

Imports matplotlib and sets the default backend used for plotting to WebAgg.

```import matplotlib.pyplot as plt
import csv

with open('etc/NASDAQ_AAPL.txt') as inf:
csvr.next()
prices = [float(row[2]) for row in csvr]
```

Import plotting part of matplotlib and the standard Python csv library. Read the file, skip the header and pick open prices (3rd column in the CSV file).

```plt.title('AAPL prices')
plt.xlabel('Time')
plt.ylabel('Price')
plt.grid(True)

plt.plot(prices)
plt.show()
```

Set the title, X and Y axis labels of the plot and specify that plot should have the grid shown. Actually perform plotting and show it.

There’s a minor issue for which I filed a report here, but after manually updating the file as per the ticket, all seems to be working just fine.

After doing:

```\$ python matplotlib_prb.py
```

It will start a server and open your browser pointing to http://127.0.0.1:8988/.

Final plot

Here’s how it looks for the above file:

Be Sociable, Share!

(required)

(required)

I stumbled upon this Stackoverflow question:

and got interested into the way to get your external IP by using a DNS lookup, as presented in this answer:

It’s an interesting idea and implementation and I also agree with the poster:

• DNS query is a bit faster
• More importantly, I have a feeling it’s more reliable. I know that sites can be slow, DNS query is less likely to be so
• Given the investment in hosting the DNS service on a large scale, they service is likely more robust and likely to stay there longer than sites

Anyway, if you are using Oracle Java, then you already have a JNDI DNS provider built-in. You can read more about it here:

This Stackoverflow question:

has an example code to query a generic DNS server, provided you know it’s IP address. Below is a Groovy script that combines the information from the above links:

• Gives an example of how a default way to perform a DNS query would be – `getIp` method
• Gives a way to perform DNS query on the specific DNS server – `getIpUsingDnsServer` method
• Uses these to query `myip.opendns.com` to get your external IP

Read more about OpenDNS `myip` entry here:

Here’s the script itself:

```import javax.naming.Context
import javax.naming.NamingEnumeration
import javax.naming.directory.Attribute
import javax.naming.directory.Attributes
import javax.naming.directory.DirContext
import javax.naming.directory.InitialDirContext

class DnsPrb {
static main(String[] args) {
new DnsPrb().run()
}

def run() {
String dnsServer = 'resolver4.opendns.com'
String dnsIp = getIp dnsServer
println("\$dnsServer -> \$dnsIp")

def myIps = getIpUsingDnsServer dnsServer, 'myip.opendns.com'
println("myIps: \$myIps")
}

String getIpUsingDnsServer(String dnsServer, String name) {
Properties env = new Properties()
env.put Context.INITIAL_CONTEXT_FACTORY, 'com.sun.jndi.dns.DnsContextFactory'
env.put Context.PROVIDER_URL, "dns://\$dnsServer".toString()

DirContext ictx = new InitialDirContext(env)
String[] types = ["A", "AAAA"]
Attributes attrs = ictx.getAttributes name, types

NamingEnumeration<? extends Attribute> e = attrs.all
def ips = e.collect { it.get() }
ips
}

String getIp(String name) {
ip
}
}
```
Be Sociable, Share!

(required)

(required)

Linear programming in R using lpsolve

You can read more about linear programming basics here. Here’s how one can work through this example in R using lpsolve library.

Problem

Problem definition copied from the above link:

Suppose a farmer has 75 acres on which to plant two crops: wheat and barley. To produce these crops, it costs the farmer (for seed, fertilizer, etc.) \$120 per acre for the wheat and \$210 per acre for the barley. The farmer has \$15000 available for expenses. But after the harvest, the farmer must store the crops while awaiting favourable market conditions. The farmer has storage space for 4000 bushels. Each acre yields an average of 110 bushels of wheat or 30 bushels of barley. If the net profit per bushel of wheat (after all expenses have been subtracted) is \$1.30 and for barley is \$2.00, how should the farmer plant the 75 acres to maximize profit?

Mathematical definition

Also copied from the above:

```maximize
P = (110)(1.30)x + (30)(2.00)y = 143x + 60y
subject to
120x + 210y <= 15000
110x + 30y <= 4000
x + y <= 75
x >= 0
y >= 0
```

To reference this again, we have this as the generic mathematical formulation:

```- A linear function to be maximized or minimized
maximize c1 x1 + c2 x2
- Problem constraints of the following form
a11 x1 + a12 x2 <= b1
a21 x1 + a22 x2 <= b2
a31 x1 + a32 x2 <= b3
- Default lower bounds of zero on all variables
```

Matching to our problem, we have:

```- A linear function to be maximized or minimized
P = (110)(1.30)x + (30)(2.00)y = 143x + 60y
c1 = 143
c2 = 60
- Problem constraints of the following form
120x + 210y <= 15000
a11 = 120
a12 = 210
b1  = 15000
110x + 30y <= 4000
a21 = 110
a22 = 30
b2  = 4000
x + y <= 75
a31 = 1
a32 = 1
b3  = 75
- Default lower bounds of zero on all variables
x >= 0
y >= 0
```

Note that lpsolve by default includes the last condition (i.e. all variables non-negative).

Using R to solve

See this for more details.

• Install lpsolve library
```> install.packages("lpSolveAPI")
```
```> library("lpSolveAPI")
```
• Represent our problem
```> lprec <- make.lp(0, 2)
> lp.control(lprec, sense="max")
> set.objfn(lprec, c(143, 60))
> add.constraint(lprec, c(120, 210), "<=", 15000)
> add.constraint(lprec, c(110, 30), "<=", 4000)
> add.constraint(lprec, c(1, 1), "<=", 75)
```
• Display the lpsolve matrix
```> lprec
Model name:
C1    C2
Maximize   143    60
R1         120   210  <=  15000
R2         110    30  <=   4000
R3           1     1  <=     75
Kind       Std   Std
Type      Real  Real
Upper      Inf   Inf
Lower        0     0
```
• Solve
```> solve(lprec)
[1] 0
```
• Get maximum profit
```> get.objective(lprec)
[1] 6315.625
```
• Get the solution
```> get.variables(lprec)
[1] 21.875 53.125
```

Thus, to achieve the maximum profit (\$6315.625), the farmer should plant 21.875 acres of wheat and 53.125 acres of barley.

Be Sociable, Share!

(required)

(required)

I’m in the process of familiarizing myself with Haskell (wouldn’t say it’s learning at this point), so decided to work on some Project Euler problems. Here are my solutions to problems 1-5. One thing to notice – they are unusually long for a Haskell program and as usual – take them with a grain of salt.

Project Euler problem 1

```mul35 :: Int -> Int
mul35 n = sum xs
where
xs = [i | i <- [1..n-1],
(i `mod` 3 == 0) ||
(i `mod` 5 == 0)]

main =
do
print \$ mul35 10
print \$ mul35 1000
```

Project Euler problem 2

```fibs :: [Int]
fibs = 1 : 2 : [a + b | (a, b) <- zip fibs (tail fibs)]

sumFibs :: Int -> Int
sumFibs ms = sum [x | x <- takeWhile (< ms) fibs, even x]

main = do
print \$ sumFibs 4000000
```

Project Euler problem 3

```lpf :: Int -> Int
lpf n = if md == n then n
else lpf (n `div` md)
where md = head [x | x <- [2..n], n `mod` x == 0]

main = do
print \$ lpf 13195
print \$ lpf 600851475143
```

Project Euler problem 4

```import Data.List (tails)

numsLen :: Int -> [Int]
numsLen l = [mx,mx-1..mi] where
mi = 10^(l-1)
mx = 10^l - 1

digits :: Int -> [Int]
digits 0 = []
digits n = n `mod` 10 : digits (n `div` 10)

palindrome :: Int -> Bool
palindrome n = digits n == reverse (digits n)

lpal :: Int -> Int
lpal d = maximum ps where
ns = numsLen d
xss = tails ns
ps = [y | x:xs <- xss, y <- map (* x) xs, palindrome y]

main = do
print \$ lpal 2
print \$ lpal 3
```

Project Euler problem 5

```lcmm :: [Int] -> Int
lcmm [] = error "Empty list"
lcmm [x] = x
lcmm xs = foldr1 lcm xs

hdbf :: Int -> Int
hdbf n = lcmm [1..n]

main = do
print \$ hdbf 10
print \$ hdbf 20
print \$ hdbf 30
```
Be Sociable, Share!

One Response to “Project Euler in Haskell”

Project Euler in Haskell – problems 6 through 10 « Blog Archive « icyrock.com on November 30th, 2014 15:15:

[…] from the previous one, here are my solutions to problems 6-10. Same warning applies – they are unusually long for a […]

(required)

(required)

WebGL charts

I wanted to see how hard it would be to make a WebGL chart. Here’s the code with comments. The code is written in CoffeeScript.

```class ThreeJsPrb
initCSR: ->
width = 800
height = 600
viewAngle = 45
aspect = width / height
near = 0.1
far = 20000

@camera = new THREE.PerspectiveCamera viewAngle, aspect, near, far
@camera.position.z = 15000

@scene = new THREE.Scene

@renderer = new THREE.WebGLRenderer
antialias: true
premultipliedAlpha: false
@renderer.setSize width, height

\$('<div>')
.append(@renderer.domElement)
.appendTo(document.body)
```

We are making a class called ThreeJsPrb. The first method is called initCSR, short for init camera, scene and renderer. WebGL needs these three:

• Camera to define where we are looking from
• Scene that defines what the world contains
• Rendered to render all this

In the above:

• We define a few variables defining dimensions of the renderer, view angle aspect and near / far z-index
• Setup a camera and it’s position
• Setup a scene and add a camera to it
• Setup a renderer, with some options (antialias and premultipliedAlpha) and set it’s weight
• Finally, add the renderer to dom using jQuery
```  draw: =>
@render()
setTimeout(() =>
requestAnimationFrame @draw
, 1000 / @fps)
```

This method is the main “loop” of this app. It will render the current scene, then use a combination of setTimeout and requestAnimationFrame to repeat this in the future. The combination in this case is necessary to be able to set a relatively constant fps that doesn’t max out the fps all the time.

```  render: =>
if Math.abs(@group.rotation.y) > Math.PI / 8
@rot *= -1
@group.rotation.y += @rot
@renderer.render @scene, @camera
```

The render method itself does two things:

• Applies a see-saw-behaving rotation (i.e. rotate right up to Math.PI / 8 radians, then reverse the direction)
• Renders the scene using the given camera
```  # http://en.wikipedia.org/wiki/World_population#Population_growth_by_region
worldPopulation: {
1: 200
1000: 310
1750: 791
1800: 978
1850: 1262
1900: 1650
1950: 2519
1955: 2756
1960: 2982
1965: 3335
1970: 3692
1975: 4068
1980: 4435
1985: 4831
1990: 5263
1995: 5674
2000: 6070
2005: 6454
2010: 6972
}
```

This is just a sample chart data, taken from Wikipedia.

```  makeScene: ->
material = new THREE.MeshLambertMaterial
color: 0x80b2ff

@group = new THREE.Object3D

@graph = new THREE.Object3D
@graph.position.y -= 3000

xpos = 0

for k, v of @worldPopulation
height = v
heightSegments = 50
openEnded = false

cylinder = new THREE.Mesh cylinderGeometry, material
cylinder.position.x = xpos
cylinder.position.y = v / 2

@graph.position.x = -xpos / 2

@rot = 0.01
@group.rotation.x = Math.PI / 8

directionalLight = new THREE.SpotLight 0xffffff
directionalLight.position.set -xpos, 1000, 3000
directionalLight.angle = Math.PI / 2
directionalLight.target.position.set xpos / 3, 0, 0
```

This is the meat of the app. The above code is responsible for setting up the scene. As our scene doesn’t change except for rotation, this is done only once. Here’s what’s going on:

• We define a lambert material of a given bluish color
• We define a Object3D called group. This will be used for easier around-the-center rotation later
• We create another Object3D called graph and add it to the group. We also move it “down” by setting the y-axis position
• For each of the keys in worldPopulation map, we create a cylinder geometry and a mesh out of this and the material we made above. We add that to the graph
• We move the graph within it’s parent element (group) to be split in the middle along x-axis. Again, this is to achieve around-the-center rotation later
• We setup the rotation step
• We add a direction light
```  run: ->
console.log '> ThreeJsPrb.run'

@initCSR()
@makeScene()

@fps = 15
@draw()

console.log '< ThreeJsPrb.run'

module.exports = ThreeJsPrb
```

Finally, the initialization code and module export.

Here’s a screenshot:

Be Sociable, Share!

One Response to “WebGL charts”

three.js clock « Blog Archive « icyrock.com on April 29th, 2014 22:48:

[…] the three.js charts post, here’s the clock using […]

(required)

(required)

Brunch / Marionette sample application

The other day I ran into Brunch. You can visit the site to get more information, but in a nutshell it’s a build tool. I decided to play with it a bit.

Installation

Installation is simple:

```\$ npm install -g brunch
```

Creating a sample project

In order to create a new project, a skeleton is used. At the moment, there are a few dozen skeletons listed here. I am going to use this, which is “Brunch with Coffee Script, Stylus, Backbone, Marrionette, and jQuery.”.

To create the project, this needs to be done:

```\$ brunch new https://github.com/monokrome/brunch-with-grits
```

After the skeleton is cloned and the libraries downloaded, you will have something like this:

```app
bower_components
bower.json
config.coffee
node_modules
package.json
vendor
```

Here:

• `config.coffee` is a brunch configuration
• `bower.json` is bower configuration
• `vendor` is where brunch will put the bower-fetched dependencies (which are managed by bower under `bower_components`)
• `app` is where files related to our application should go

In order to build it for the first time, do this:

```\$ npm install
\$ brunch build
```

After this, another folder appears – `public`. This one contains compiled files:

```index.html
javascripts
stylesheets
```

Watching

When developing, all the compilation that needs to be done can be done automatically. This is the watching functionality of brunch. Just invoke this:

```\$ brunch watch --server
```

The `--server` parameter will start a development Web server (defaults to `localhost:3333`).

Pieces

The above skeleton already contains `application.coffee` file. This one initializes `Backbone.Marionette.Application` and does nothing else. In order to display something, Marionette has a few concepts. This is I think best explained on the main page here, but briefly:

• Template translates into a HTML that will be shown
• View renders a template and handles events
• Region defines a jQuery selector that will hold a View instance

View also depends on Backbone.Model or Backbone.Collection to hold the data that is used by a Template instance when rendering.

Basic app

Let’s do a small app – a bounded (to [-5, 5] integer range) counter. In brief:

• Our model is a number
• Our view is a text box and a button
• Button click will make the model’s number to be increased by one

I’m also going to use Handlebars templates, so will first add this:

```    "handlebars-brunch": ">= 1.0 < 1.8"
```

to the `dependencies` secdion of `package.json`, followed by:

```\$ npm install
```

Let's do this step by step.

Modules

I'm going to use the regular CommonJS modules here. Thus, when I say "this goes to file abc", it needs to be put in that file for the require logic to work. If you change the file names or the folders where they belong, please update the require lines appropriately. Just to make it simple, all files here will go to the root of `app` folder.

Main HTML

The main HTML in the skeleton is not surprisingly `index.html`. We just need to add one line in the body:

```    <div id="main"></div>
```

As to why, it will be clear when we discuss the controller a bit later. This edit goes to `assets/index.html`.

Model

Our model is simple:

```module.exports = class Number extends Backbone.Model
defaults:
number: 1

inc: ->
@set 'number', @get('number') + 1
```

This goes to `number-model.coffee`. So we have:

• Number class that extends Backbone.Model class
• Default number is 1
• Inc method that increases the number property
• Emphasis on property here - calling `set` on `number` will send a `change:number` event, which we will use later

Template

Template is simple as well:

```<input id="number" type="text" value="{{number}}" readonly="false" />
<button id="inc">Inc</button>
```

This goes to `number-template.hbs`. We have this:

• This is a Handlebars template
• It contains two HTML elements - an input box to display our number
• Both have the IDs that we'll reference later (`#number` and `#inc`)
• Input has it's value set to `{{number}}` which Handlebars will render appropriately
• It also has `readonly` set to false, just so user cannot change the value, as we don't have the binding for this update

View

View is simple, though a bit more complex than model:

```module.exports = class NumberView extends Backbone.Marionette.ItemView
template: require('number-template')
events:
'click #inc': 'inc'
ui:
incInp: '#number'

initialize: ->
@listenTo @model, "change:number", @numberChanged

numberChanged: ->
@ui.incInp.attr 'value', @model.get 'number'

inc: (evt) ->
@trigger 'number:inc'
```

This goes to `number-view.coffee`. Here we have:

• NumberView extends Backbone.Marionette.ItemView. This class is responsible for showing a single item, hence the name
• We specify the template as `number-template`
• The events says that when our button (HTML ID is `#inc`, our Inc button) is clicked, we invoke `inc` method on the view
• `ui` property is just an alias map. It allows us to say `@ui.incInp` and reference the HTML element specified, in this case `#number`, which is our `input` element
• `initialize` method binds a listener to our model. It says: whenever the model triggers `change:number` event, call our `numberChanged` function on this view
• `numberChanged` is just updating the `input` with the number whenever it changes
• `inc` method is the event listener for button click - it triggers `number:inc` event, which our controller is going to catch and then act appropriately

Controller

The controller looks like this:

```module.exports = class NumberController extends Marionette.Controller
initialize: (options) ->
@model = options.model
@view = options.view
@listenTo @view, 'number:inc', @numberInc

numberInc: ->
newNumber = @model.get 'number'
newNumber++
newNumber = -5 if newNumber > 5
@model.set 'number', newNumber
```

Note that this (as per this doc paragraph) is not equivalent to the C in MVC. I'm however using it for this purpose only.

This goes to `number-controller.coffee`. It has two things:

• `initialize` method remembers the provided model and view instances and subscribes to `number:inc` event. This event is triggered from view when button is clicked, see above
• `numberInc` is the method that encapsulates the business logic of our bounded counter. It will increase the number and make sure it stays in [-5, 5] range
• Just a reminder here: doing `@model.set` will trigger a `change:number` event, which will complete the cycle by going to our view and rendering it via `numberChanged` method, see above

Application initialization - wiring all this together

We need to update `application.coffee` to wire this together. We can also do this in `initialize.coffee`, depending on how we want to do the separation of concerns. Here's how it looks:

```NumberModel = require('number-model')
NumberView = require('number-view')
NumberController = require('number-controller')

class Application extends Backbone.Marionette.Application
initialize: =>
@on 'initialize:after', @startHistory

model = new NumberModel
view = new NumberView model: model
new NumberController model: model, view: view

@mainRegion.show view

@start()

startHistory: (options) => Backbone.history.start()

module.exports = Application
```

Here we do the following:

• Import the necessary classes, NumberModel, NumberView and NumberController
• In `initialize`, instantiate the model, view and controller and wire them up as needed
• Add a region - this references the `#main` div that we added to `index.html`
• Finally, show the view into this region and start the app

Conclusion

I can say this about the simple app:

• Brunch makes it very easy to start the project - installation and getting up and running from the appropriate skeleton is just a few commands away
• It's `watch` command is a one-step way to a very good development experience - it compiles templates, CoffeeScript files, bundles everything and a refresh of the dev Web server just brings the latest - like it a lot
• Bower allows for a very nice dependency management
• Marionette provides a very good and simple framework for decoupling things into sensible, well-contained units (models, templates, views, controllers, application - and there are also layouts and under-the-cover event aggregator that we actually used above)

All in all, I think this is a very good model - I hope to use it going forward.

Be Sociable, Share!

6 Responses to “Brunch / Marionette sample application”

Litts on October 7th, 2013 15:38:

Nice tutorial , Do you have an example here your views are in separate directories

Dan on October 15th, 2013 08:23:

Hi,

great introduction to Marionette!

One question though: what’s the purpose of this one:

inc: -> @set ‘number’, @get(‘number’) + 1

Doesn’t the controller already take care of that here:

numberInc: -> newNumber = @model.get ‘number’ newNumber++ newNumber = -5 if newNumber > 5 @model.set ‘number’, newNumber

icyrock.com on October 15th, 2013 21:47:

Thanks Litts! In order to have views in separate folders, you follow the same logic. E.g. if you put your view in app/view1/view1-view.coffee, you’d just use a different require: require(‘view1/view1-view’). Otherwise, things would look the same.

icyrock.com on October 15th, 2013 21:49:

Thanks Dan, glad you liked it! The inc method of the model is not used – I guess just wanted to emphasize that you cannot just do number++, but instead need to use set / get, which trigger the ‘change:number’ event. Agree however – the active logic is in the controller.

Poplinr on February 24th, 2014 18:27:

This helped me get setup really quickly! Thanks for the post.

icyrock.com on February 27th, 2014 23:54:

Sure thing, glad it was useful!

(required)

(required)