Konu Başlıkları Gizle
Merhaba,
Bir süredir bu yazıyı yazmayı düşünüyordum, artık vaktin geldiğini düşünüyorum.
Her şey 2019'da, üniversite hayatımın 2. senesinde yurttaki oda arkadaşımın "Gel de şu problemi çözelim!" tarzı bir çağrısıyla beni bu harika beyin sporuna davet etmesiyle başladı.
Matematiğe olan sevgim bir sonraki aşamaya ulaşacaktı...
İyi okumalar dilerim.
Yapılması gereken basit, değil mi? Verilen sayıları toplayacağız işte. E, sayılar nasıl veriliyor peki? Girdi olarak.
Girdinin verilme şekli yarışmadan yarışmaya, platformdan platforma değişebiliyor ama genelde konsoldan veriliyormuş gibi oluyor (standard input). Çok iyi anlatamadım, birkaç dille örneklendireyim: C'de
[CODE title="Girdi örneği"]5
-5 7 1 1242 3[/CODE]
Ben daha çok bu sistemin tercih edildiğini gördüm, örneğin Codeforces'ta işler bu şekilde yürüyor. Yarışmacının, problemi çözerek elde ettiği cevabı da çıktı olarak sunması bekleniyor: C'de
Bir başka yöntem de şu: Girdiyi okuma kısmı yarışmacıya bırakılmıyor, direkt bir fonksiyonun implemente edilmesi isteniyor:
[CODE lang=cpp]long long sayilarin_toplami(int n, const vector<int>& sayilar) {
// Gerekli işlemleri yapıp sayıların toplamını döndürün.
}[/CODE]
Girdi, sistem tarafından okunuyor ve problemi çözen
Hadi, artık çözelim ilk problemimizi! Hızından ve hâlihazırda sunduğu faydalı veri yapılarından ötürü daha çok C++ tercih ediliyor CP'de, hâliyle ben de C++'çıyım.
[CODE lang="cpp" title="Çözüm kodu"]#include <iostream>
using namespace std; // CP'de tercih ediliyor
int main() {
int n;
cin >> n; // Önce sayı adedini okuyoruz.
// Sayıların toplamını bir değişkende tutuyoruz.
long long toplam = 0;
// Şimdi sıra sayıları okumaya geldi.
for (int i = 0; i < n; i++) {
int sayi;
cin >> sayi; // (i+1)'inci sayıyı okuyoruz.
// Okuduğumuz gibi toplama dahil ediyoruz.
toplam += sayi;
}
cout << toplam << "\n";
}[/CODE]
Gördüğünüz üzere her şey, normalde elimizle yapacaklarımızı bilgisayara gerekli talimatlarla yaptırmaktan ibaret.
Bir probleme daha bakalım:
[CODE lang=cpp title="Çözüm kodu"]#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int sayilar[n]; // Sayıları hafızada tutmak için n boyutlu bir dizi oluşturuyoruz.
int en_buyuk_pozisyon = 0; // En büyük sayının pozisyonunu bir değişkende tutuyoruz, ilk pozisyon ile başlatıyoruz.
for (int i = 0; i < n; i++) {
cin >> sayilar;
// Okuduğumuz gibi gerekli işlemleri yapıyoruz.
// > yazsak en soldakini alırdık. >= yazınca en sağdakini alıyoruz.
if (sayilar >= sayilar[en_buyuk_pozisyon]) {
en_buyuk_pozisyon = i;
}
}
cout << en_buyuk_pozisyon << "\n";
}[/CODE]
Hadi, bir tane daha:
Birçok yolla çözülebilen bir problem fakat bir veri yapısı olan
[CODE lang="cpp" title="Çözüm kodu"]#include <iostream>
#include <set>
using namespace std;
int main() {
int n;
cin >> n;
set<int> farkli_sayilar; // Her sayıdan bir adet tutan veri yapısı, küme işte
for (int i = 0; i < n; i++) {
int sayi;
cin >> sayi;
farkli_sayilar.insert(sayi); // Sayıyı set'e ekliyoruz.
}
// Set'te kaç adet sayı olduğunu yazdırıyoruz.
cout << farkli_sayilar.size() << "\n";
}[/CODE]
Bu son:
[CODE lang="cpp" title="Çözüm kodu"]#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int cevap = 1;
const int mod = 1e9 + 7;
for (int i = 2; i <= n; i++) {
cevap = (long long)cevap * i % mod;
}
cout << cevap << "\n";
}[/CODE]
Tahmin edebileceğiniz üzere çok daha zor problemler de var.
Algoritmik problemleri, lisede çözdüğümüz matematik sorularının değişken parametreli hâlleri olarak düşünebilirsiniz. Tabii kapsam sadece matematikle sınırlı değil. Problemi çözmek için yazdığınız kod, olası tüm parametre kombinasyonları için doğru sonucu veriyor olmalı.
Yarışmaların bu kadar üzerinde durduğuma bakmayın. Yarışmalarda iyi bir derece elde etmek için yarışma dışında da bol bol pratik yapmanız gerekiyor. En az yarışmalar kadar eğlenceli oluyor bu süreç hatta benim için yarışmalardan daha eğlenceli olabiliyor.
İşin bir şimdiye kadar üzerinde durduğum rekabet kısmı var, bir de şu: Ortak amaca sahip arkadaşlar edindim ki bu benim için her şeyden daha değerli. CP, hayatıma birçok açıdan fayda sağlamış oldu. Minnettarlığımı tarif edemem.
"Nasıl yazılım öğrenirim?"
İşte bu sorunun cevabını verdi benim için CP. Problem çözmek için yazılım öğrenmem gerekiyordu; ben de araştıra araştıra, problem çöze çöze öğrendim.
Bu arada, gelişmek bol bol zaman gerektiriyor. Çözemediğiniz zamanlar da olacak, yorulduğunuz zamanlar da. Merak etmeyin, herkes bu süreçlerden geçiyor; kimisi daha hızlı, kimisi daha yavaş. Ne var ki gelişmemek için sebep yok.
LeetCode'da ilk bakmanızı tavsiye ettiğim sayfa Problems sayfası:
Burada işin rekabet kısmı olmaksızın pratik yapmak için bol bol algoritmik problem var: Easy (Kolay), Medium (Orta) ve Hard (Zor) problemler. Mesela şu problemde verilen tam sayının tersten yazılışıyla aynı olup olmadığı sorulmuş.
Contest sayfasındaysa işin rekabet kısmı var. Yarışmalar düzenleniyor, herkesle aynı anda 2-3 saat içinde yaklaşık 5 problem çözmeye çalışıyorsunuz. Bu arada, yanlışım yoksa Problems sayfası, geçmiş yarışmalardaki problemleri barındırıyor.
Buradaki Problem Solving kısmında da güzel problemler var. "Problem problemdir, platform fark etmez." kafasıyla hareket edebilirsiniz.
CONTESTS sayfasında geçmiş ve gelecek tüm resmî Codeforces yarışmaları yer alıyor. Bunun yanı sıra,
2020'den 2021'in ortalarına kadar oldukça aktifmişim. Zamanında çok eğlenirdim burada, hayatsız gibi yarışmadan yarışmaya koşardım.
Bu platformda, normal yarışmaların yanı sıra CP'ye başlamak için birtakım temel düzeyde problem setleri bulunuyor, örneğin Algorithm Training Beginner Set. Diğer tüm setlere ve ayrıca yarışmalara Contest sayfasından ulaşabilirsiniz. Practice sayfasındaysa pratik yapmak için tekil problemler var.
Başka platformlar da mevcut ama bu kadarını yeterli buldum.
Bu yarışmalar son birkaç yıldır genellikle algoleague'de düzenleniyor.
Ayrıca bu kitabı hazırlayan Antti Laaksonen'in aynı zamanda CSES diye bir platformu var ve burada çeşitli algoritmalardan problemler barındıran bir problem seti var. Pratik yapmak için harika bir set yine.
Yazılıma biraz olsun ilginiz varsa sizi de competitive programming ile tanıştırmak amacıyla böyle bir yazı yazmak istedim. Bir problemle başlamanız yeterli, emin olun ki -umarım- devamı gelecektir çünkü gerçekten eğlenceli. : D
Aklınıza takılan bir şey olursa sorabilirsiniz.
Umarım yeterince yararlı bir içerik olmuştur. Okuduğunuz için teşekkürler, CP'li günler ve...
Bir süredir bu yazıyı yazmayı düşünüyordum, artık vaktin geldiğini düşünüyorum.
Her şey 2019'da, üniversite hayatımın 2. senesinde yurttaki oda arkadaşımın "Gel de şu problemi çözelim!" tarzı bir çağrısıyla beni bu harika beyin sporuna davet etmesiyle başladı.
Matematiğe olan sevgim bir sonraki aşamaya ulaşacaktı...
İyi okumalar dilerim.
Beyin sporu mu, nasıl yani?
Rekabetçi programlama veya daha çok bilinen (İngilizce) ismiyle competitive programming ve hatta kısaltmasıyla CP, temelde birkaç algoritmik problemin bir yarışma kapsamında sunulduğu bir rekabet/spor türü. Bu alandaki yarışmalara da "yazılım/programlama yarışması" diyebiliriz. CP problemlerini dilediğiniz bir programlama diliyle (C/C++, Python, Java vb.) gerekli algoritmaları kodlayarak sınırlı kaynaklarla (süre, hafıza...) çözmeniz beklenir yani aslında problemi bilgisayara çözdürmeniz gerekli. Bunun nedeniyse biz insanlara kıyasla bilgisayarların acayip hızlı olması ve büyük miktarda veriyle iş yapabilmesi. Kendi yapacaklarımızı gerekli talimatları bilgisayara vererek yaptırabilirsek hayat kolaylaşıyor.Algoritmik problem örnekleri
Basit bir tanesiyle başlayalım:n adet [-10⁹, 10⁹] aralığında tam sayı veriliyor. Bu sayıların toplamı nedir?
Yapılması gereken basit, değil mi? Verilen sayıları toplayacağız işte. E, sayılar nasıl veriliyor peki? Girdi olarak.
Girdinin verilme şekli yarışmadan yarışmaya, platformdan platforma değişebiliyor ama genelde konsoldan veriliyormuş gibi oluyor (standard input). Çok iyi anlatamadım, birkaç dille örneklendireyim: C'de
scanf, C++'ta scanf/cin, Python'da input kullanarak alıyoruz girdiyi. Problem açıklamasında girdinin hangi formatta verildiği de söyleniyor, örneğin:İlk satırda n veriliyor.
İkinci satırda aralarında birer boşluk olacak şekilde n adet sayı veriliyor.
[CODE title="Girdi örneği"]5
-5 7 1 1242 3[/CODE]
Ben daha çok bu sistemin tercih edildiğini gördüm, örneğin Codeforces'ta işler bu şekilde yürüyor. Yarışmacının, problemi çözerek elde ettiği cevabı da çıktı olarak sunması bekleniyor: C'de
printf, C++'ta printf/cout, Python'da print...Bir başka yöntem de şu: Girdiyi okuma kısmı yarışmacıya bırakılmıyor, direkt bir fonksiyonun implemente edilmesi isteniyor:
[CODE lang=cpp]long long sayilarin_toplami(int n, const vector<int>& sayilar) {
// Gerekli işlemleri yapıp sayıların toplamını döndürün.
}[/CODE]
Girdi, sistem tarafından okunuyor ve problemi çözen
sayilarin_toplami fonksiyonu, bu girdiler sağlanarak çağrılıyor. Bu sistemin tercih edildiği platformlardan birisi LeetCode. Codeforces'ın aksine LeetCode'da cevabı fonksiyon döndürdüğü için yarışmacıdan herhangi bir çıktı sunması da beklenmiyor. Sistem, fonksiyonun döndürdüğü cevabı değerlendiriyor. Tüm kodun bizden gizlenmiş kısmında girdi/çıktı ve değerlendirme işlemleri hallediliyor, böyle düşünebilirsiniz.Hadi, artık çözelim ilk problemimizi! Hızından ve hâlihazırda sunduğu faydalı veri yapılarından ötürü daha çok C++ tercih ediliyor CP'de, hâliyle ben de C++'çıyım.
[CODE lang="cpp" title="Çözüm kodu"]#include <iostream>
using namespace std; // CP'de tercih ediliyor
int main() {
int n;
cin >> n; // Önce sayı adedini okuyoruz.
// Sayıların toplamını bir değişkende tutuyoruz.
long long toplam = 0;
// Şimdi sıra sayıları okumaya geldi.
for (int i = 0; i < n; i++) {
int sayi;
cin >> sayi; // (i+1)'inci sayıyı okuyoruz.
// Okuduğumuz gibi toplama dahil ediyoruz.
toplam += sayi;
}
cout << toplam << "\n";
}[/CODE]
Gördüğünüz üzere her şey, normalde elimizle yapacaklarımızı bilgisayara gerekli talimatlarla yaptırmaktan ibaret.
Bir probleme daha bakalım:
n adet [-10⁹, 10⁹] aralığında tam sayı veriliyor. En büyük sayı nerededir? Birden fazla en büyük sayı varsa sonuncunun yerini söyleyin.
[CODE lang=cpp title="Çözüm kodu"]#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int sayilar[n]; // Sayıları hafızada tutmak için n boyutlu bir dizi oluşturuyoruz.
int en_buyuk_pozisyon = 0; // En büyük sayının pozisyonunu bir değişkende tutuyoruz, ilk pozisyon ile başlatıyoruz.
for (int i = 0; i < n; i++) {
cin >> sayilar;
// Okuduğumuz gibi gerekli işlemleri yapıyoruz.
// > yazsak en soldakini alırdık. >= yazınca en sağdakini alıyoruz.
if (sayilar >= sayilar[en_buyuk_pozisyon]) {
en_buyuk_pozisyon = i;
}
}
cout << en_buyuk_pozisyon << "\n";
}[/CODE]
Hadi, bir tane daha:
n adet [-10⁹, 10⁹] aralığında tam sayı veriliyor. Toplam kaç adet farklı sayı vardır?
Birçok yolla çözülebilen bir problem fakat bir veri yapısı olan
set'in kullanım örneğini göstereyim:[CODE lang="cpp" title="Çözüm kodu"]#include <iostream>
#include <set>
using namespace std;
int main() {
int n;
cin >> n;
set<int> farkli_sayilar; // Her sayıdan bir adet tutan veri yapısı, küme işte
for (int i = 0; i < n; i++) {
int sayi;
cin >> sayi;
farkli_sayilar.insert(sayi); // Sayıyı set'e ekliyoruz.
}
// Set'te kaç adet sayı olduğunu yazdırıyoruz.
cout << farkli_sayilar.size() << "\n";
}[/CODE]
Bu son:
Verilen n doğal sayısı için n!'in 10⁹ + 7'ye bölümünden kalanı bulun.
[CODE lang="cpp" title="Çözüm kodu"]#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int cevap = 1;
const int mod = 1e9 + 7;
for (int i = 2; i <= n; i++) {
cevap = (long long)cevap * i % mod;
}
cout << cevap << "\n";
}[/CODE]
Tahmin edebileceğiniz üzere çok daha zor problemler de var.
Algoritmik problemleri, lisede çözdüğümüz matematik sorularının değişken parametreli hâlleri olarak düşünebilirsiniz. Tabii kapsam sadece matematikle sınırlı değil. Problemi çözmek için yazdığınız kod, olası tüm parametre kombinasyonları için doğru sonucu veriyor olmalı.
Tamam, olayı ne competitive programming'in peki?
Kendi adıma konuşmam gerekirse ben yazılımı CP sayesinde sevdim, gerçekten. Bugünlerimi, 2019'daki o CP ile tanıştığım ilk günlerime borçluyum. CP, zaten matematiğe ilgisi olan bana kod yazmam için muhteşem bir amaç sundu:Kodlamayı ve algoritmaları öğren ve bu esnada geliş, sonra yarışmalarda başkalarıyla yarış.
Yazılım öğrenmem için o kadar eğlenceli bir amaçtı ki bu, 5 yıl oldu, hâlâ daha bayılırım CP'ye. Zaman geçtikçe önceden çözemediğim problemleri çözebilir hâle geliyor, her problem çözdüğümde daha da seviniyor, yarışmalarda rekabet açlığımı giderip duruyordum. 5 yıl az bir süre değil, hayata bakış açım bile değişti. Algoritmik düşünce yapısı kafama işledi.
Yarışmaların bu kadar üzerinde durduğuma bakmayın. Yarışmalarda iyi bir derece elde etmek için yarışma dışında da bol bol pratik yapmanız gerekiyor. En az yarışmalar kadar eğlenceli oluyor bu süreç hatta benim için yarışmalardan daha eğlenceli olabiliyor.
İşin bir şimdiye kadar üzerinde durduğum rekabet kısmı var, bir de şu: Ortak amaca sahip arkadaşlar edindim ki bu benim için her şeyden daha değerli. CP, hayatıma birçok açıdan fayda sağlamış oldu. Minnettarlığımı tarif edemem.
"Nasıl yazılım öğrenirim?"
İşte bu sorunun cevabını verdi benim için CP. Problem çözmek için yazılım öğrenmem gerekiyordu; ben de araştıra araştıra, problem çöze çöze öğrendim.
Bu arada, gelişmek bol bol zaman gerektiriyor. Çözemediğiniz zamanlar da olacak, yorulduğunuz zamanlar da. Merak etmeyin, herkes bu süreçlerden geçiyor; kimisi daha hızlı, kimisi daha yavaş. Ne var ki gelişmemek için sebep yok.
Nerede yapılıyor bu competitive programming?
Çeşitli platformlar mevcut, onları teker teker paylaşayım:LeetCode
CP'ye ilk kez başlayacaklar için ideal çünkü görece basit problemler var LeetCode'da, arayüzü de hoş. Özünde mülakat problemleri odaklı bir platform aslında ama CP için de kullanılıyor gayet.LeetCode'da ilk bakmanızı tavsiye ettiğim sayfa Problems sayfası:
Contest sayfasındaysa işin rekabet kısmı var. Yarışmalar düzenleniyor, herkesle aynı anda 2-3 saat içinde yaklaşık 5 problem çözmeye çalışıyorsunuz. Bu arada, yanlışım yoksa Problems sayfası, geçmiş yarışmalardaki problemleri barındırıyor.
HackerRank
Sanırsam HackerRank'te de eskiden yarışmalar vardı fakat artık yapılmıyor gibi. Çeşitli şirketler mülakat için tercih ediyor yine de.
Codeforces
Codeforces, asıl CP'cilerin buluştuğu en popüler platformlardan biri. CP asıl burada yapılıyor diyebilirim. Kitlesi çok geniş olduğu için sık sık yarışma düzenlenebiliyor. Yarışmaları düzenleyenler de birer CP'ci yani komüniteden birileri olunca bu sıklık gayet anlaşılır.
- GYM sayfasında kullanıcılar kendi yarışmalarını hazırlayabiliyor.
- PROBLEMSET sayfası Codeforces'ın resmî yarışmalarındaki tüm problemleri barındırıyor.
- EDU sayfasında belli başlı algoritmalar için eğitim odaklı anlatım ve problem çözüm videoları ve problemler mevcut.
2020'den 2021'in ortalarına kadar oldukça aktifmişim.
algoleague
Türkiye'nin ilk CP platformu diyebiliriz algoleague için. Doğal olarak burada daha çok Türkler takılıyor. Diğer platformlara göre daha yeni olduğu ve daha küçük bir kitlesi olduğu için o kadar sık yarışma düzenlenmiyor ancak CP ile tanışmak için ideal bir platform.
Başka platformlar da mevcut ama bu kadarını yeterli buldum.
Üniversitelerdeki öğrenci kulüplerinin düzenlediği yarışmalar
Ülkemizde İstanbul Teknik Üniversitesi, Orta Doğu Teknik Üniversitesi, Hacettepe Üniversitesi ve Boğaziçi Üniversitesi gibi belli başlı üniversitelerdeki CP'ye ilgili öğrenci kulüpleri her sene çeşitli ulusal algoritma yarışmaları düzenliyor. Üniversite hayatınızda bu yarışmalara katılmanızı kesinlikle tavsiye ederim.Bu yarışmalar son birkaç yıldır genellikle algoleague'de düzenleniyor.
Olimpiyatlar ve uluslararası yarışmalar
CP'de "daha ciddi" olarak nitelendirebileceğimiz yarışmalar ve olimpiyatlar var: TÜBİTAK olimpiyatları, IOI (liseliler için), ICPC (üniversiteliler için)... Esasen CP'ciler bunlara hazırlanıyor çünkü başarının asıl meyvesi bu tür etkinliklerde yeniyor. Benim bu kısımda pek tecrübem yok, o yüzden sadece bahsetmekle yetinebiliyorum. : D Lisede zaten CP'den veya olimpiyatlardan bihaberdim, üniversitedeyse ICPC'ye birkaç kere katıldım fakat pek bir başarı elde edemedim.Kaynaklar
Algoritmik problemleri çözebilmek için algoritmaları öğrenmek lazım tabii. İnternetten araştırarak öğrenmek de mümkün ama ben birkaç başlangıç noktası sunmak istedim.inzva Algorithm Program GitHub
inzva, Türkiye'deki üniversite öğrencilerini algoritmalar ve CP çatısı altında toplayan bir komünite. CP'nin yanı sıra yapay zeka tarafı da var. Paylaştığım bu GitHub reposunda çeşitli algoritmaların anlatıldığı dokümanların yanında pratik yapabileceğiniz geçmiş inzva yarışmaları mevcut. Bu yarışmalar da vaktinde HackerRank'te düzenlenmiş bu arada. Ben zamanında bu yarışmalardaki problemleri sabah akşam çözüyordum. Gelişimimin ilk aşamalarını inzva sayesinde katettiğimi rahatlıkla söyleyebilirim.Competitive Programmer’s Handbook
Oldukça kapsamlı bir CP kaynağı. Ben hiç açıp okumadım çünkü çok geç tanıştım ama önerilmeyecek bir tarafı yok, harika bir kaynak.Ayrıca bu kitabı hazırlayan Antti Laaksonen'in aynı zamanda CSES diye bir platformu var ve burada çeşitli algoritmalardan problemler barındıran bir problem seti var. Pratik yapmak için harika bir set yine.
USACO Guide
USACO yani ABD Bilgisayar Olimpiyatı'na hazırlanmak için oluşturulmuş bir platform. İlla olimpiyat kaynağı olarak değerlendirmeye gerek yok, CP kaynağı olarak da ele alabilirsiniz. Arayüzü harika. Direkt şu sayfadan başlayabilirsiniz incelemeye.Yazılıma biraz olsun ilginiz varsa sizi de competitive programming ile tanıştırmak amacıyla böyle bir yazı yazmak istedim. Bir problemle başlamanız yeterli, emin olun ki -umarım- devamı gelecektir çünkü gerçekten eğlenceli. : D
Aklınıza takılan bir şey olursa sorabilirsiniz.
Umarım yeterince yararlı bir içerik olmuştur. Okuduğunuz için teşekkürler, CP'li günler ve...