Monthly Archive: November 2011

Nov 28 2011

Mengurutkan Bilangan dengan Selection Sort

Untuk mengurutkan sekumpulan bilangan, dapat dilakukan dengan berbagai cara (algoritma), misalnya bubble sort, selection sort, merge sort, quick sort. Di bawah ini akan dijelaskan cara mengurutkan sekumpulan bilangan menggunakan selection sort.

Dalam selection sort ini kita memilih (select) bilangan terkecil, kemudian menempatkannya di awal. Kemudian memilih bilangan terkecil selanjutnya (terkecil kedua), dan menempatkannya di posisi setelah awal (posisi kedua). Berikutnya memilih bilangan terkecil ketiga, dan menempatkannya di posisi ketiga. Begitu seterusnya.

Misalnya diberikan sekumpulan bilangan berikut:

 3   8   5   7   2   3   6   8   0   4

Maka cara mengurutkannya seperti ini.

Pertama, cari bilangan yang paling kecil dari paling kiri (posisi 1):

 3   8   5   7   2   3   6   8   0   4
 --------------------------------|

Pindahkan bilangan tersebut ke depan (posisi 1). Bilangan yang ada di posisi 1 tersebut dipindahkan ke posisi bilangan terkecil tadi (istilahnya swap = tukar tempat):

[0]  8   5   7   2   3   6   8  [3]  4

Maka posisi 1 sudah berisi bilangan yang tepat.

Selanjutnya, cari bilangan yang paling kecil berikutnya. Kali ini, tidak dari posisi 1 (karena di posisi tersebut sudah berisi bilangan yang tepat), tetapi cari dari posisi 2:

 0   8   5   7   2   3   6   8   3   4
     ------------|

Swap bilangan tersebut ke posisi 2:

 0  [2]  5   7  [8]  3   6   8   3   4

Maka posisi 2 sudah berisi bilangan yang tepat.

Selanjutnya, cari bilangan yang paling kecil berikutnya. Kali ini, dari posisi 3:

 0   2   5   7   8   3   6   8   3   4
         ------------|

Swap bilangan tersebut ke posisi 3:

 0   2  [3]  7   8  [5]  6   8   3   4

Maka posisi 3 sudah berisi bilangan yang tepat.

Selanjutnya cari bilangan yang paling kecil berikutnya dari posisi 4:

 0   2   3   7   8   5   6   8   3   4
             --------------------|

Kemudian swap:

 0   2   3  [3]  8   5   6   8  [7]  4

Selanjutnya dari posisi 5:

 0   2   3   3   8   5   6   8   7   4
                 --------------------|

Hasil swap:

 0   2   3   3  [4]  5   6   8   7  [8]

Selanjutnya dari posisi 6:

 0   2   3   3   4   5   6   8   9   8
                     |

Karena bilangan terkecil berikutnya sudah terletak di posisinya yang sesuai, maka tidak perlu dilakukan swap.

Selanjutnya dari posisi 7:

 0   2   3   3   4   5   6   8   9   8
                         |

Ini juga tidak perlu melakukan swap.

Selanjutnya dari posisi 8:

 0   2   3   3   4   5   6   8   9   8
                             |

Tidak perlu swap.

Selanjutnya dari posisi 9 yang merupakan posisi terakhir. Setelah mencari bilangan terkecil dari posisi ini dan melakukan swap, kita tidak perlu melanjutkan pencarian ke posisi 10. Pada posisi tersebut sudah pasti berisi bilangan terbesar yang merupakan hasil swap-swap sebelumnya.

 0   2   3   3   4   5   6   8   9   8
                                 ----|

Hasil swap terakhir (hasil ini sudah terurut):

 0   2   3   3   4   5   6   8  [8] [9]

Berikut adalah contoh implementasi algoritma di atas dalam bahasa C++:

#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
    int N;
    cout << "N = ";
    cin >> N;

    int bilangan[N];
    cout << "bilangan (pisah dgn spasi) = ";
    for (int i = 0; i < N; i++) {
        cin >> bilangan[i];
    }

    // selection sort
    for (int i = 0; i < N - 1; i++) {
        // cari yg paling minimum
        int posisiTerkecil = i;
        for (int j = i + 1; j < N; j++) {
            if (bilangan[j] < bilangan[posisiTerkecil]) {
                posisiTerkecil = j;
            }
        }

        // swap ke depan (kalo memang perlu dilakukan swap)
        if (posisiTerkecil != i) {
            int sementara = bilangan[i];
            bilangan[i] = bilangan[posisiTerkecil];
            bilangan[posisiTerkecil] = sementara;
        }
    }

    cout << "hasil = ";
    for (int i = 0; i < N; i++) {
        cout << bilangan[i] << " ";
    }

    cout << endl;

    // system("pause");
}

Dan berikut merupakan contoh implementasi dalam Java:

import java.util.Scanner;

public class SelectionSort {

    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);

        System.out.print("N = ");
        int N = sc.nextInt();

        System.out.print("bilangan (pisah dgn spasi) = ");
        int[] bilangan = new int[N];
        for (int i = 0; i < N; i++) {
            bilangan[i] = sc.nextInt();
        }

        // selection sort
        for (int i = 0; i < N - 1; i++) {
            // cari bilangan terkecil
            int posisiTerkecil = i;
            for (int j = i + 1; j < N; j++) {
                if (bilangan[j] < bilangan[posisiTerkecil]) {
                    posisiTerkecil = j;
                }
            }

            // swap (jika memang harus di-swap)
            if (posisiTerkecil != i) {
                int sementara = bilangan[i];
                bilangan[i] = bilangan[posisiTerkecil];
                bilangan[posisiTerkecil] = sementara;
            }
        }

        System.out.print("hasil = ");
        for (int i = 0; i < N; i++) {
            System.out.print(bilangan[i] + " ");
        }
        System.out.println();
    }

}

  • Facebook
  • Twitter
  • Delicious
  • Digg
  • Google Buzz
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Permanent link to this article: http://www.muhammadalvin.net/2011/11/mengurutkan-bilangan-dengan-selection-sort/

Nov 26 2011

Artechno Festival Programming Competition – Monyet dan Pisang (H)

Saya mendapatkan ide soal ini dari soal ACORN untuk ACM/ICPC Asia Regional Contest 2007 Singapore. Ketika itu, USU mengirimkan dua tim untuk acara ini. Tim pertama terdiri dari saya, Alfarisi, Surya Wijaya, dan tim kedua terdiri dari Izhari Ishak Aksa, Ronny Silitonga, Jefri Umar (sebenarnya tim kami yang merupakan tim kedua :D ). Tim kami tidak berhasil menyelesaikan soal tersebut, sementara tim satunya berhasil. Setelah kembali ke tanah air, saya berhasil menyelesaikannya. Kegagalan ini membuat saya selalu teringat dengan soal tersebut. Pelajaran berharga memang dari pengalaman, pengalaman adalah guru terbaik. Begitu kata teman saya – Yayan – ketika saya berbagi pengalaman ini.

Alice dan Bob merupakan peneliti yang sedang melakukan percobaan mutasi gen. Alice melakukan percobaannya terhadap pohon pisang, sehingga beberapa pohon pisang dapat tumbuh dengan ketinggian yang sama dan memiliki buah di berbagai titik di sepanjang pohon tersebut. Sementara Bob melakukan percobaannya terhadap monyet, sehingga monyet tersebut dapat menyelesaikan permasalahan dengan algoritma tertentu.

Alice dan Bob tinggal bersebelahan. Rumah keduanya memiliki halaman yang hanya terpisah dinding yang cukup tinggi. Di halaman rumah itulah keduanya melakukan percobaannya. Suatu hari, seekor monyet dari halaman rumah Bob secara tidak sengaja memanjat dinding tersebut dan melihat beberapa pohon pisang yang ada di rumah Alice. Melihat banyaknya pisang yang tersebar di pohon-pohon tersebut, monyet tersebut tergoda untuk mengambilnya.

Dari atas dinding, monyet hanya bisa melompat ke salah satu pohon. Selanjutnya ia harus menuruni pohon tersebut sambil mengambil pisang yang dilewatinya. Saat menuruni pohon, ia bisa turun lurus ke bawah sejauh 1 meter atau pindah ke pohon tepat di sebelah kiri atau kanannya sambil turun sejauh 2 meter.

Tentukan berapa jumlah pisang terbanyak yang dapat diambil oleh monyet tersebut.

Sebagai contoh, Alice memiliki 3 pohon pisang dengan ketinggian 5 meter. Pohon pertama memiliki 5 pisang di ketinggian 2 meter, 15 pisang di ketinggian 4 meter, dan 5 pisang di ketinggian 5 meter. Pohon kedua memiliki 20 pisang di ketinggian 2 dan 3 meter. Pohon ketiga memiliki 15 pisang di ketinggian 4 meter. Jika digambarkan menjadi seperti berikut:

Jika monyet memilih pohon pertama lalu turun lurus ke bawah, maka ia akan memperoleh 5 + 15 + 5 = 25 pisang. Jika memilih pohon kedua lalu turun lurus ke bawah, maka ia akan memperoleh 20 + 20 = 40 pisang. Jika memilih pohon ketiga lalu turun lurus ke bawah, maka ia akan memperoleh 15 pisang.

Jika monyet memilih pohon pertama lalu turun ke ketinggian 4 meter di pohon yang sama, kemudian pindah ke pohon kedua ke ketinggian 2 meter, maka ia akan memperoleh 5 + 15 + 20 = 40 pisang.

Tetapi jika monyet memilih pohon pertama, lalu pindah ke pohon kedua ke ketinggian 3 meter, kemudian turun terus ke bawah, maka ia akan memperoleh 5 + 20 + 20 = 45 pisang. Pada test case ini, 45 pisang adalah jumlah maksimum yang dapat diambil.

Ingat: Pindah pohon berarti turun 2 meter, dan monyet hanya bisa pindah ke pohon yang berada tepat di sebelah kiri atau kananya. Sebagai contoh, jika ada empat pohon dan monyet berada di pohon kedua, maka ia bisa pindah ke pohon pertama atau ketiga, tetapi tidak bisa pindah ke pohon keempat.

Input:
Input diawali oleh T (1 <= T <=1000) yang menunjukkan jumlah test case.

Setiap test case terdiri dari beberapa baris. Baris pertama berisi dua buah bilangan bulat N dan H (1 <= N, H <= 50), di mana N merupakan banyaknya pohon pisang setinggi H meter yang terdapat di halaman Alice. N baris berikutnya berisi H buah integer (X1 X2 X3 … XH di mana 0 <= Xi <= 100) yang menunjukkan letak dan jumlah pisang di setiap pohon. Integer pertama (X1) adalah jumlah pisang di ketinggian 1 meter, integer kedua (X2) adalah jumlah pisang di ketinggian 2 meter, integer ketiga (X3) adalah jumlah pisang di ketinggian 3 meter, dst.

Output:
Untik setiap test case, tampilkan jumlah maksimum pisang yang dapat diambil untuk test case tersebut.

Contoh input:
4
3 5
0 5 0 15 5
0 20 20 0 0
0 0 0 15 0
1 1
10
1 10
0 0 0 0 0 0 0 0 0 0
2 5
1 2 3 4 5
1 2 3 4 5

Contoh output:
45
10
0
15

———-

Cara penyelesaian soal ini mirip seperti soal Rute Maksimal (B). Jika pada soal tersebut, yang kita cari adalah maksimum untuk turun ke kiri atau ke kanan, maka pada soal ini yang kita cari adalah maksimum untuk:

  • turun lurus (1 langkah ke bawah)
  • turun ke kiri (2 langkah ke bawah)
  • turun ke kanan (2 langkah ke bawah)

Berikut ini merupakan contoh solusi dalam bahasa Java:

import java.util.Scanner;
import java.util.Arrays;

public class H {

    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);

        int nTC = sc.nextInt();
        while (nTC-- > 0) {
            int N = sc.nextInt();
            int H = sc.nextInt();

            int[][] pohon = new int[52][52]; // batasan pada soal: 1 <= N, H <= 50
            for (int i = 0; i <= N; i++) {
                Arrays.fill(pohon[i], 0);
            }

            for (int i = 1; i <= N; i++) {
                for (int j = 1; j <= H; j++) {
                    pohon[i][j] = sc.nextInt();
                }
            }

            int hasil = 0; // terbanyak di ketinggian H

            // mulai dari baris ke-2 dari bawah sampai paling atas
            for (int i = 2; i <= H; i++) {
                for (int j = 1; j <= N; j++) {
                    // cari turun yg optimmal!
                    int best = pohon[j][i] + pohon[j][i - 1]; // turun lurus
                    if (j - 1 >= 1 && i - 2 >= 1) {
                        best = Math.max(best, pohon[j][i] + pohon[j - 1][i - 2]); // turun ke kiri
                    }
                    if (j + 1 <= N && i - 2 >= 1) {
                        best = Math.max(best, pohon[j][i] + pohon[j + 1][i - 2]); // turun ke kanan
                    }

                    pohon[j][i] = best; // update!

                    if (i == H) {
                        hasil = Math.max(hasil, pohon[j][i]); // update hasil
                    }
                }
            }

            System.out.println(hasil);
        }
    }

}

Input dan output yang digunakan oleh juri bisa dilihat di sini.

———-

Untuk soal ACORN, karena time limit untuk soalnya hanya 3 detik, maka tidak bisa menggunakan looping 3 tingkat (pertama untuk mengiterasi setiap ketinggian, kedua untuk mengiterasi setiap pohon, ketiga untuk mengiterasi arah turun). Saya sudah mencoba solusi tersebut dan dinyatakan No – Time Limit Exceeded. Agar mendapatkan Yes/Accepted, harus menggunakan teknik dynamic programming, di mana kita menyimpan maksimum dari tiap-tiap ketinggian di tabel DP (ada juga yang menyebutnya tabel memo). Ini akan meng-eliminasi looping ketiga dengan cara melihat nilai maksimum untuk ketinggian tertentu ke tabel DP tersebut.

  • Facebook
  • Twitter
  • Delicious
  • Digg
  • Google Buzz
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Permanent link to this article: http://www.muhammadalvin.net/2011/11/artechno-festival-programming-competition-monyet-dan-pisang/

Nov 26 2011

Artechno Festival Programming Competition – Hitung Prima (G)

Soal dibuat oleh Izhari Ishak Aksa.

Diberikan sebuah deretan bilangan bulat, jumlahkan bilangan-bilangan pada deretan tersebut yang merupakan bilangan prima (bilangan yang pembaginya hanya 1 dan bilangan itu sendiri). Tentukan pada bilangan prima ke berapa pada deretan tersebut ketika hasil penjumlahannya melebihi 100. Asumsikan bahwa untuk setiap kasus, pasti akan terdapat jawaban untuk hasil penjumlahan melebihi 100.

Input:
Input diawali oleh T (1 <= T <= 1000) yakni banyaknya test case.
Untuk setiap test case, diawali bilangan bulat N yang menunjukkan banyaknya bilangan pada deretan bilangan bulat. N baris berikutnya, berisi bilangan bulat X (0 < X < 1000) yaitu bilangan bulat yang dimaksud dalam deretan tersebut.

Output:
Untuk setiap test case, tampilkan sebuah bilangan bulat yang menunjukkan bilangan prima ke berapa saat hasil penjumlahannya melebihi 100.

Contoh input:
2
6
10
7
41
32
43
17
2
9
101

Contoh output:
4
1

Catatan:
Contoh input baris ke-8 tertulis 2, seharusnya 17.

———-

Pada soal ini, diminta menjumlahkan setiap bilangan prima yang ditemukan. Saat penjumlahan tersebut menghasilkan jumlah yang lebih besar dari 100, maka hentikan penjumlahan dan tampilkan pada penjumlahan ke berapa yang menghasilkan jumlah lebih dari 100 tersebut.

Berikut ini merupakan contoh solusi menggunakan bahasa Java:

import java.util.Scanner;
import java.util.Arrays;

public class G {

    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);

        // sieve of eratosthenes
        boolean[] prima = new boolean[1002]; // batasan input: 0 < X < 1000
        Arrays.fill(prima, true);
        prima[0] = prima[1] = false;
        for (int i = 2; i * i <= 1000; i++) {
            for (int j = 2; (j * i) <= 1000; j++) {
                prima[j * i] = false;
            }
        }

        int nTC = sc.nextInt();
        while (nTC-- > 0) {
            int N = sc.nextInt();

            int[] bilangan = new int[N];
            for (int i = 0; i < N; i++) {
                bilangan[i] = sc.nextInt();
            }

            int ke = 0;
            int jumlah = 0;
            for (int i = 0; i < N; i++) {
                if (prima[bilangan[i]]) {
                    jumlah += bilangan[i];
                    ke++;

                    if (jumlah > 100) {
                        break;
                    }
                }
            }

            System.out.println(ke);
        }
    }

}

Input dan output yang digunakan oleh juri dapat dilihat di sini.

  • Facebook
  • Twitter
  • Delicious
  • Digg
  • Google Buzz
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Permanent link to this article: http://www.muhammadalvin.net/2011/11/artechno-festival-programming-competition-hitung-prima/

Nov 26 2011

Artechno Festival Programming Competition – Lingkaran dan Persegi (F)

Ini merupakan variasi soal Porseni V Imilkom USU 2010, di mana yang diminta pada soal ini hanya luas lingkaran paling dalam, tidak semua lingkaran seperti yang diminta pada soal untuk Porseni.

Diberikan masukan S yaitu panjang sisi persegi dan N yaitu banyaknya persegi dan lingkaran, hitung luas lingkaran yang terletak paling dalam. Sebagai contoh, jika diberikan S = 10 dan N = 1, maka akan terdapat 1 persegi dan lingkaran seperti berikut:

Luas yang akan dihitung adalah bagian yang berwarna biru. Dari gambar di atas, diameter lingkaran sama dengan panjang sisi persegi, yaitu 10, sehingga luas lingkaran berwarna biru tersebut adalah 78.539816 (luas lingkaran = π r2 = ¼ π d2, di mana π = 3.1415926535897932).

Jika diberikan S = 10 dan N = 2, maka terdapat 2 persegi dan lingkaran seperti berikut:

Luas yang akan dihitung adalah bagian yang berwarna hijau.

Input:
Input diawali oleh T (1 <= T <= 1000) yakni banyaknya test case.
T baris berikutnya (di mana setiap baris merupakan sebuah test case) berisi dua bilangan bulat S (1 <= S <= 10000) dan N (1 <= N <= 100).

Output:
Untuk setiap test case, tampilkan luas lingkaran yang diminta (lingkaran paling dalam) dalam 6 angka desimal. Lakukan pembulatan bila perlu.

Contoh input:
3
10 1
10 2
14 4

Contoh output:
78.539816
39.269908
19.242255

———-

Untuk N = 1, akan terdapat persegi dan lingkaran sebagai berikut:

Luas yang akan dihitung adalah bagian yang berwarna biru. Dari gambar di atas, jari-jari lingkaran (R1) adalah ½ panjang sisi persegi (S1), yaitu 5, sehingga luas lingkaran (L) tersebut adalah sebagai berikut:

L=\pi r^{2}
L=\pi 5^{2}
L=78.539816

Jika N = 2, maka akan terdapat 2 buah persegi dan 2 buah lingkaran seperti berikut:

Luas yang akan dihitung adalah bagian yang berwarna hijau. Untuk itu, kita perlu mengetahui jari-jari atau diameter lingkaran berwarna hijau. Perhatikan gambar berikut:

Jari-jari lingkaran berwarna hijau adalah R2. Selanjutnya perhatikan gambar berikut:

Dari gambar tersebut, diperoleh persamaan berikut:

(R_{1})^{2}=(R_{2})^{2}+(R_{2})^{2}
(R_{1})^{2}=2((R_{2})^{2})
(R_{2})^{2}=\frac{1}{2}((R_{1})^{2})
R_{2}=\sqrt{\frac{1}{2}((R_{1})^{2})}
R_{2}=R_{1}\sqrt{\frac{1}{2}}

Karena kita sudah memiliki R1 (yaitu 5), maka R2 bisa diperoleh:

R_{2}=R_{1}\sqrt{\frac{1}{2}}
R_{2}=5\sqrt{\frac{1}{2}}
R_{2}=3.535534

Sehingga luas lingkaran berwarna hijau adalah:

L=\pi (R_{2})^{2}
L=\pi (3.536)^{2}
L=39.269908

Untuk N selanjutnya (2, 3, 4, …), dapat diturunkan rumus yang sama:

R_{N}=R_{N-1}\sqrt{\frac{1}{2}}

Karena sudah memperoleh jari-jari, luas lingkaran dapat dihitung.

Berikut ini merupakan contoh solusi dalam bahasa Java:

import java.util.Scanner;

public class F {

    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);

        int nTC = sc.nextInt();
        while (nTC-- > 0) {
            int S = sc.nextInt();
            int N = sc.nextInt();

            double R = 0.5 * (double) S; // 1 persegi dan lingkaran
            for (int i = 2; i <= N; i++) {
                R = R * Math.sqrt(0.5); // 2, 3, 4, ... persegi dan lingkaran
            }

            double L = Math.PI * Math.pow(R, 2);
            System.out.println(String.format("%.6f", L));
        }
    }

}

Input dan output yang digunakan oleh juri bisa dilihat di sini.

  • Facebook
  • Twitter
  • Delicious
  • Digg
  • Google Buzz
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Permanent link to this article: http://www.muhammadalvin.net/2011/11/artechno-festival-programming-competition-lingkaran-dan-persegi/

Nov 25 2011

Mengenal Ajax

Ajax merupakan singkatan dari Asynchronous JavaScript and XML. Dari kepanjangan tersebut, terdapat 3 bagian penting yaitu asychronous, javascript dan XML.

Asynchronous dikenal juga dengan istilan non-blocking. Selama proses asychronous terjadi, proses yang lain (biasanya proses utama) tidak akan terganggu dan tetap dapat berjalan. Dalam Ajax, ini dilakukan dengan melakukan request di background, sehingga apa yang sedang kita lakukan di sebuah halaman web tidak akan terganggu dengan request yang dilakukan oleh Ajax tersebut.

JavaScript merupakan teknologi yang digunakan dalam implementasi Ajax. Ajax itu sendiri bukan merupakan suatu bahasa pemrograman baru.

XML merupakan bentuk data yang digunakan dalam Ajax. Saat ini, lebih populer menggunakan data dalam bentuk JSON. Bentuk data yang digunakan tidak ada batasan, boleh juga teks biasa ataupun HTML.

Apa yang mesti saya ketahui agar dapat memahami Ajax?

Read the rest of this entry »

  • Facebook
  • Twitter
  • Delicious
  • Digg
  • Google Buzz
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS

Permanent link to this article: http://www.muhammadalvin.net/2011/11/mengenal-ajax/

Older posts «