Kata Spiral
Untuk menyambut semakin dekatnya Olimpiade sains Nasional, saya pengen berbagi sedikit solusi soal OSN Komputer. Semoga bisa membantu adik2 sekalian yang hendak berkompetisi di OSN nanti. Kali ini saya mau membahas soal favorit saya, Kata Spiral, soal OSN 2005.
Deskripsi
Suatu sistem sandi menyandikan kalimat yang diberikan dalam bantuk spiral.
Penyusunan tersebut dilakukan membentuk matriks spiral yang dimulai pusat matriks
1 karakter pertama, lalu 1 karakter berikutnya ke kanan, lalu 1 karakter berikutnya ke
bawah, lalu 2 karakter berikutnya ke kiri, lalu 2 karakter berikutnya ke atas, 3 karakter
berikutnya ke kanan, 3 karakter berikutnya ke bawah, dan seterusnya hingga semua
karakter dalam kalimat termasuk dalam spiral. Khususnya, karakter spasi di ganti
dengan “_” (underscore), dan jika ada baris/kolom tersisa setelah karakter terakhir
maka elemen-elemen matriks diisi juga dengan “_” (underscore) tsb. Misalnya
kalimat “Seluruh peserta OSN bidang komputer harus mengerjakan soal-soal sebaikbaiknya
untuk mendapatkan peringkat terbaik.” Dikodekan kedalam matriks sebagai
berikut.
Program Penerjemah Bilangan
Ok, next program, pengeja bilangan.
Kebetulan, dulu temen saya pernah minta tolong dibuatkan program ini untuk tugas kuiahnya, jadi saya tinggal copy-paste
Bagaimana caranya membuat program untuk membaca digit angka ini?
Sebeumnya, mari kita analisis masalahnya dulu.
Disediakan bilangan yang tersusun dari m digit angka.
Kita lihat angka ini mulai dari yang paling kanan.
Untuk n>=0 berlaku lemma sebagai berikut :
- Digit ke 3n+1 (dari kanan) pasti diikuti kata “ribu”, “juta”, “milyar”, dst
KECUALI JIKA digit 3n+1 hingga digit 3n+3 bernilai ‘0′. - Digit ke 3n+2 pasti diikuti kata “puluh”, KECUALI :
- digit tersebut ‘0′
- digit ke 3n+2=’1′ dan digit ke 3n+1<>’0′ (karena menghasilkan angkabelasan)
- Digit ke 3n+3 pasti dikuti kata “ratus” KECUALI digit tersebut = ‘0′
- Karakter ‘1′ ditulis sebagai “satu” jika berada pada posisi 3n+1. KECUALI pada posisi ke 4 (ribuan), bisa ditulis sebagai “se” (’seribu’) jika dua digit didepannya (digit 5 dan 6) adalah ‘0′. Selain pada posisi itu dan posisi 3n+2, ‘1′ ditulis sebagai “se”.
- Jika karakter ‘1′ menempati posisi 3n+2, maka
- jika karakter dibelakangnya (3n+1) adalah ‘0′ maka kedua digit ditulis sebagai “se”+”puluh”
- jika karakter dibelakangnya (3n+1) bukan ‘0′ maka kedua digit ditulis sebagai “”+”belas”, kemudian ind dan i masing2 dikurangi 1
yang berarti kedua digit sudah diterjemahkan.
- Karakter ‘0′ tidak diterjemahkan.
Dari lemma-lemma diatas, terlihat bahwa blok seleksi/ logika akan sangat dominan dalam program ini. Pertama-tama kata-kata untuk menerjemahkan digit angka ini kita simpan dahulu dalam array. Dan untuk memudahan penerjemahan dan indexingnya (yup! kita akan bermain-main dengan index di sini
), angka ini kita baca dari yang paling kanan (atau lebih mudahnya, angkanya kita balik!). Oh, iya! Jangan lupa dengan special casenya yah! Hati-hati dengan angka 0 dan 1!
So, here it is listing yang saya buat
var pangkat3:array[0..4] of string=('','ribu ','juta ','milyar ','trilyun ');
//pangkat3 => kata untuk orde 10^3n
atrib:array[0..3] of string=('belas ','','puluh ','ratus ');
//atrib => untuk ratusan, puluhan dan belasan
angka:array[0..9] of string=('se','satu','dua','tiga',
'empat','lima','enam',
'tujuh','delapan','sembilan');
//angka => menerjemahkan tiap digit angka
inp:string;
//inp => angka yang akan diterjemahkan
ind:integer;
//ind => bernilai 1-3 untuk menyatakan digit ke 3n+ind
//berfungsi menentukan atrib yang akan digunakan
i,j:integer;
c:char;
begin
readln(inp);
i:=length(inp);
inp:='0'+inp; //mengatasi input '0'
while (inp<>'') and (inp[1]='0') do
begin
delete(inp,1,1);
end;
if inp='' then
begin
writeln('nol');
halt;
end;
i:=length(inp);
while i mod 3<>0 do //ditambah '0' sampai panjangnya kelipatan 3
begin //untuk mempermudah penulisan nantinya
inp:='0'+inp;
inc(i);
end;
ind:=3;
for j:=1 to i div 2 do //angka dibalik, biar gampang diproses
begin
c:=inp[j];
inp[j]:=inp[i+1-j];
inp[i+1-j]:=c;
end;
while i<>0 do
begin
{angka 1 biasa atau menimbulkan angka belasan?}
if inp[i]='1' then
if ind<>2 then
{pilih "se" atau "satu"?}
if ((ind=1) and (i<>4)) or
((i=4) and ((inp[5]<>'0') or (inp[6]<>'0'))) then
write(angka[1],' ')
else
write(angka[0])
else
begin
{angka belasan dan "sepuluh"}
if (inp[i-1]='0') then write(angka[0])
else
begin
if inp[i-1]='1' then write(angka[0],atrib[0])
else
begin
val(inp[i-1],j);
write(angka[j],atrib[0]);
end;
dec(i);
dec(ind);
end;
end
else
if inp[i]<>'0' then
begin
{angka-angka lainnya}
val(inp[i],j);
write(angka[j],' ');
end;
{ratus dan puluh}
if inp[i]<>'0' then write(atrib[ind]);
{ribu, juta, milyar}
if (ind=1) and ((inp[i]<>'0') or (inp[i+1]<>'0') or (inp[i+2]<>'0')) then
write(pangkat3[(i-1) div 3]);
dec(ind);
dec(i);
if ind=0 then ind:=3;
end;
writeln;
readln;
end.
Segitiga Pascal – part II
Karena banyaknya permintaan, saya coba buat coding untuk program Segitiga Pascal dalam C++. Mohon maaf, untuk
program dalam bahasa JAVA, saya belum bisa buat karena pemahaman OOP saya masih cetek dan lebih-lebih, laptop saya
yang sudah tuwa dan mulai rewel menolak untuk diinstall JDK T_T
Algoritmanya tidak jauh berbeda dengan program sebelumnya dalam bahasa Pascal. Hanya saja, untuk kemudahan, saya
gunakan array 2 dimensi saja. Listingnya sebegai berikut
#include <iostream.h>
int main(){
int n,i,j;
unsigned long long arr[101][101];
cin>>n;
for (i=1;i<=n;i++){
for (j=1;j<i;j++){
arr[i][j]=arr[i-1][j-1]+arr[i-1][j];
cout<<arr[i][j]<<’ ‘;
}
arr[i][i]=1;
cout<<arr[i][i]<<’\n’;
}
return 0;
}
Katanya, banyak jalan menuju Roma. Begitu pula dalam pemrograman. banyak algoritma yang bisa diterapkan untuk
menyelesaikan satu masalah. Berikut ini salah satu coding lain untuk membuat Segitiga Pascal. Masih mengunakan
bahasa C++, hanya dengan sedikit sentuhan STL dan trik minimalisasi memori (duuh, kayakya bahasanya ketinggian,
hehehe… :p ). Here they are
#include <iostream.h>
#include <vector.h>
int main(){
int n,i,j,tmp1,tmp2;
vector <unsigned long long> arr;
bool odd;
cin>>n;
arr.push_back(0);
arr.push_back(1);
if (n>=1) cout<<arr[1]<<’\n’;
for (i=2;i<=n;i++){
odd=i%2;
tmp1=0;
for (j=1;j<=i/2;j++){
tmp2=arr[j];
arr[j]=tmp1+arr[j];
tmp1=tmp2;
}
for (j=1;j<=i/2;j++) cout<<arr[j]<<’ ‘;
if (odd) {
arr.push_back(2*tmp1);
cout<<arr[i/2+1]<<’ ‘;
}
for (j=i/2;j>=1;j–) cout<<arr[j]<<’ ‘;
cout<<’\n’;
}
return 0;
}
Kira-kira demikianlah ![]()
semoga bisa membantu dan semoga tidak ngebug juga :p
Vector di C++. Array dinamis di Pascal???
Beberapa hari yang lalu, tumben lagi semangat coding. Mulai buka2 deh tutorial STL untuk C++. Kenapa STL? Karena konon katanya, STL C++ tuh isinya banyak tentang struktur data baru dan sintaks2 aneh lainnya. Bayangin aja, prosedur quicksort yang kalo koding di pascal bisa beberapa baris (rawan bug pula), bisa diselesaikan pake STL dengan hanya 1 baris sintaks, qsort().
Cukup sebel juga awalnya, kenapa di pascal kok gak bisa yah? Karena itu, terpaculah saya belajar STL. Yang pertama aku baca yaitu tentang vector. Vector nih bisa dibilang evolusinya array, atau aku sebut saja smart array. Kenapa? Antara lain, sifatnya sangat dinamis. vector ini bisa berkembang dan menyusut sewaktu-waktu dengan sintaks(atau mungkin lebih tepat disebut member, karena sepertinya vector itu sejenis class) yang simple. Sebut saja push_back(), yaitu menambahkan elemen baru sebagai elemen terakhir di vector, atau pop_back() yaitu menghapus/ memotong elemen terakhir dari vector. Dengan ini, kita bisa dengan mudah membuat dan mengolah struktur data , misal stack, tanpa harus repot memikirkan ukuran array. suatu vector juga dapat melaporkan ukurannya, yaitu dengan sintaks size(). Selain itu, masih banyak lagi member-member vector yang sangat amat berguna.
Dan ketika sedang terkagum-kagum dengan vector, esok harinya tiba-tiba Pak Janoe menjelaskan tentang deklarasi array dinamis di Pascal (????????).
Hah? ada ya?
Memang sih, cuma ada di beberapa compiler, Free Pascal misalnya. Tapi itu itu sudah cukup membuat saya shock. Deklarasinya mirip deklarasi array pada umumnya. Bedanya, ukuran array tidak ditentukan di awal, seperti ini :
var arr:array of integer;
Nah lo, ukurannya gimana? Ukuran array tersebut kemudian kita tentukan dengan sintaks
setlength(nama_array,ukuran);
Array dinamis ini pun bisa mengembang dan menyusut sewaktu-waktu, tentunya dengan menggunakan sintaks setlength beberapa kali. Bahkan, ketika arraynya kita perbesar, data yang kita masukkan sebelumnya tidak hilang!!
AArrgh!! Meringis hatiku! Coba aku tahu tentang array ini 2 tahun yang lalu! T_T
Hasil Olimpiade Sains Mahasiswa
Akhirnya, 13 Desember kemarin pengumuman resmi juara Olimpiade Sain Mahasiswa Yogyakarta keluar. Alhamdulillah dapet juara 1. Secara umum, perolehan juara di setiap bidang tampak didominasi oleh mahasiswa-mahasiswa UGM
Di bidang komputer sendiri pemenangnya adalah sebagai beriut :
1. Riza Oktavian, Ilmu Komuter UGM
2. Anugrah Galang P, Teknik Elektro UGM
3. Okie Primatyo, Teknik Elektro UGM
Yang menarik bagi saya, 2 teman sekontrakan saya yang juga mengikuti Olimpiade Sains Mahasiswa juga meraih juara di bidangnya masing-masing yaitu I Wayan Samayoga (Kedokteran Umum UGM), juara 3 bid Kimia dan Fajar Sofyantoro(Biologi UGM), juara 1 bid Biologi (perlu selametan se kontrakan nih ^_^).
Selamat kepada semua juara, semoga prestasi ini dapat menjadi pemacu untuk dapat berprestasi lebih tinggi di kemudian hari.
Perkalian Matriks
Soal 5 Olimpiade Sains Mahasiswa 2007, Yogyakarta.
Deskripsi Soal :
Diberikan sebuah perkalian matriks, P=A*B*C*D, dengan ordo/ ukuan masing-masing A(20X50), B(50X100), C(100X10), dan D(10X30). Ada beberapa cara melakukan perkalian matriks ini, dan tiap cara mempunyai jumlah operasi perkalian yang berbeda, antara lain :
1) P=(A*B)*C*D => (20*50*100)+(20*100*10)+(20*10*30) = 126000 perkalian
2) P=A*((B*C)*D) => (50*100*10)+(50*10*30)+(20*50*30) = 95000 perkalian
3) P=A*(B*C)*D => (50*100*10)+(20*50*10)+(20*10*30) = 66000 perkalian
Ternyata jumlah operasi perkalian terkecil yang mungkin terjadi adalah 66000 perkalian, yaitu dengan P=A*(B*C)*D. Buatlah program yang menerima input 2 baris. Baris pertama adalah jumlah matriks(N) dan baris kedua berisi N+1 bilangan asli yang menyatakan ukuran matriks pada perkalian. Program harus meng-outputkan jumlah opersi perkalian terkecildari perkalian matriks tersebut.
Game
Soal 4 Olimpiade Sains Mahasiswa 2007, Yogyakarta.
Deskripsi Soal :
Buatlah sebuah game 2 player antara Komputer Vs User dengan deskripsi game seperti berikut :
Ada dua buah kotak. Kotak pertama berisi sejumlah kelereng N. Secara bergantian, player 1 dan payer 2 memindahkan sejumlah kelereng dari kotak pertama ke kotak kedua dan tidak boleh melebihi jumlah maksimal pemindahan, M. M dijamin tidak melebih 10% dari total kelereng. Pemain yang berhasil memindahkan kelereng terakhir kali sehingga kotak pertama kosong, keluar sebagai pemenang.
Diberikan input N dan M. User memilih siapa yang menjadi player 1, komputer atau user, kemudian user menginputkan jumlah kelereng yang ingin dipindahkan setiap kali gilirannya. Program harus dibuat sehingga komputer selalu memenangkan game, kecuali jika player 1 adalah User dan User selalu mengambil langkah terbaik.
Tempat Pensil
Soal 3 Olimpiade Sains Mahasiswa 2007, Yogyakarta.
Deskripsi Soal :
Andi gemar mengoleksi pensil. Kian hari, koleksi pensilnya semakin banyak. Oleh karena itu dia berencana membeli tempat pensil baru di toko A untuk menampung N pensil koleksinya. Toko A menjual 2 jenis tempat pensil dengan harga dan kapasitas yang berbeda. Tempat pensil 1 berharga R1 dan dapat menyimpan J1 pensil, sedangkan tempat pensil 2 berharga R2 dan dapat menyimpan J2 pensil. Diberikan input N, R1, J1, R2, dan J2. Buatlah program yang mengoutputkan jumlah tempat pensil 1dan jumlah tempat pensil 2 yang harus dibeli Andi sehingga tempat pensil yang dibelinya tepat menampung N pensilnya. Jika tidak ada kombinasi sehingga tempat pensil yang dibelinya tepat menampung N pensil, maka outputkan ”Tidak jadi beli”
Segitiga Pascal
Soal 2 Olimpiade Sains Mahasiswa 2007, Yogyakarta.
Deskripsi Soal :
Buatlah program yang meminta input bilangan asli n dan mengoutputkan segitiga pascal dari baris 0 hingga baris n
Warna Dominan
Soal 1 Olimpiade Sains Mahasiswa 2007, Yogjakarta.
Deskripsi Soal :
Buatlah program yang menghasilkan sebuah matriks 5X6 yang elemennya adalah angka random 1 sampai 255. Outputkan juga warna dominan/ angka yang paling sering muncul dalam matriks tersebut. Jika ada lebih dari satu warna dominan, maka outputkanlah semua warna dominan. Jika tidak ada warna dominan, outputkan ”Tidak ada warna dominan”.