Merhabalar bu yazımın konusu bazen matematik problemlerinde denk geldiğimiz hatalı bir sayacın bir hanesini hatalı gösterdiğinde sayaç kaçı gösterirdi gibi bir problemi çözmeye yönelik (tam ifade edemedim ama soru aşağıda var). Üniversiteye hazırlanan kuzenimin gittiği hazırlık kursunda sorulan ödüllü soruyu çözmek amacıyla geliştirmiş olduğum uygulama benzeri problemlere de uyarlanabilir. Soru kısaca şu şekilde:
Bir aracın kilometre sayacı 4 rakamına her geldiğinde atlayarak 5 rakamına geçiyor. Bu araç 1412 km yol yaptığında sayaç kaç değerini gösterir?
Ben bu probleme uygun olarak sadece dört basamaklı sayıları çözecek şekilde uyarladım ancak farklı problemlere uyarlanabilir. Program basitçe şöyle işliyor:
int k=0, i=0; // hatalı ve gerçek sayı sayaç değişkenleri
int t1=0, t2=0; //hatalı rakamı sadece bir kez dikkate almamızı sağlayacak değişkenler
// hatalı sayının haneleri
char h1 = '0', h2 = '0', h3 = '0', h4 = '0';
Programda iki tane sayaç oluşturuyoruz. Birisi gerçek sayıyı tutarken diğeri hatalı sayıyı tutacak. Hatalı sayıyı tutan değişkene i, gerçek sayıyı tutan değişkene de k diyelim.
private bool CozBakalim(int kacakadar, int hangirakam)
{
t2 = t1; // t2 önceki i değerini gösteriyor.
i++;
t1 = i; // t1 o anki i değerini gösteriyor.
k++;
Oluşturduğumuz i değişkenini 10'un üstelleri aralığına alıp ayrı ayrı değerlendirerek sayının her bir basamağında hatalı rakama rastlanıp rastlanılmadığına bakıyoruz. Eğer rakama rastlanırsa hatalı rakamın bulunduğu basamak değeri kadar hatalı sayı değişkeni k artırılıyor. Mesela 1 ile 10 arasındaki sayıların basamaklarında aranan rakam var mı yok mu. 10 ile 100 arasındaki sayıların basamaklarında aranan rakam var mı yok mu. 100 ile 1000 arasındaki sayıların basamaklarında aranan rakam var mı yok mu... gibi.
Basamaklarda değer arama işini ise basitçe ToString() metoduyla i değişkenini stringe çevirdikten sonra Contains() metodu ile hatalı rakamı içerip içermediğine bakarak gerçekleştirdim.
Tabi burada bir sorun var. Birler basamağı için aslında sorun yok ama diğer basamaklarda örneğin onlar basamağında, yüzler ya da binler basamağında hatalı rakama gelindiğinde ne olacak? Sayaç değeri her bir tikte bir artıyor. Onlar basamağında hatalı rakam geçene kadar hatalı rakamın bulunduğu haneyi 10'ar artırırsak sayımıza fazladan 90 eklemiş oluruz ve yanlış bir sonuca ulaşırız. Bunu engellemek için iki yeni değişken oluşturuyoruz ve gerçek sayı değişkenimizin bir üstüne bir de altına yerleştirerek ilgili hanede hatalı rakamın önceki ve sonraki durumlarda bulunup bulunmadığına bakıyoruz. Yani kısaca programımıza hatalı rakamı sadece bir kere dikkate al ve haneyi bir kere artır diyoruz.
if (i > 0 && i < 10)
{
h1 = i.ToString()[0];
if (h1.ToString().Contains(rak)) i++;
}
if (i > 10 && i < 100)
{
h2 = i.ToString()[0];
h1 = i.ToString()[1];
// t2 ve t1'in ilgili basamak değerleri birbirinden farklıysa ve ilgili hane hatalı rakamı içeriyorsa işlem yap
if (t2.ToString()[0] != t1.ToString()[0] && h2.ToString().Contains(rak)) i += 10;
if (h1.ToString().Contains(rak)) i++;
}
if (i > 100 && i < 1000)
{
h3 = i.ToString()[0];
h2 = i.ToString()[1];
h1 = i.ToString()[2];
if (t2.ToString()[0] != t1.ToString()[0] && h3.ToString().Contains(rak)) i += 100;
if (t2.ToString()[1] != t1.ToString()[1] && h2.ToString().Contains(rak)) i += 10;
if (h1.ToString().Contains(rak)) i++;
}
if (i > 1000)
{
h4 = i.ToString()[0];
h3 = i.ToString()[1];
h2 = i.ToString()[2];
h1 = i.ToString()[3];
if (t2.ToString()[1] != t1.ToString()[1] && h3.ToString().Contains(rak)) i += 100;
if (t2.ToString()[2] != t1.ToString()[2] && h2.ToString().Contains(rak)) i += 10;
if (h1.ToString().Contains(rak)) i++;
}
İstenen sayıya gelinmediyse metot false döndürüyor.
return false;
Uygulamanın algoritması bu şekilde umarım açıklayıcı olmuştur. Uyuglamanın kaynak kodlarını buradan indirebilirsiniz. Bir sonraki paylaşımda görüşmek üzere hoşkalın :)
Bir aracın kilometre sayacı 4 rakamına her geldiğinde atlayarak 5 rakamına geçiyor. Bu araç 1412 km yol yaptığında sayaç kaç değerini gösterir?
Ben bu probleme uygun olarak sadece dört basamaklı sayıları çözecek şekilde uyarladım ancak farklı problemlere uyarlanabilir. Program basitçe şöyle işliyor:
int k=0, i=0; // hatalı ve gerçek sayı sayaç değişkenleri
int t1=0, t2=0; //hatalı rakamı sadece bir kez dikkate almamızı sağlayacak değişkenler
// hatalı sayının haneleri
char h1 = '0', h2 = '0', h3 = '0', h4 = '0';
private bool CozBakalim(int kacakadar, int hangirakam)
{
t2 = t1; // t2 önceki i değerini gösteriyor.
i++;
t1 = i; // t1 o anki i değerini gösteriyor.
k++;
char rak = Convert.ToChar(hangirakam-1);
Basamaklarda değer arama işini ise basitçe ToString() metoduyla i değişkenini stringe çevirdikten sonra Contains() metodu ile hatalı rakamı içerip içermediğine bakarak gerçekleştirdim.
Tabi burada bir sorun var. Birler basamağı için aslında sorun yok ama diğer basamaklarda örneğin onlar basamağında, yüzler ya da binler basamağında hatalı rakama gelindiğinde ne olacak? Sayaç değeri her bir tikte bir artıyor. Onlar basamağında hatalı rakam geçene kadar hatalı rakamın bulunduğu haneyi 10'ar artırırsak sayımıza fazladan 90 eklemiş oluruz ve yanlış bir sonuca ulaşırız. Bunu engellemek için iki yeni değişken oluşturuyoruz ve gerçek sayı değişkenimizin bir üstüne bir de altına yerleştirerek ilgili hanede hatalı rakamın önceki ve sonraki durumlarda bulunup bulunmadığına bakıyoruz. Yani kısaca programımıza hatalı rakamı sadece bir kere dikkate al ve haneyi bir kere artır diyoruz.
{
h1 = i.ToString()[0];
if (h1.ToString().Contains(rak)) i++;
}
if (i > 10 && i < 100)
{
h2 = i.ToString()[0];
h1 = i.ToString()[1];
// t2 ve t1'in ilgili basamak değerleri birbirinden farklıysa ve ilgili hane hatalı rakamı içeriyorsa işlem yap
if (t2.ToString()[0] != t1.ToString()[0] && h2.ToString().Contains(rak)) i += 10;
if (h1.ToString().Contains(rak)) i++;
}
if (i > 100 && i < 1000)
{
h3 = i.ToString()[0];
h2 = i.ToString()[1];
h1 = i.ToString()[2];
if (t2.ToString()[0] != t1.ToString()[0] && h3.ToString().Contains(rak)) i += 100;
if (t2.ToString()[1] != t1.ToString()[1] && h2.ToString().Contains(rak)) i += 10;
if (h1.ToString().Contains(rak)) i++;
}
if (i > 1000)
{
h4 = i.ToString()[0];
h3 = i.ToString()[1];
h2 = i.ToString()[2];
h1 = i.ToString()[3];
if (t2.ToString()[1] != t1.ToString()[1] && h3.ToString().Contains(rak)) i += 100;
if (t2.ToString()[2] != t1.ToString()[2] && h2.ToString().Contains(rak)) i += 10;
if (h1.ToString().Contains(rak)) i++;
}
İstenen sayıya gelindiğinde metot true döndürerek işlemi bitiriyor.
if (k >= kacakadar) return true;return false;
}
Uygulamanın algoritması bu şekilde umarım açıklayıcı olmuştur. Uyuglamanın kaynak kodlarını buradan indirebilirsiniz. Bir sonraki paylaşımda görüşmek üzere hoşkalın :)

Hiç yorum yok:
Yorum Gönder