2015-02-14

How to Learn Programming and Train your Logic

So today one of my student ask me, how to train your logic in programming? There are two steps that you must do, here's my tips in English, the Indonesian slang version below. For those who doesn't understand English, it's greatly recommended to learn about it (at least you must able to read and understand English) before studying programming, since most all programming language tools, errors, and documentation written in English.

Tips on learning programming and train your logic

Actually, learning programming language is quite similar to learning ordinary language (Indonesian or English).

1. memorize the syntax

  • first thing you must do is.. memorize the syntax, yes, because it would took a long time to describe logic with shapes and pictures ^^ (especially when the logic is too long and complex), so learn how to describe a logic, and the most concrete way to do it is using a programming language!
    • understand and memorize how to create a variable, data types (character, integer, real numbers, boolean, string), how program works (from beginning to end, or line by line), how to create a main function and how to compile
    • this is analogous to understand a alphabet and how words are made, kind of words (nouns, adjective, verbs, adverb, etc)
    • we could not make a correct word without understanding alphabet
    • we could not make a correct statement without understanding kinds of words (is this word a subject/name? is this word a predicate/verb? is this an object/complement? is this word a modifier?)
    • people (or the compiler) would complain if we write many statements without punctuations (dot or question mark or exclamation sign, etc)
    • by doing a compilation process, it's like to tell the word processor to do a spell-check on our script, is there any miss-spelling on my script?
  • understand and memorize how to use ask for input and give an output, using built-in functions and math operators (addition, subtraction, division, multiplication and modulo), grammar, and also feedback (error and how to run a program)
    • this step analogous to how to create a statement, how to ask a question and how to give a correct answer
    • after we know how to ask and answer, we now could interact with computer, we also required to store their answer for later decision (just like approaching someone you like, if we remember that she like noodle (stored on a variable), maybe sometime we could ask her out on some noodle restaurant)
    • understand that there would be an input (how we tell something to the computer), process (how computer transform data into information), and output (how computer tell us something)
    • including a customer feedback, in this case, we are the store manager (or producer), and compiler is our prospective buyer/customer, when we knew that customer want, we already reduce 1/3rd of the problem (compile error - correct purchase request), 2 other problem would be runtime error (correct purchase order but our staff execute it poorly or give wrong item), and logic error (understand what customer need, but give a bad service)
    • running a program is just like accepting reader's feedback, is what we write could be understood well by computer (give an expected result)
  • learn and understand how boolean algebra works (and, or), branch or decision (if-then), looping or iteration (while, until) 
    • this is analogous to understand how to make correct life decision (if I need money, I should work; if I want to be an expert in certain field, I must practice and use it in my life, I must keep trying until I succeed or until I gave up; etc)
  • just doing first three steps is enough to write a program, but if you want your life to be easier, learn how to make a phrase/synonym/acronym (function/procedure + array/list/associative array/map + struct/record)
    • this is analogous to understanding certain word or phrase to shorten our statements (rather than say "4 legged animal that say meow", it would be easier to call it a "cat")
  • these first steps can be done by reading a good programming books
  • the criteria of success for step #1 is when you could read many program's source code and understand it's meaning, line by line

2. try to write, practice, practice and practice..

  • read a question, understand what's the input, what's the output, and what how to process those input into a correct output, for example, if you're given a raw ingredients, how to process it into a well prepared hot soup that ready to be eaten?
    • if you could not found the answer by yourself, you must read other people's source code (for example in codeforces), try to read and understand, imitate (try to cook it yourself), don't ask for other people to cook it for you (directly copying and pasting) then you claim it as your own soup
  • try to solve questions on the online judge (for example in URI, SPOJ, UVA, etc)
    • more you practice cooking, or workout/exercise, or anything, we would become more experienced in that field.. (practice doesn't lie - the practice result/planting/investing time/money correctly will produce a result)
    • start from easiest problem (start crawling, walking before you learn to run)
  • and lastly, don't start step 2 before you do step 1 (start by writing an alphabet before you write a poem)

Tips sukses belajar bahasa pemrograman dan mengasah logika

Benernya belajar bahasa pemrograman itu sama saja seperti mempelajari bahasa biasa (Indonesia or Inggris).

1. hafalkan syntax-nya.

  • pertama kali yang harus dilakukan adalah, hafalkan syntax, yup, karena mendeskripsikan suatu logika dengan gambar itu merepotkan ^^ (apalagi kalo logika-nya panjang dan kompleks); jadi dipelajari dahulu cara mendeskripsikan suatu logika, dan cara yang paling kokrit adalah dengan bahasa pemrograman!
    • pahami dan hafalkan cara membuat variabel, jenis2 tipe data (karakter, bilangan bulat, bilangan riil, boolean, string), cara program berjalan (dari atas ke bawah atau baris demi baris), cara membuat fungsi main dan cara compile..
    • ini analoginya seperti memahami huruf dan bagaimana sebuah kata dibentuk, jenis-jenis kata (kata benda, kata sifat, kata kerja, kata keterangan, dst)
    • kita tidak bisa membuat kata dengan benar kalau belum hafal semua huruf
    • kita tidak bisa membuat kalimat dengan benar, kalau tidak tahu kata ini jenisnya apa (subject/nama orang kah? predikat/kata kerja kah? obyek kah? kata keterangankah?)
    • orang (atau compiler) akan ngomel2 ketika kita menulis banyak kalimat tanpa diberi titik (atau titik koma atau pemisah lainnya)
    • dengan melakukan proses compile, itu seperti meminta program word processor untuk memeriksa spelling, ada kata/huruf yang salah atau tidak di naskah ku?
  • pahami dan hafalkan cara meminta input dan mencetak output, cara menggunakan fungsi2 bawaan dan operator2 matematika (penjumlahan, pengurangan, pembagian, perkalian, modulo, akar), tata bahasa, dan feedback (cara membaca error dan cara run program)
    • ini analoginya seperti memahami cara membuat kalimat (SPOK), cara membuat kalimat tanya, dan cara menjawab yang benar
    • setelah tahu cara bertanya dan cara menjawab, kita sudah bisa berinteraksi (PDKT dengan komputer), kita tinggal simpan jawaban si komputer untuk masa depan, misal dia suka makan ayam, ya suatu saat kita masak'kan soto ayam atau ayam goreng, dll
    • pahami bahwa minimal ada input (cara kita memberi tahu komputer), proses (cara data diubah menjadi informasi oleh komputer), dan output (cara komputer memberi tahu kita)
    • termasuk dengan customer feedback, dalam hal ini kita yang jadi toko/produser/distributor, compiler yang jadi customer; ketika tahu customer maunya apa, ya kita sudah mengurangi 1/3 masalah.. (compile error - pesanan benar), 2 masalah lagi adalah: runtime error (pesanan benar tapi staff kalian salah ngasih barang) dan logic error.. (paham kebutuhan customer tapi salah dalam memberikan pelayanan)
    • run program itu seperti menerima feedback dari pembaca, apakah yang ingin kumaksud sama dengan yang dipahami oleh komputer (hasilnya sesuai keinginan)
  • pahami dan hafalkan cara kerja aljabar boolean (dan, atau), percabangan (bila/jika, maka), perulangan (sampai, ketika masih)
    • ini analoginya seperti memahami cara membuat keputusan hidup yang benar, (jika butuh uang, maka saya harus bekerja; jika saya ingin mahir di suatu bidang, maka saya harus latihan dan sering menggunakannya dalam kehidupan; saya akan mencoba terus sampai saya berhasil atau saya putus asa; dst)
  • benernya dari 3 hal di atas sudah cukup untuk membuat program, tapi kalau mau hidup lebih mudah, pelajari cara membuat istilah/sinonim/frasa (fungsi/prosedur + array/list/associative array/map + struct/record)
    • ini analoginya seperti memahami suatu istilah, dengan menggunakan istilah, kita dapat mempersingkat kalimat (daripada menyebut "binatang berkaki empat yang mengeong", kan lebih muda menyebutnya "kucing")
  • step pertama ini bisa dilakukan dengan membaca buku programming yang tepat.
  • kesuksesan step pertama bisa diukur ketika sudah sanggup membaca banyak source code program dan memahami maksudnya baris demi baris.

2. coba menulis, latihan, latihan, dan latihan..

  • baca soal, dipahami apa inputnya, apa outputnya, dan kira2 prosesnya seperti apa (diapakan), misal dikasih 1 bungkus mie instan, maka harus diapakan supaya jadi mie goreng yang siap dimakan?
    • kalau belum bisa menemukan sendiri, ya terpaksa baca source code orang (misal di codeforces), pahami, tiru (dicoba masak sendiri), jangan minta orang lain yg membuatkan (copy paste langsung) lalu di claim sebagai mie goreng buatan sendiri..
  • coba soal2 di online judge (misal TOKI Learning Center, URI, SPOJ, dst)
    • makin sering kita latihan masak, atau olahraga, atau apapun, maka kita akan makin mahir.. (practice doesn't lie - hasil latihan/menanan/menginvestasikan materi/waktu dengan benar pasti berbuah)
    • mulailah dari problem/soal yang paling sederhana (belajarlah merangkak terlebih dahulu sebelum belajar berlari).
  • jangan lupa, jangan mulai step 2 sebelum menjalankan step 1 (belajarlah menulis huruf terlebih dahulu, sebelum belajar membuat puisi).







2015-02-12

How to Remove Right Click or Copy restriction/protection from a website?

Sometimes, some annoying website, such as this site :3 disables the right-click or text selection to prevent people from copying their content, for example using this javascript and css before </body>

<script>
  document.body.oncopy = function(e){
    if (window.clipboardData) window.clipboardData.clearData();
    return false;
  };    
  document.body.onselectstart = function(e){ return false; };    
  document.oncontextmenu = function(){ return false; }
<script>
<style>
  html {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }
</style>


How to disable them?
Just open the JavaScript Console (Ctrl+Shift+I on Chrome or Ctrl+Shift+K on Firefox), go to the Console tab and paste this command:

document.body.oncopy = document.body.onselectstart = document.oncontextmenu = null;

If the selection still not working, then go to the Element tab, just uncheck the css rules that contains substring user-select or touch-callout, like the picture below:


Voila, now you can select freely on their website ^_^)b


2015-02-11

How to Install OrientDB Community Edition in Linux

OrientDB is full-featured NoSQL database, it is a RDBMS (just like PostgreSQL, MySQL, Oracle, MSSQL Server), a document-oriented database (just like MongoDB and Cassandra), key-value store (yes, just like Redis, Memcache, RiakCouchBase and many more) and also a graph database (just like Neo4j). To install the sofware, first you must make sure you have installed JDK and Ant. Then download, extract the archive, and compile using this command:

wget -c https://github.com/orientechnologies/orientdb/archive/2.0.2.tar.gz 
tar xvfz orientdb-2.0.2.tar.gz
cd orientdb-2.0.2
ant
cd ../releases/orientdb-community-2.0.2

To start the server, use this command:

cd bin/
./server.sh

At the first time you will be asked a new root password. To start the console, use this command:

./console.sh

Type help within the console for more information about the console commands. And lastly if you want to use the OrientDB Studio UI, just visit this URL: http://127.0.0.1:2480.

You can learn more about OrientDB here.


2015-02-10

If Programming Languages were Religions

This is old (2008) but still fun to re-read ^_^;;
Re-blogged from higherorderfun (Rodrigo Monteiro).
(Inspired by “If programming languages were cars“)
See other comparison about programming language and anything here.

C would be Judaism - it’s old and restrictive, but most of the world is familiar with its laws and respects them. The catch is, you can’t convert into it – you’re either into it from the start, or you will think that it’s insanity. Also, when things go wrong, many people are willing to blame the problems of the world on it.

Java would be Fundamentalist Christianity – it’s theoretically based on C, but it voids so many of the old laws that it doesn’t feel like the original at all. Instead, it adds its own set of rigid rules, which its followers believe to be far superior to the original. Not only are they certain that it’s the best language in the world, but they’re willing to burn those who disagree at the stake.

PHP would be Cafeteria Christianity – Fights with Java for the web market. It draws a few concepts from C and Java, but only those that it really likes. Maybe it’s not as coherent as other languages, but at least it leaves you with much more freedom and ostensibly keeps the core idea of the whole thing. Also, the whole concept of “goto hell” was abandoned.

C++ would be Islam - It takes C and not only keeps all its laws, but adds a very complex new set of laws on top of it. It’s so versatile that it can be used to be the foundation of anything, from great atrocities to beautiful works of art. Its followers are convinced that it is the ultimate universal language, and may be angered by those who disagree. Also, if you insult it or its founder, you’ll probably be threatened with death by more radical followers.

C# would be Mormonism - At first glance, it’s the same as Java, but at a closer look you realize that it’s controlled by a single corporation (which many Java followers believe to be evil), and that many theological concepts are quite different. You suspect that it’d probably be nice, if only all the followers of Java wouldn’t discriminate so much against you for following it.

Lisp would be Zen Buddhism – There is no syntax, there is no centralization of dogma, there are no deities to worship. The entire universe is there at your reach – if only you are enlightened enough to grasp it. Some say that it’s not a language at all; others say that it’s the only language that makes sense.

Haskell would be Taoism - It is so different from other languages that many people don’t understand how can anyone use it to produce anything useful. Its followers believe that it’s the true path to wisdom, but that wisdom is beyond the grasp of most mortals.

Erlang would be Hinduism – It’s another strange language that doesn’t look like it could be used for anything, but unlike most other modern languages, it’s built around the concept of multiple simultaneous deities.

Perl would be Voodoo – An incomprehensible series of arcane incantations that involve the blood of goats and permanently corrupt your soul. Often used when your boss requires you to do an urgent task at 21:00 on friday night.

Lua would be Wicca – A pantheistic language that can easily be adapted for different cultures and locations. Its code is very liberal, and allows for the use of techniques that might be described as magical by those used to more traditional languages. It has a strong connection to the moon.

Ruby would be Neo-Paganism – A mixture of different languages and ideas that was beaten together into something that might be identified as a language. Its adherents are growing fast, and although most people look at them suspiciously, they are mostly well-meaning people with no intention of harming anyone.

Python would be Humanism: It’s simple, unrestrictive, and all you need to follow it is common sense. Many of the followers claim to feel relieved from all the burden imposed by other languages, and that they have rediscovered the joy of programming. There are some who say that it is a form of pseudo-code.

COBOL would be Ancient Paganism – There was once a time when it ruled over a vast region and was important, but nowadays it’s almost dead, for the good of us all. Although many were scarred by the rituals demanded by its deities, there are some who insist on keeping it alive even today.

APL would be Scientology – There are many people who claim to follow it, but you’ve always suspected that it’s a huge and elaborate prank that got out of control.

LOLCODE would be Pastafarianism – An esoteric, Internet-born belief that nobody really takes seriously, despite all the efforts to develop and spread it.

Visual Basic would be Satanism - Except that you don’t REALLY need to sell your soul to be a Satanist…

Thanks to jfs and other people on #aegisub for the suggestions. Keep in mind, this list is a joke, and is not meant to offend anyone. Also, if you’re a ******, please don’t kill me.

-- and some of the comments (butt-hurt people and flames filtered)

Well if you want to add JavaScript to the list, how about we class it under Black Magic. Seeing how it is something designed to help us achieve good, with unintentional consequences beyond our comprehension, plus it can be used by evil doers to control, spy and mess with the innocent. I personally use as little as possible JavaScript, resorting more to server side code if possible. Or Alcoholism, the more you do it, the more it rots your brain as you realize that functions are objects, your prototypes are polluting namespaces, and you just can't seem to get any closure. Or Jedi Religion. Those who master it can do anything.

What about Prolog? Surely that'd be Atheism (yeah - I know, not technically a religion, but you know what I mean) a completely rationalistic take on the programming universe by following scientific deduction.

Smalltalk is the ancient Egyptian religion. The Initiated know it already had all the important concepts working long ago and most popular modern languages are incomplete subsets of it that obsess over artificial restrictions of their own creation while entirely missing the reason their code exists in the first place. And the heart of your code will be judged against the Feather of Truth before it can join the message passing afterlife. Smalltalk would be Freemasonry: lots of companies know it and use it but are afraid to say they do because it is a competitive advantage to them. Therefore it is a close, near-secret society of users. Moreover Smalltalk programs use reflection as means to improve themselves, which is one of the key principles in freemasonry. Last but not least they are viewed by several other religions as ancient outcasts, but they know better and are still quietly changing the world and influencing others.

Machine Language is Animism - the belief that ultimately everything is made out of bits and on some level can be thought of as an executable.

Assembly Language is Shamanism - the idea that we can use symbols to more easily communicate with the binary world. Also that we can change the visible world by journying into the hidden realm by the use of debuggers. Or Assembly is Atheism... followers believe that whatever you do, there is only the reality on the chip. You shouldn't need intermediary or 'fake' rules to deal with the reality right in front of you, but they can be useful for guidance so long as you don't believe them. They believe if you can handle it, you are enlightened, but understand a human need for simplicity. Try to argue with them though, and you'll get an earful.

Delphi is obviously Catholic. We enjoy lots of structure, and the VCL/RTL protects us from making most windows calls directly. It was founded (created) by somebody who is said to have super-human (very good technical) abilities. It grew to a point where it had a lot of power and followers. Many things have changed since Delphi was founded and, somehow, it has managed to evolve and grow (Delphi for .NET), however, in the process, it has lost the consistency that characterized its earlier flavors. Due to gross mistakes in its leadership (yeah, Borland), Delphi has lost ground to newer religions like C#, dynamic languages and, of course, the Web; but it still manages to survive and grow within its possibilities. -- Pascal/Delphi is Church of England. Once having quite an extensive and radical following, it has since mellowed out a lot. These days its followers have mostly given up on converting the world to their point of view. It's looked down at with some bemusement by some of the bigger languages that see themselves as more serious. Has trouble attracting young people. Pascal is Catholicism, it's old, was meant as a universal language, developed in a town that has climate similar to Rome, a language with no actual compilers--only interpreters, a language in which most anybody who does any programming had to learn, a language that no one practices, a language with simple but very strict rules making it a very litigious language such that if you don't follow all of the rules all of the time to the minutest detail, you will never experience the joy of getting your program to actually run, only frustration, confusion and guilt.

Fortran would be like the Amish faith - there's a relatively small number of programmers that use it, they don't try to proselytize others into using Fortran (perhaps knowing it's futile), and if you weren't born into it (that is, it wasn't the first or second major programming language you learned) there's about zero chance you'll ever understand it (and if you do learn a little about it later in life, you'll shake your head and wonder how anyone could adhere to it). And yet its adherents refuse to let it die. Also if you have programmed in Fortran for years and then discover another language you like better you'll probably never go back, so it's likely those in the "Fortran forever" camp will shun you from then on (at least they will never admit that your new preferred language could possibly be better!). But no one denies that you can run Fortran successfully on horse-and-buggy era computers (metaphorically speaking, of course!) and if, someday, something (like an EMP) destroys all the semiconductor-based computers, the Fortran guys will probably be able to run their language on the old vacuum-tube based Univac computers, and will therefore be far ahead of their peers who need the modern semiconductor-based technology to accomplish anything!

Objective-C would be Jews for Jesus. They want to keep the old ways, and extend them in a lovey dovey easy-to-use ways.

Groovy is Emergent Christianity: it comes from Java, but it's much hipper, its adherents look down on the Java followers they're still friends with, and they're a lot less concerned about putting things into such rigid categories. It's also low on ceremony and can easily modify itself as needed.

RPG would be Jehovah’s Witnesses. RPG programmers are of the elite 144,000 left in the world (because there are only 144,000 left in the world) and believe we are in the last days of the present world and lots of people make fun of them for their beliefs and rigid standards

Applescript is an analogy to Shinto: It pervades everyday life on Mac OS X, has few requirements or taboos, has been around practically forever (it started life as Hypercard), and is easy to get your mind around. It also has Steve Jobs as its Amaterasu. The only problem: As Shinto is confined solely to Japan, so Applescript is confined solely to Mac OS X and is found nowhere else.

Postscript is like one of those weird native south american religions where you have to get completely mashed on psychoactive herbs to program in it and then spend the next two days solid vomiting

Forth is like Kaballah, learning it requires lots of meditation on stuff like number theory and the calculus of infinitesimals, and any written stuff on it sounds to the uninitiated to be solid gibberish, but once you know it you see that it's just a systemization of minimalism-worship.

Clojure would be Unitarian Universalism. Although technically based on Java, it looks more like an eccentric version of Lisp. Somehow, the Renaissance and Enlightenment managed to produce, on a foundation of Java, a language that has the spare simplicity, lack of doctrine, and freedom of Lisp, that nevertheless, somehow, is able to coexist peacefully and productively with Java, while also incorporating modern ideals found in neither.

Ada is Anglicanism. Created by fiat as the official language of the government but nobody really pays it much attention anymore.

Brainf*ck, I think, would be Discordianism. Is it a programming language disguised as a joke, or is it a joke, disguised as a programming language..?

Check the next blogpost, if programming langauge were woman.

2015-02-03

How to build latest Go IDEA Plugin

As we already know, IntelliJ IDEA has the best Javascript and almost any other language auto-complete support, including database client and many useful linters and development tools. This tutorial intended to make IntelliJ as Go IDE, since last time I tried, the plugin (v0.9.6) is buggy and not good enough for daily use. First of all, the last plugin release (1.0.0-alpha11) is outdated, there's many bug that has been fixed after then. To build the latest package, use this command (or see first comment below for shorter command):

git clone --depth 1 git@github.com:go-lang-plugin-org/go-lang-idea-plugin.git
cd go-lang-idea-plugin
git checkout -b v1.0.0-alpha0
git branch --set-upstream-to=origin/v1.0.0-alpha0 v1.0.0-alpha0
git reset --hard origin/v1.0.0-alpha0
git pull
ln -s $YOUR_INSTALLED_IDEA_PATH idea-IC

alternatively, you can clone certain branch directly:

git clone -b v1.0.0-alpha0 https://github.com/go-lang-plugin-org/go-lang-idea-plugin.git
ln -s $YOUR_INSTALLED_IDEA_PATH idea-IC

Then open the directory using IntelliJ, open the File > Project Structure...


Make sure it has been configured as described in this link (rename the idea-IC SDK to IDEA sdk, assign that SDK to each module and project, install correct GrammarKit and ant plugin), when done, choose Build > Build Artifacts... > Go.zip to build the latest release on the bin/directory. Just install the zip file normally in plugins setting dialog. One more thing, to make this plugin works correctly, enter your $GOPATH value into Global Libraries and Project Libraries on Settings > Languages and Frameworks > Go Libraries. Voila! now your IDEA support Go programming language ^_^;


Or if building manually is taking too much of your time, you could download Go.zip file from this directory.

Old String CombSort Benchmark

this is old benchmark, you can find updated result here.

2015-01-29

IntroSort vs CombSort vs ShellSort vs HeapSort vs MergeSort

As we already know, that GCC's std::sort uses IntroSort (a QuickSort algorithm that changes into HeapSort when recursion depth is too deep). Also as we already know that CombSort is improved version of BubbleSort, and ShellSort is improved version of InsertionSort), but sometimes we don't know, how good are they in real-life benchmark. So today I tried to compare them all (with addition HeapSort and inplace MergeSort). My setup is 64-bit Linux 3.18.2-1, Intel i3-4150, 8 GB RAM, Non-SSD disk, here's the code:

// intro.cpp
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 10000000;
int main() {
    int* arr = new int[N];
    for(int z=0;z<N;++z) arr[z] = rand();
    sort(arr,arr+N);
    for(int z=1;z<N;++z) if(arr[z]<arr[z-1]) printf("!");
    delete[] arr;
}

// comb.cpp
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
int newGap(int gap){
    gap /= 1.3;
    if(gap == 9 || gap == 10) gap = 11;
    if(gap < 1) return 1;
    return gap;
}
void combSort(int a[], int len){
    int gap = len;
    bool swapped;
    do {
        swapped = false;
        gap = newGap(gap);
        for(int i=0; i < len-gap; ++i) {
            if(a[i] > a[i+gap]) {
                swapped = true;
                swap(a[i], a[i+gap]);
            }
        }
    } while(gap > 1 || swapped);
}
const int N = 10000000;
int main() {
    int* arr = new int[N];
    for(int z=0;z<N;++z) arr[z] = rand();    
    combSort(arr,N);
    for(int z=1;z<N;++z) if(arr[z]<arr[z-1]) printf("!");
    delete[] arr;
}

// shell.cpp
#include<cstdlib>
#include<cstdio>
#include<deque>
#include<algorithm>
using namespace std;
void shellSortPhase(int a[], int length, int gap) {
    int i;
    for (i = gap; i < length; ++i) {
        int value = a[i];
        int j;
        for (j = i - gap; j >= 0 && a[j] > value; j -= gap) a[j + gap] = a[j];
        a[j + gap] = value;
    }
}
void shellSort(int a[], size_t length) { 
    deque<int> gaps;
    for(size_t z=length/2;z>701;z/=2) gaps.push_front(z);
    static int cuira[] = {701,301,132,57,23,10,4,1};
    for(int z=0;z<sizeof(cuira)/sizeof(int);++z) gaps.push_front(cuira[z]);
    while(gaps.size()) {
        shellSortPhase(a, length, gaps.back());
        gaps.pop_back();
    }
}
const int N = 10000000;
int main() {
    int* arr = new int[N];
    for(int z=0;z<N;++z) arr[z] = rand();    
    shellSort(arr,N);
    for(int z=1;z<N;++z) if(arr[z]<arr[z-1]) printf("!");    
    delete[] arr;
}

// heap.cpp
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
const int N = 10000000;
int main() {
    int* arr = new int[N];
    for(int z=0;z<N;++z) arr[z] = rand();
    make_heap(arr,arr+N);
    sort_heap(arr,arr+N);
    for(int z=1;z<N;++z) if(arr[z]<arr[z-1]) printf("!");
    delete[] arr;
}

// merge.cpp
#include<vector>
#include<string>
#include<algorithm>
#include<cstdio>
using namespace std;
void merge_sort( int* beg, int* end) {
    if (end - beg > 1)  {
        int* mid = beg + (end - beg) / 2;
        merge_sort(beg, mid);
        merge_sort(mid, end);
        inplace_merge(beg, mid, end);
    }
}
const int N = 10000000;
int main() {
    int* arr = new int[N];
    for(int z=0;z<N;++z) arr[z] = rand();
    merge_sort(arr,arr+N);
    for(int z=1;z<N;++z) if(arr[z]<arr[z-1]) printf("!");
    delete[] arr;
}

The benchmark result for 10M items:

$ g++ intro.cpp ; time ./a.out 
real    0m2.515s
user    0m2.503s
sys     0m0.007s

$ g++ comb.cpp ; time ./a.out 
real    0m3.457s
user    0m3.443s
sys     0m0.007s

$ g++ shell.cpp ; time ./a.out 
real    0m4.109s
user    0m4.103s
sys     0m0.003s

$ g++ heap.cpp ; time ./a.out 
real    0m4.478s
user    0m4.470s
sys     0m0.003s

$ g++ merge.cpp ; time ./a.out 
real    0m3.748s
user    0m3.743s
sys     0m0.007s

Result with -O2 flag:

$ g++ -O2 intro.cpp ; time ./a.out 
real    0m0.806s
user    0m0.797s
sys     0m0.007s

$ g++ -O2 comb.cpp ; time ./a.out 
real    0m1.421s
user    0m1.417s
sys     0m0.000s

$ g++ -O2 shell.cpp ; time ./a.out 
real    0m1.959s
user    0m1.950s
sys     0m0.003s

$ g++ -O2 heap.cpp ; time ./a.out 
real    0m2.373s
user    0m2.357s
sys     0m0.010s

$ g++ -O2 merge.cpp ; time ./a.out
real    0m1.384s
user    0m1.360s
sys     0m0.017s

As we could see both are quite good enough, at par with some O(n log n) sorting algorithms.

Just for comparison let's compare with O(n^2) sorting algorithms, with lower number of items:

// sel.cpp
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
void selSort(int a[], size_t length) {
    for(size_t z=0;z<length-1;++z) {
        size_t best = z;
        for(size_t y=z+1;y<length;++y) if(a[best]>a[y]) best = y;
        if(z!=best) swap(a[best],a[z]);
    }    
}
const int N = 200000;
int main() {
    int* arr = new int[N];
    for(int z=0;z<N;++z) arr[z] = rand();
    selSort(arr,N);
    for(int z=1;z<N;++z) if(arr[z]<arr[z-1]) printf("!");
    delete[] arr;
}

// bub.cpp
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
void bubSort(int a[], size_t length) {
    for(size_t z=length-1;z>0;--z) {
        for(size_t y=0;y<z;++y) if(a[y]>a[y+1]) swap(a[y],a[y+1]);
    }    
}
const int N = 200000;
int main() {
    int* arr = new int[N];
    for(int z=0;z<N;++z) arr[z] = rand();
    bubSort(arr,N);
    for(int z=1;z<N;++z) if(arr[z]<arr[z-1]) printf("!");
    delete[] arr;
}

// ins.cpp
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
void insSort(int a[], size_t length) {
    for(size_t z=1;z<length;++z) {
    int copy = a[z];    
    size_t y = z;
        for(;y>0 && a[y-1]>copy;--y) a[y] = a[y-1];
        a[y] = copy;
    }    
}
const int N = 200000;
int main() {
    int* arr = new int[N];
    for(int z=0;z<N;++z) arr[z] = rand();
    insSort(arr,N);
    for(int z=1;z<N;++z) if(arr[z]<arr[z-1]) printf("!");
    delete[] arr;
}

// bin-ins.cpp
#include<cstdlib>
#include<cstdio>
#include<algorithm>
using namespace std;
void binInsSort(int data[], int size) {
    int index = -1,i = 1,j;
    for(;i<size;i++) {
        int temp = data[i];
        int high = i,low = 0,mid;
        while(low <= high) {
            mid = (low + high) /2;
            if(temp < data[mid]) {
                high = mid - 1;
                index = mid;
            } else if (temp > data[mid]) {
                low = mid + 1;      
            } else if(data[mid] == temp) {
                index = mid;
                break; 
            } 
        }
        for(j = i;j > index;j--) data[j] = data[j-1];
        data[j] = temp;
    }   
}
const int N = 200000;
int main() {
    int* arr = new int[N];
    for(int z=0;z<N;++z) arr[z] = rand();
    binInsSort(arr,N);
    for(int z=1;z<N;++z) if(arr[z]<arr[z-1]) printf("!");
    delete[] arr;
}

The benchmark result for 200K items:

$ g++ -O2 bub.cpp ; time ./a.out 
real    0m54.837s
user    0m54.790s
sys     0m00.000s

$ g++ -O2 sel.cpp ; time ./a.out 
real    0m51.671s
user    0m51.623s
sys     0m00.000s

$ g++ -O2 ins.cpp ; time ./a.out
real    0m4.513s
user    0m4.507s
sys     0m0.000s

$ g++ -O2 bin-ins.cpp ; time ./a.out 
real    0m3.736s
user    0m3.730s
sys     0m0.000s

The benchmark for 500K items:

$ g++ -O2 ins.cpp ; time ./a.out 
real    0m31.179s
user    0m31.137s
sys     0m00.003s

$ g++ -O2 bin-ins.cpp ; time ./a.out 
real    0m24.109s
user    0m24.087s
sys     0m00.000s


Apparently I was wrong, till recently I thought that SelectionSort is faster than InsertionSort (because of lower number of write/swap), but now I know that it doesn't..

2015-01-27

Vivaldi: New Chromium-based Web Browser

So today a new web browser, another chromium-based released, the name is Vivaldi. The review? first thing: Ctrl+Enter doesn't work, in another browser its usually for appending ".com" and go! Ctrl+L (location bar), Ctrl+H (history), Ctrl+J (download) works fine. Opening many tabs lags a lot, maybe because of their skin. You can install it on Windows, Mac, UbuntuFedora, also on ArchLinux using this command:
yaourt -Sy vivaldi



So, how about their javascript performance? Here's the result of SunSpider benchmark

Vivaldi 1.0.83.38 (Developer Build) stable
============================================
RESULTS (means and 95% confidence intervals)
--------------------------------------------
Total:                 228.3ms +/- 1.3%
--------------------------------------------

  3d:                   43.1ms +/- 3.1%
    cube:               13.0ms +/- 4.5%
    morph:              17.5ms +/- 2.9%
    raytrace:           12.6ms +/- 4.0%

  access:               17.6ms +/- 2.8%
    binary-trees:        2.0ms +/- 0.0%
    fannkuch:            7.9ms +/- 5.1%
    nbody:               4.0ms +/- 0.0%
    nsieve:              3.7ms +/- 9.3%

  bitops:               13.2ms +/- 3.4%
    3bit-bits-in-byte:   1.2ms +/- 25.1%
    bits-in-byte:        3.0ms +/- 0.0%
    bitwise-and:         4.1ms +/- 5.5%
    nsieve-bits:         4.9ms +/- 4.6%

  controlflow:           2.3ms +/- 15.0%
    recursive:           2.3ms +/- 15.0%

  crypto:               16.7ms +/- 4.1%
    aes:                 6.5ms +/- 5.8%
    md5:                 5.2ms +/- 8.7%
    sha1:                5.0ms +/- 0.0%

  date:                 23.3ms +/- 3.2%
    format-tofte:       12.1ms +/- 1.9%
    format-xparb:       11.2ms +/- 6.6%

  math:                 23.2ms +/- 3.8%
    cordic:              4.9ms +/- 4.6%
    partial-sums:       14.9ms +/- 1.5%
    spectral-norm:       3.4ms +/- 20.3%

  regexp:                8.1ms +/- 2.8%
    dna:                 8.1ms +/- 2.8%

  string:               80.8ms +/- 1.8%
    base64:              8.4ms +/- 4.4%
    fasta:              12.2ms +/- 2.5%
    tagcloud:           26.8ms +/- 2.8%
    unpack-code:        23.2ms +/- 3.2%
    validate-input:     10.2ms +/- 3.0%
Firefox 35.0
============================================
RESULTS (means and 95% confidence intervals)
--------------------------------------------
Total:                 195.3ms +/- 1.3%
--------------------------------------------

  3d:                   32.0ms +/- 3.2%
    cube:               12.1ms +/- 5.9%
    morph:               6.6ms +/- 5.6%
    raytrace:           13.3ms +/- 3.6%

  access:               19.0ms +/- 6.4%
    binary-trees:        3.9ms +/- 10.4%
    fannkuch:            7.8ms +/- 8.4%
    nbody:               3.6ms +/- 10.3%
    nsieve:              3.7ms +/- 13.0%

  bitops:               11.4ms +/- 3.2%
    3bit-bits-in-byte:   1.1ms +/- 20.5%
    bits-in-byte:        2.7ms +/- 12.8%
    bitwise-and:         2.5ms +/- 15.1%
    nsieve-bits:         5.1ms +/- 4.4%

  controlflow:           2.8ms +/- 10.8%
    recursive:           2.8ms +/- 10.8%

  crypto:               19.2ms +/- 3.4%
    aes:                 9.6ms +/- 5.2%
    md5:                 4.9ms +/- 4.6%
    sha1:                4.7ms +/- 7.3%

  date:                 22.2ms +/- 3.0%
    format-tofte:        9.8ms +/- 3.1%
    format-xparb:       12.4ms +/- 4.0%

  math:                 15.5ms +/- 2.4%
    cordic:              3.1ms +/- 7.3%
    partial-sums:       10.2ms +/- 3.0%
    spectral-norm:       2.2ms +/- 13.7%

  regexp:                9.0ms +/- 3.7%
    dna:                 9.0ms +/- 3.7%

  string:               64.2ms +/- 2.6%
    base64:              8.0ms +/- 9.4%
    fasta:               8.6ms +/- 4.3%
    tagcloud:           17.2ms +/- 3.3%
    unpack-code:        21.5ms +/- 3.6%
    validate-input:      8.9ms +/- 8.0%
Opera 26.0.1656.60
============================================
RESULTS (means and 95% confidence intervals)
--------------------------------------------
Total:                 235.4ms +/- 1.6%
--------------------------------------------

  3d:                   46.4ms +/- 7.3%
    cube:               13.7ms +/- 4.3%
    morph:              19.7ms +/- 12.7%
    raytrace:           13.0ms +/- 6.9%

  access:               17.9ms +/- 6.1%
    binary-trees:        1.8ms +/- 16.7%
    fannkuch:            8.2ms +/- 5.5%
    nbody:               4.0ms +/- 11.9%
    nsieve:              3.9ms +/- 10.4%

  bitops:               12.7ms +/- 4.6%
    3bit-bits-in-byte:   1.3ms +/- 26.6%
    bits-in-byte:        3.0ms +/- 0.0%
    bitwise-and:         4.1ms +/- 5.5%
    nsieve-bits:         4.3ms +/- 8.0%

  controlflow:           2.1ms +/- 10.8%
    recursive:           2.1ms +/- 10.8%

  crypto:               17.7ms +/- 6.6%
    aes:                 6.9ms +/- 7.6%
    md5:                 5.4ms +/- 14.2%
    sha1:                5.4ms +/- 6.8%

  date:                 24.7ms +/- 3.6%
    format-tofte:       12.7ms +/- 2.7%
    format-xparb:       12.0ms +/- 7.4%

  math:                 22.8ms +/- 2.9%
    cordic:              5.0ms +/- 9.5%
    partial-sums:       15.0ms +/- 3.9%
    spectral-norm:       2.8ms +/- 10.8%

  regexp:                8.0ms +/- 4.2%
    dna:                 8.0ms +/- 4.2%

  string:               83.1ms +/- 1.4%
    base64:              8.8ms +/- 10.0%
    fasta:              12.7ms +/- 3.8%
    tagcloud:           28.5ms +/- 3.4%
    unpack-code:        23.1ms +/- 3.1%
    validate-input:     10.0ms +/- 0.0%
Chromium 39.0.2171.99 (64-bit)
============================================
RESULTS (means and 95% confidence intervals)
--------------------------------------------
Total:                 242.2ms +/- 2.2%
--------------------------------------------

  3d:                   46.6ms +/- 8.8%
    cube:               13.5ms +/- 5.1%
    morph:              20.7ms +/- 16.3%
    raytrace:           12.4ms +/- 5.6%

  access:               18.5ms +/- 4.2%
    binary-trees:        2.2ms +/- 13.7%
    fannkuch:            8.1ms +/- 6.5%
    nbody:               4.2ms +/- 7.2%
    nsieve:              4.0ms +/- 8.4%

  bitops:               13.0ms +/- 3.7%
    3bit-bits-in-byte:   1.5ms +/- 25.1%
    bits-in-byte:        2.9ms +/- 7.8%
    bitwise-and:         3.9ms +/- 5.8%
    nsieve-bits:         4.7ms +/- 7.3%

  controlflow:           2.0ms +/- 0.0%
    recursive:           2.0ms +/- 0.0%

  crypto:               17.8ms +/- 5.9%
    aes:                 6.8ms +/- 8.3%
    md5:                 5.4ms +/- 9.3%
    sha1:                5.6ms +/- 17.2%

  date:                 22.4ms +/- 2.2%
    format-tofte:       11.8ms +/- 5.6%
    format-xparb:       10.6ms +/- 4.7%

  math:                 23.6ms +/- 2.6%
    cordic:              4.9ms +/- 4.6%
    partial-sums:       15.4ms +/- 3.2%
    spectral-norm:       3.3ms +/- 14.6%

  regexp:                8.0ms +/- 0.0%
    dna:                 8.0ms +/- 0.0%

  string:               90.3ms +/- 4.8%
    base64:              8.5ms +/- 12.1%
    fasta:              11.2ms +/- 5.0%
    tagcloud:           34.8ms +/- 4.9%
    unpack-code:        26.0ms +/- 18.5%
    validate-input:      9.8ms +/- 5.8%

Javascript speed in latest browser doesn't really matter now, they are already blazing fast.

2015-01-26

PHP/HHVM vs Go vs NodeJs BubbleSort Benchmark

So, I wonder about how good HHVM now, the code was taken from this post. My setup is 64-bit Linux 3.18.2-1, AMD A8-6600K, 16 GB RAM, Non-SSD disk, here's the best result of each implementation:

PHP 5.6.4

$ time php bench.php 
Array
(
    [0] => 1
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 3
    [5] => 4
    [6] => 5
    [7] => 12
    [8] => 52
    [9] => 92
    [10] => 424
    [11] => 4124
)
2.3711581230164
real    0m2.383s
user    0m2.373s
sys     0m0.010s

HHVM 3.5.0

$ time hhvm -v Eval.Jit=true bench.php 
Array
(
    [0] => 1
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 3
    [5] => 4
    [6] => 5
    [7] => 12
    [8] => 52
    [9] => 92
    [10] => 424
    [11] => 4124
)
0.13958597183228
real    0m0.414s
user    0m0.247s
sys     0m0.033s

Go 1.4.1
And yes, I include the compile time also for fairness.

$ rm bench; time(go build bench.go && ./bench)
removed ‘bench’
[1 1 2 3 3 4 5 12 52 92 424 4124]
23.027575ms
real    0m0.191s
user    0m0.150s
sys     0m0.033s

$ time ./bench 
[1 1 2 3 3 4 5 12 52 92 424 4124]
22.757741ms
real    0m0.024s
user    0m0.023s
sys     0m0.000s

NodeJS 0.10.35

$ time node bench.js
[ 1, 1, 2, 3, 3, 4, 5, 12, 52, 92, 424, 4124 ]
42

real    0m0.065s
user    0m0.060s
sys     0m0.003s

From what we could see (run duration - actual duration):
Go: 22ms - 24ms
NodeJS: 42ms - 65ms
Go (with compile duration included): 23ms - 191ms
HHVM: 139ms - 414ms
PHP2371ms - 2383ms