- Bahkan soal LeetCode yang sulit pun bisa diselesaikan jauh lebih mudah dengan memakai constraint solver
- Alih-alih dynamic programming yang kompleks atau algoritme buatan sendiri, kita bisa memanfaatkan constraint solver seperti MiniZinc untuk menyelesaikan masalah optimasi matematis dengan sederhana
- Bahasa pemrograman tradisional sulit mengekspresikan masalah optimasi matematis semacam ini, sehingga pendekatan berbasis kendala menjadi unggul
- Bahkan ketika muncul kasus pengecualian atau kendala tambahan, perubahan model pada constraint solver tetap minimal
- Kompleksitas runtime memang bisa lebih lambat daripada algoritme optimal yang ditulis langsung, tetapi dari sisi fleksibilitas dan produktivitas pengembangan pendekatan ini punya banyak keunggulan
Soal LeetCode yang Diselesaikan dengan Constraint Solver
Memilih alat yang tepat
-
Penulis mendapat soal 'coin change problem' pada wawancara kerja pertamanya setelah lulus kuliah
- Diberikan denominasi koin, tujuannya adalah mencari jumlah koin minimum yang diperlukan untuk memberikan kembalian sejumlah tertentu
- Penulis memakai algoritme greedy sederhana, tetapi itu tidak menjamin solusi optimal untuk semua kasus
- Jawaban yang benar adalah dynamic programming, tetapi karena gagal mengimplementasikannya, wawancara pun gagal
-
Namun, tanpa mengimplementasikan algoritme sendiri, masalah ini bisa diselesaikan dengan sangat mudah memakai constraint solver seperti MiniZinc
-
Contoh kode:
int: total; array[int] of int: values = [10, 9, 1]; array[index_set(values)] of var 0..: coins; constraint sum (c in index_set(coins)) (coins[c] * values[c]) == total; solve minimize sum(coins); -
Contohnya bisa langsung dijalankan secara online di MiniZinc
-
Solver akan menemukan solusi optimal secara bertahap
-
Beragam masalah optimasi/kepuasan
- Masalah optimasi matematis yang sering muncul di LeetCode dan sejenisnya—dengan fungsi objektif untuk dimaksimalkan/diminimalkan serta berbagai kendala—
sulit diselesaikan dalam bahasa pemrograman biasa karena perlu implementasi level rendah, tetapi sangat cocok untuk constraint solver - Misalnya, berbagai jenis masalah berikut termasuk dalam kategori ini
Contoh 1: masalah keuntungan saham maksimum
- 'Dari data harga saham dalam bentuk daftar, cari keuntungan maksimum yang bisa diperoleh dengan membeli sekali lalu menjual pada waktu sesudahnya'
- Secara tradisional memerlukan brute force O(n²) atau algoritme optimal O(n)
- Di MiniZinc, ini bisa didefinisikan secara sederhana sebagai masalah kendala berikut
array[int] of int: prices = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8]; var int: buy; var int: sell; var int: profit = prices[sell] - prices[buy]; constraint sell > buy; constraint profit > 0; solve maximize profit;
Contoh 2: membuat 0 dengan penjumlahan/pengurangan bilangan tertentu (masalah kepuasan)
- 'Bisakah memilih tiga angka dari daftar, lalu menambah atau menguranginya sehingga hasilnya menjadi 0?'
- Yang dicari bukan nilai optimal, melainkan sekadar solusi yang memenuhi
- Pada constraint solver, ini bisa dinyatakan sebagai berikut
include "globals.mzn"; array[int] of int: numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8]; array[index_set(numbers)] of var {0, -1, 1}: choices; constraint sum(n in index_set(numbers)) (numbers[n] * choices[n]) = 0; constraint count(choices, -1) + count(choices, 1) = 3; solve satisfy;
Contoh 3: luas persegi panjang maksimum dalam histogram
- 'Dari histogram yang tinggi tiap batangnya diberikan, carilah luas persegi panjang terbesar yang bisa dibentuk'
- Secara tradisional perlu algoritme yang rumit dan banyak pengelolaan state
- Dengan kendala saja, solusinya bisa dijelaskan secara ringkas
array[int] of int: numbers = [2,1,5,6,2,3]; var 1..length(numbers): x; var 1..length(numbers): dx; var 1..: y; constraint x + dx <= length(numbers); constraint forall (i in x..(x+dx)) (y <= numbers[i]); var int: area = (dx+1)*y; solve maximize area; output ["(\(x)->\(x+dx))*\(y) = \(area)"]
Apakah pendekatan constraint solver memang lebih baik?
-
Dalam konteks wawancara, pendekatan ini punya kelemahan saat ditanya soal kompleksitas waktu
- Runtime constraint solver sulit diprediksi, dan umumnya lebih lambat daripada algoritme optimal yang dirancang khusus
- Tetapi ini tetap lebih baik daripada algoritme berkualitas rendah yang salah implementasi, dan kebanyakan programmer juga tidak mudah menulis solusi optimal dari nol setiap saat
-
Kekuatan sebenarnya adalah fleksibilitas saat menambahkan kendala baru
- Misalnya, pada contoh saham, jika diubah dari sekali transaksi menjadi beberapa kali beli-jual, kompleksitas algoritmenya langsung meningkat tajam
- Dalam model kendala MiniZinc, kebutuhan yang jauh lebih kompleks bisa diakomodasi hanya dengan sedikit perubahan kode
include "globals.mzn"; int: max_sales = 3; int: max_hold = 2; array[int] of int: prices = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8]; array [1..max_sales] of var int: buy; array [1..max_sales] of var int: sell; array [index_set(prices)] of var 0..max_hold: stocks_held; var int: profit = sum(s in 1..max_sales) (prices[sell[s]] - prices[buy[s]]); constraint forall (s in 1..max_sales) (sell[s] > buy[s]); constraint profit > 0; constraint forall(i in index_set(prices)) (stocks_held[i] = (count(s in 1..max_sales) (buy[s] <= i) - count(s in 1..max_sales) (sell[s] <= i))); constraint alldifferent(buy ++ sell); solve maximize profit; output ["buy at \(buy)\n", "sell at \(sell)\n", "for \(profit)"];
-
Contoh masalah kendala yang beredar online memang banyak berfokus pada puzzle seperti Sudoku, tetapi sebenarnya pendekatan ini lebih menarik dan praktis untuk masalah dengan business logic atau kebutuhan optimasi nyata
- Misalnya, ada juga peluang besar untuk menerapkan teknik optimasi tingkat lanjut seperti symmetry breaking
Penutup dan referensi
- Tulisan ini berasal dari newsletter mingguan penulis yang membahas sejarah perangkat lunak, metode formal, teknologi baru, dan teori rekayasa perangkat lunak
- Jika tertarik, Anda bisa berlangganan atau melihat situs utama penulis
- Buku baru penulis, "Logic for Programmers", juga sedang dirilis
2 komentar
Biasanya masalah algoritma punya batasan kompleksitas waktu/ruang, kan? Kalau diselesaikan dengan solver constraint, pada dasarnya yang bisa ditunjukkan cuma kemampuan mengubah soal menjadi formula constraint... jadi saya kurang yakin apakah itu benar-benar kemampuan yang dibutuhkan di pekerjaan nyata...
Komentar Hacker News
Masalah terbesar dengan pertanyaan wawancara ala Leetcode adalah kita tidak bisa meminta klarifikasi tambahan; karena cara berpikirku berbeda dari yang umum, Leetcode terasa bergantung pada menghafal jawaban. Kalau soalnya punya konteks yang cukup, aku bisa membangun pemahaman yang realistis sehingga tidak masalah, tetapi kebanyakan penjelasannya kurang sehingga aku bahkan tidak bisa benar-benar memahami persoalannya. Karena itu belakangan ini aku langsung menolak tahap wawancara Leetcode atau wawancara otomatis berbasis AI. Tugas take-home atau wawancara 1:1 dengan screen sharing masih oke. Kalau situs Leetcode punya penjelasan dan jawaban yang benar-benar bagus, belajar mandiri juga pasti jauh lebih mudah, tetapi kenyataannya sangat sulit. Ini bukan cuma soal kemampuan; ini lebih soal kecocokan antara cara berpikirku dan jenis masalahnya. Terus disuruh mengerjakan soal pilihan tetap tanpa bisa bertanya terasa seperti sistem yang memang dirancang supaya gagal, terutama untuk masalah AI/Leetcode yang dipakai di tahap pra-wawancara. Untuk wawancara dengan manusia sungguhan, di mana ada tanya jawab, menurutku itu jauh lebih baik.
Wawancara LC(Leetcode) itu seperti menguji kecepatan lari 100 meter yang sudah dilatih, sedangkan pekerjaan nyata lebih mirip maraton panjang yang penuh berhenti dan lanjut lagi. Meski begitu, kalau sekarang ingin mendapat gaji tinggi di perusahaan besar seperti SMEGMA, ya harus memainkan game ini. Misalnya, aku pernah membuat engine game 2D sendiri, tetapi kurasa aku tetap tidak akan lolos wawancara LC yang menuntutmu menaklukkan beberapa soal hard sambil salto balik. Aku sudah menerima kenyataan itu. Engine yang kubuat
Tidak semuanya selesai hanya dengan menghafal solusi; meski hafal, kamu bisa tetap mentok di pertanyaan lanjutan. Tapi kalau kamu sudah hafal dan tetap bisa menjawab pertanyaan lanjutannya dengan baik, menurutku berarti kamu memang tidak bermasalah dengan soal bergaya Leetcode. Kemampuan memecahkan masalah pada dasarnya adalah kemampuan pattern matching, dan semakin banyak pola yang kamu kenal, semakin tinggi kemampuanmu. Sekarang GPT juga bisa menyelesaikan soal dan menjelaskannya, jadi kemampuan seperti ini jadi lebih mudah dipelajari. Menurutku lebih baik dipelajari mulai sekarang.
Sangat setuju. Dalam wawancara terbaruku, aku mendapat nilai tertinggi untuk tugasnya dan para engineer serta CEO juga memberi penilaian positif, tetapi lalu CTO tiba-tiba memintaku menjalani live coding interview, dan akhirnya aku tetap ditolak. Sebelas minggu proses wawancara jadi sia-sia. Menyebalkan sekali bahwa proses bodoh seperti ini masih ada. Demo/tugas yang kukerjakan ada di sini, tautan monumental dan hasilnya, dan kode GitHub
Bukankah ketidakmampuan untuk mengajukan pertanyaan yang jelas justru kemampuan yang sebenarnya ingin diuji? Melihat bagaimana kandidat mendekati pemecahan masalah. Kalau orang dipaksa selalu mendekati masalah secara tegas tanpa ambiguitas, semua software justru akan menjadi lebih rumit dan berantakan. Yang benar-benar sulit bukan menulis baris kode, melainkan proses memecahkan masalahnya.
Tempat-tempat yang pernah mewawancaraiku memang memberi satu atau dua soal LC, tetapi kalau aku meminta penjelasan, mereka langsung mengubahnya menjadi percakapan real-time sambil coding. Kekurangannya, tekanan psikologis live coding jadi lebih besar.
Saat menerima soal wawancara seperti ini, rasanya mereka tidak ingin kita 'menggunakan' constraint solver, melainkan 'menulis sendiri' constraint solver yang cocok untuk masalah terbatas itu.
Betul, dan karena itu menurutku pendekatan wawancara seperti ini pada dasarnya kikuk. Dalam situasi engineering nyata, kamu bisa ngopi, membaca paper, buka-buka referensi, jalan-jalan sambil berpikir, dan memakai alat yang sudah ada seperti constraint solver atau LLM untuk menyelesaikan masalah 100%. Tetapi dalam situasi wawancara, rasanya 0% pun tidak bisa. Aku bahkan tidak pernah terpikir ingin masuk ke tempat yang mewawancarai seperti itu.
Menurutku benar sekali. Sebagian besar masalah NP bisa diubah menjadi masalah constraint. Apakah constraint solver benar-benar jawaban yang tepat sangat bergantung pada domain penerapannya. Dan dalam konteks wawancara, hampir pasti bukan jawaban yang tepat. Solver seperti ini sering kali jauh lebih lambat daripada dynamic programming sederhana.
Di beberapa wawancara perusahaan mungkin memang begitu, tetapi tidak semuanya. Secara umum, LC dipakai dalam wawancara sering kali hanya karena satu alasan: proses perekrutan yang tidak efisien. Bahkan orang-orang yang terlibat pun tahu sistemnya perlu dirombak, tetapi mereka tidak punya kuasa atau terlalu tersebar untuk mengubahnya. Di perusahaan besar, HR kadang memutar pertanyaan yang sama ke berbagai tim demi 'standardisasi', dan perusahaan kecil tidak punya waktu menyiapkan soal sendiri jadi asal ambil dari internet. Dalam situasi seperti ini, bahkan interviewer teknis pun sering kritis terhadap wawancara LC, sehingga mereka sebenarnya berusaha menemukan kandidat yang menonjol. Di lingkungan seperti itu, menunjukkan bahwa kamu punya minat atau pengetahuan tentang constraint solver saja sering kali sudah memberi nilai cukup tinggi.
Kalau seseorang menyelesaikan soal LC hard dengan constraint solver lalu tidak direkrut, berarti interviewer-nya sendiri yang bodoh. Orang yang tahu apa itu constraint solver, apalagi bisa mendefinisikan masalah lalu memakainya, sangat jarang. Aku sendiri pernah memakainya saat tingkat tiga kuliah, dan hanya menulis constraint-nya saja sudah cukup rumit sampai bikin pusing.
Bagian ini ada benarnya dan ada tidaknya juga. Aku pernah mengajukan pertanyaan seperti ini dalam wawancara, dan kalau kandidat terpikir constraint solver, aku memberinya nilai bagus. Dalam engineering nyata, constraint solver cenderung diremehkan padahal itu menunjukkan kemampuan menghasilkan jawaban yang tepat dengan cepat. Tentu setelah itu aku tetap akan memberi pertanyaan whiteboard lanjutan untuk mengukur kemampuan coding yang sebenarnya. Tetapi menjawab dengan constraint solver itu sendiri menurutku bukan hal yang buruk.
Insight yang keren, tetapi menurutku kurang cocok dengan wawancara dunia nyata. Inti dari masalah seperti ini adalah menguji apakah kandidat bisa 'benar-benar berpikir'. Menyelesaikannya hanya sebagai constraint tidak menunjukkan itu; yang tampak hanya tingkat pengalaman dan pengetahuannya.
Pewawancara cenderung sering memberi soal "Array String" dari Leetcode "Top Interview 150". Dari sudut pandangku sebagai backend Python developer, soal-soal itu terasa jauh dari pekerjaan sehari-hari. Kebanyakan menuntut algoritma operasi array in-place, yang biasanya baru penting di bahasa berorientasi performa seperti C atau Rust. Justru soal tipe "Hashmap" lebih berguna untuk menunjukkan pemanfaatan alat yang sesuai dengan bahasa. Selain itu, banyak juga soal yang tingkat kesulitannya tidak terkalibrasi; soal berlabel "easy" seperti Majority Element pada praktiknya menuntut algoritma historis seperti Boyer–Moore, jadi sulit dianggap benar-benar "mudah".
Putaran terakhir yang kulihat baru-baru ini di Meta murni seperti proses mengecek seberapa banyak seseorang sudah menghafal soal-soal spesifik milik mereka. Jadi kalau kamu menjawab berbeda dari jawaban buku teks, mereka justru bingung. Rasanya 'kepintaran' itu sendiri tidak terlalu penting.
Algoritma DP bottom-up memang butuh sedikit pemikiran, tetapi kebanyakan masalah bisa diselesaikan dengan pendekatan top-down (rekursi + memoization). Misalnya, masalah coin change bisa diselesaikan lebih baik dengan pencarian A*. Namun di dunia nyata, kebanyakan programmer hampir tidak pernah benar-benar perlu memakai algoritma seperti ini. Yang jauh lebih penting adalah menyadari ketika tanpa sengaja kamu menulis kode dengan kompleksitas waktu O(n^2). Jika melihat accidentallyquadratic.tumblr.com, bahkan orang-orang sangat kompeten di proyek terkenal pun sering melakukan kesalahan seperti ini. Jadi kemampuan membuat algoritma dalam tes terpisah dari kemampuan menangkap kesalahan algoritmik saat bekerja sungguhan.
Saat menguji kemampuan problem solving dalam wawancara, aku lebih mementingkan proses berpikir, cara berkomunikasi, dan kemampuan memecah masalah. Jauh lebih penting menyiapkan pertanyaan yang tingkat kesulitannya bisa disesuaikan agar semua kandidat punya kesempatan menunjukkan kemampuannya. Kalau seseorang langsung meneriakkan jawaban yang kebetulan terlintas, atau malah benar-benar buntu, sejujurnya dari sudut pandang interviewer tidak banyak hal yang bisa dipelajari dengan cepat dari situ. Karena itu, pertanyaan wawancara berbasis problem solving bisa sangat berguna, tetapi sayangnya di dunia nyata sering tidak dipakai dengan baik.
Soal-soal seperti ini sebenarnya bukan menguji 'kepintaran', melainkan seberapa banyak kamu sudah menghafal sekitar selusin pola baku. Hampir semua kandidat akhirnya ditentukan lolos atau tidak berdasarkan hafalan yang sudah mereka persiapkan, bukan kemampuan pemecahan masalah kreatif mereka. Soal LeetCode terasa terlalu gamified sampai akhirnya hanya jadi alat untuk mengukur kemauan bersiap.
Kebanyakan wawancara terasa seperti memberi soal dengan asumsi, 'kalau pasien diabetes tidak bisa mensintesis insulin sendiri di rumah, berarti dia curang dalam game kehidupan'. Istriku menyuntik insulin saat gula darahnya naik; begitu pula untuk masalah constraint, ya wajar memakai solver. Kalau perusahaan itu bukan pembuat software constraint solver, aku tidak paham kenapa mereka harus memulai dari asumsi bahwa 'software seperti ini tidak ada' lalu memintamu membangunnya lagi dari nol.
Intinya bukan menguji kemampuan mensintesis insulin saat krisis, melainkan tes bakat awal untuk menilai apakah kamu bisa menghafal materi dalam seminggu lalu melafalkannya dengan baik saat phone screen.
Kalau kamu bisa menemukan cara menyelesaikan masalah secara efisien dengan constraint solver, membuat dua
forloop dan satu fungsi rekursif pembantu untuk menyelesaikan soal mainan tentu mudah saja.(Tidak ada isi yang bermakna)
Untuk sedikit membela coding test, kebanyakan orang yang bahkan tidak bisa menyelesaikan soal DP sederhana memang sering kali kurang kuat juga dalam pekerjaan nyata. Tentu ada pengecualian, tetapi setidaknya itulah pengalamanku.
Setiap kali bahasa pemrograman constraint dibahas, kita harus menyebut Håkan Kjellerstrand. Dia mengelola situs luar biasa yang mengumpulkan banyak contoh dan soal, termasuk MiniZinc. hakank minizinc
Dulu sekali, saat aku masih hijau dan belum pernah belajar constraint solver di program computer science kampus, aku menemukan masalah ini ketika seorang teman memintaku membuat aplikasi penjadwalan klub olahraga. Awalnya terlihat mudah, tetapi ketika benar-benar kucoba, aku bahkan tidak sadar sedang berhadapan dengan masalah besar. Baru belakangan aku menyadari itu pelajaran bagus tentang kesombonganku sendiri, dan pengalaman itu sangat membantu saat berdiskusi tentang jadwal/deadline/ekspektasi.
Mungkin ini pertanyaan pemula, tetapi apakah ini tidak bisa lebih mudah diselesaikan dengan 'optimisasi linear' daripada constraint solver? Dari pengalaman menulisnya sendiri, kelebihan optimisasi linear adalah konflik antaraturan bisa diperlakukan sebagai bobot, sehingga solusi dicari ke arah yang meminimalkan 'efek samping'.
Dua puluh lima tahun lalu saat masih SMA, ketika baru mulai belajar TI-Basic dan VB6, aku kerja paruh waktu di restoran burger dan mendengar manajer mengeluh tiap minggu susah menyusun jadwal karyawan. Aku langsung bilang, "Saya lumayan paham komputer, saya buatkan program penjadwalan ya!" Tak lama kemudian aku sadar betapa sulitnya membuat scheduler, lalu segera menyerah.
Maksud penulis adalah, "kalau soal seperti ini dipakai dalam wawancara, lalu kandidat bertanya 'berapa kompleksitas runtime algoritma ini?', pewawancara akan kehabisan jawaban". Artinya, constraint solver juga bukan jawaban untuk soal Leetcode hard jika ia tidak bisa menyelesaikannya cukup cepat. Kalau kebutuhan runtime-nya longgar, pendekatan sederhana mungkin cukup, tetapi menemukan solusi yang efisien adalah bagian besar dari keseluruhan tantangannya.
Constraint solver? Ide bagus dan aku pernah mendengarnya, tetapi dalam wawancara kenyataannya mereka cuma ingin melihatmu mengimplementasikannya sendiri dengan Python sambil mengamati alur pikirmu. (Rasanya hampir mustahil meyakinkan mereka untuk memakai constraint solver dalam wawancara.)
Aku penasaran, apakah kamu benar-benar pernah mengatakan ini ke interviewer, atau ini cuma perkiraanmu?
import z3Setelah menyelesaikannya dengan DP (dynamic programming), lalu berkata "sekarang saya akan coba juga dengan constraint solver", itu langsung diterima kerja.
Kekuatan nyata constraint solver adalah seberapa mudah ia beradaptasi dengan 'kebutuhan baru'. Aku juga merasakan langsung manfaat solver umum seperti ini saat mengerjakan optimisasi data center di Google, karena dia bisa menyesuaikan diri secara fleksibel saat requirement berubah.